int findkey(char *keyfile, char *host, RSApub *key) { char *h; Biobuf *b; RSApub *k; if((b = Bopen(keyfile, OREAD)) == nil) return NoKeyFile; for(;;){ if((k = readpublickey(b, &h)) == nil){ Bterm(b); return NoKey; } if(match(h, host) != 0){ free(h); rsapubfree(k); continue; } if(mpcmp(k->n, key->n) != 0 || mpcmp(k->ek, key->ek) != 0){ free(h); rsapubfree(k); Bterm(b); return KeyWrong; } free(h); rsapubfree(k); Bterm(b); return KeyOk; } }
RSApub* readpublickey(Biobuf *b, char **sp) { char *s; RSApub *key; key = rsapuballoc(); if(key == nil) return nil; for(;;){ if((s = Brdstr(b, '\n', 1)) == nil){ rsapubfree(key); return nil; } if(s[0]=='#'){ free(s); continue; } if(parsepubkey(s, key, sp, 10)==0 || parsepubkey(s, key, sp, 16)==0) return key; fprint(2, "warning: skipping line '%s'; cannot parse\n", s); free(s); } }
static void rsa_freepub(void *a) { rsapubfree((RSApub*)a); }
int replacekey(char *keyfile, char *host, RSApub *hostkey) { int ret; char *h, *nkey, *p; Biobuf *br, *bw; Dir *d, nd; RSApub *k; ret = -1; d = nil; nkey = smprint("%s.new", keyfile); if(nkey == nil) return -1; if((br = Bopen(keyfile, OREAD)) == nil) goto out; if((bw = Bopen(nkey, OWRITE)) == nil){ Bterm(br); goto out; } while((k = readpublickey(br, &h)) != nil){ if(match(h, host) != 0) Bprint(bw, "%s %d %.10M %.10M\n", h, mpsignif(k->n), k->ek, k->n); free(h); rsapubfree(k); } Bprint(bw, "%s %d %.10M %.10M\n", host, mpsignif(hostkey->n), hostkey->ek, hostkey->n); Bterm(bw); Bterm(br); d = dirstat(nkey); if(d == nil){ fprint(2, "new key file disappeared?\n"); goto out; } p = strrchr(d->name, '.'); if(p == nil || strcmp(p, ".new") != 0){ fprint(2, "%s: new key file changed names? %s to %s\n", argv0, nkey, d->name); goto out; } *p = '\0'; nulldir(&nd); nd.name = d->name; if(remove(keyfile) < 0){ fprint(2, "%s: error removing %s: %r\n", argv0, keyfile); goto out; } if(dirwstat(nkey, &nd) < 0){ fprint(2, "%s: error renaming %s to %s: %r\n", argv0, nkey, d->name); goto out; } ret = 0; out: free(d); free(nkey); return ret; }