aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/auth/factotum/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/auth/factotum/key.c')
-rw-r--r--src/cmd/auth/factotum/key.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/cmd/auth/factotum/key.c b/src/cmd/auth/factotum/key.c
new file mode 100644
index 00000000..e2299b84
--- /dev/null
+++ b/src/cmd/auth/factotum/key.c
@@ -0,0 +1,217 @@
+#include "std.h"
+#include "dat.h"
+
+Ring ring;
+
+Key*
+keyiterate(int skip, char *fmt, ...)
+{
+ int i;
+ Attr *a;
+ Key *k;
+ va_list arg;
+
+ va_start(arg, fmt);
+ a = parseattrfmtv(fmt, arg);
+ va_end(arg);
+
+ for(i=0; i<ring.nkey; i++){
+ k = ring.key[i];
+ if(matchattr(a, k->attr, k->privattr)){
+ if(skip-- > 0)
+ continue;
+ k->ref++;
+ freeattr(a);
+ return k;
+ }
+ }
+ freeattr(a);
+ werrstr("no key found");
+ return nil;
+}
+
+Key*
+keylookup(char *fmt, ...)
+{
+ int i;
+ Attr *a;
+ Key *k;
+ va_list arg;
+
+ va_start(arg, fmt);
+ a = parseattrfmtv(fmt, arg);
+ va_end(arg);
+
+ for(i=0; i<ring.nkey; i++){
+ k = ring.key[i];
+ if(matchattr(a, k->attr, k->privattr)){
+ k->ref++;
+ freeattr(a);
+ return k;
+ }
+ }
+ freeattr(a);
+ werrstr("no key found");
+ return nil;
+}
+
+Key*
+keyfetch(Conv *c, char *fmt, ...)
+{
+ int i, tag;
+ Attr *a;
+ Key *k;
+ va_list arg;
+
+ va_start(arg, fmt);
+ a = parseattrfmtv(fmt, arg);
+ va_end(arg);
+
+ tag = 0;
+
+ for(i=0; i<ring.nkey; i++){
+ k = ring.key[i];
+ if(tag < k->tag)
+ tag = k->tag;
+ if(matchattr(a, k->attr, k->privattr)){
+ k->ref++;
+ if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
+ k->ref--;
+ continue;
+ }
+ freeattr(a);
+ return k;
+ }
+ }
+
+ if(needkey(c, a) < 0)
+ convneedkey(c, a);
+
+ for(i=0; i<ring.nkey; i++){
+ k = ring.key[i];
+ if(k->tag <= tag)
+ continue;
+ if(matchattr(a, k->attr, k->privattr)){
+ k->ref++;
+ if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
+ k->ref--;
+ continue;
+ }
+ freeattr(a);
+ return k;
+ }
+ }
+ freeattr(a);
+ werrstr("no key found");
+ return nil;
+}
+
+static int taggen;
+
+void
+keyadd(Key *k)
+{
+ int i;
+
+ k->ref++;
+ k->tag = ++taggen;
+ for(i=0; i<ring.nkey; i++){
+ if(matchattr(k->attr, ring.key[i]->attr, nil)
+ && matchattr(ring.key[i]->attr, k->attr, nil)){
+ keyclose(ring.key[i]);
+ ring.key[i] = k;
+ return;
+ }
+ }
+
+ ring.key = erealloc(ring.key, (ring.nkey+1)*sizeof(ring.key[0]));
+ ring.key[ring.nkey++] = k;
+}
+
+void
+keyclose(Key *k)
+{
+ if(k == nil)
+ return;
+
+ if(--k->ref > 0)
+ return;
+
+ if(k->proto->closekey)
+ (*k->proto->closekey)(k);
+
+ freeattr(k->attr);
+ freeattr(k->privattr);
+ free(k);
+}
+
+Key*
+keyreplace(Conv *c, Key *k, char *fmt, ...)
+{
+ Key *kk;
+ char *msg;
+ Attr *a, *b, *bp;
+ va_list arg;
+
+ va_start(arg, fmt);
+ msg = vsmprint(fmt, arg);
+ if(msg == nil)
+ sysfatal("out of memory");
+ va_end(arg);
+
+ /* replace prompted values with prompts */
+ a = copyattr(k->attr);
+ bp = parseattr(k->proto->keyprompt);
+ for(b=bp; b; b=b->next){
+ a = delattr(a, b->name);
+ a = addattr(a, "%q?", b->name);
+ }
+ freeattr(bp);
+
+ if(badkey(c, k, msg, a) < 0)
+ convbadkey(c, k, msg, a);
+ kk = keylookup("%A", a);
+ freeattr(a);
+ keyclose(k);
+ if(kk == k){
+ keyclose(kk);
+ werrstr("%s", msg);
+ return nil;
+ }
+
+ if(strfindattr(kk->attr, "confirm")){
+ if(confirmkey(c, kk) != 1){
+ werrstr("key use not confirmed");
+ keyclose(kk);
+ return nil;
+ }
+ }
+ return kk;
+}
+
+void
+keyevict(Conv *c, Key *k, char *fmt, ...)
+{
+ char *msg;
+ Attr *a, *b, *bp;
+ va_list arg;
+
+ va_start(arg, fmt);
+ msg = vsmprint(fmt, arg);
+ if(msg == nil)
+ sysfatal("out of memory");
+ va_end(arg);
+
+ /* replace prompted values with prompts */
+ a = copyattr(k->attr);
+ bp = parseattr(k->proto->keyprompt);
+ for(b=bp; b; b=b->next){
+ a = delattr(a, b->name);
+ a = addattr(a, "%q?", b->name);
+ }
+ freeattr(bp);
+
+ if(badkey(c, k, msg, nil) < 0)
+ convbadkey(c, k, msg, nil);
+ keyclose(k);
+}