ctl.c (3781B)
1 #include "std.h" 2 #include "dat.h" 3 4 /* 5 * key attr=val... - add a key 6 * the attr=val pairs are protocol-specific. 7 * for example, both of these are valid: 8 * key p9sk1 gre cs.bell-labs.com mysecret 9 * key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex 10 * delkey ... - delete a key 11 * if given, the attr=val pairs are used to narrow the search 12 * [maybe should require a password?] 13 * 14 * debug - toggle debugging 15 */ 16 17 static char *msg[] = { 18 "key", 19 "delkey", 20 "debug" 21 }; 22 23 static int 24 classify(char *s) 25 { 26 int i; 27 28 for(i=0; i<nelem(msg); i++) 29 if(strcmp(msg[i], s) == 0) 30 return i; 31 return -1; 32 } 33 34 int 35 ctlwrite(char *a) 36 { 37 char *p; 38 int i, nmatch, ret; 39 Attr *attr, *kpa, **l, **lpriv, **lprotos, *pa, *priv, *protos; 40 Key *k; 41 Proto *proto; 42 43 while(*a == ' ' || *a == '\t' || *a == '\n') 44 a++; 45 46 if(a[0] == '#' || a[0] == '\0') 47 return 0; 48 49 /* 50 * it would be nice to emit a warning of some sort here. 51 * we ignore all but the first line of the write. this helps 52 * both with things like "echo delkey >/mnt/factotum/ctl" 53 * and writes that (incorrectly) contain multiple key lines. 54 */ 55 if(p = strchr(a, '\n')){ 56 if(p[1] != '\0'){ 57 werrstr("multiline write not allowed"); 58 return -1; 59 } 60 *p = '\0'; 61 } 62 63 if((p = strchr(a, ' ')) == nil) 64 p = ""; 65 else 66 *p++ = '\0'; 67 switch(classify(a)){ 68 default: 69 werrstr("unknown verb %s", a); 70 return -1; 71 case 0: /* key */ 72 attr = parseattr(p); 73 /* separate out proto= attributes */ 74 lprotos = &protos; 75 for(l=&attr; (*l); ){ 76 if(strcmp((*l)->name, "proto") == 0){ 77 *lprotos = *l; 78 lprotos = &(*l)->next; 79 *l = (*l)->next; 80 }else 81 l = &(*l)->next; 82 } 83 *lprotos = nil; 84 if(protos == nil){ 85 werrstr("key without protos"); 86 freeattr(attr); 87 return -1; 88 } 89 90 /* separate out private attributes */ 91 lpriv = &priv; 92 for(l=&attr; (*l); ){ 93 if((*l)->name[0] == '!'){ 94 *lpriv = *l; 95 lpriv = &(*l)->next; 96 *l = (*l)->next; 97 }else 98 l = &(*l)->next; 99 } 100 *lpriv = nil; 101 flog("addkey %A %A %N", protos, attr, priv); 102 103 /* add keys */ 104 ret = 0; 105 for(pa=protos; pa; pa=pa->next){ 106 if((proto = protolookup(pa->val)) == nil){ 107 werrstr("unknown proto %s", pa->val); 108 flog("addkey: %r"); 109 ret = -1; 110 continue; 111 } 112 if(proto->keyprompt){ 113 kpa = parseattr(proto->keyprompt); 114 if(!matchattr(kpa, attr, priv)){ 115 freeattr(kpa); 116 werrstr("missing attributes -- want %s", proto->keyprompt); 117 flog("addkey %s: %r", proto->name); 118 ret = -1; 119 continue; 120 } 121 freeattr(kpa); 122 } 123 k = emalloc(sizeof(Key)); 124 k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr)); 125 k->privattr = copyattr(priv); 126 k->ref = 1; 127 k->proto = proto; 128 if(proto->checkkey && (*proto->checkkey)(k) < 0){ 129 flog("addkey %s: %r", proto->name); 130 ret = -1; 131 keyclose(k); 132 continue; 133 } 134 flog("adding key: %A %N", k->attr, k->privattr); 135 keyadd(k); 136 keyclose(k); 137 } 138 freeattr(attr); 139 freeattr(priv); 140 freeattr(protos); 141 return ret; 142 case 1: /* delkey */ 143 nmatch = 0; 144 attr = parseattr(p); 145 flog("delkey %A", attr); 146 for(pa=attr; pa; pa=pa->next){ 147 if(pa->type != AttrQuery && pa->name[0]=='!'){ 148 werrstr("only !private? patterns are allowed for private fields"); 149 freeattr(attr); 150 return -1; 151 } 152 } 153 for(i=0; i<ring.nkey; ){ 154 if(matchattr(attr, ring.key[i]->attr, ring.key[i]->privattr)){ 155 nmatch++; 156 flog("deleting %A %N", ring.key[i]->attr, ring.key[i]->privattr); 157 keyclose(ring.key[i]); 158 ring.nkey--; 159 memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0])); 160 }else 161 i++; 162 } 163 freeattr(attr); 164 if(nmatch == 0){ 165 werrstr("found no keys to delete"); 166 return -1; 167 } 168 return 0; 169 case 2: /* debug */ 170 debug ^= 1; 171 flog("debug = %d", debug); 172 return 0; 173 } 174 }