diff options
Diffstat (limited to 'src/cmd/auth/factotum/key.c')
-rw-r--r-- | src/cmd/auth/factotum/key.c | 217 |
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); +} |