123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <mp.h>
- #include <ctype.h>
- #include <libsec.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- #include "netssh.h"
- enum {
- Arbsz = 256,
- };
- static int
- parsepubkey(char *s, RSApub *key, char **sp, int base)
- {
- int n;
- char *host, *p, *z;
- z = nil;
- n = strtoul(s, &p, 10);
- host = nil;
- if(n < Arbsz || !isspace(*p)){ /* maybe this is a host name */
- host = s;
- s = strpbrk(s, " \t");
- if(s == nil)
- return -1;
- z = s;
- *s++ = '\0';
- s += strspn(s, " \t");
- n = strtoul(s, &p, 10);
- if(n < Arbsz || !isspace(*p)){
- if(z)
- *z = ' ';
- return -1;
- }
- }
- /* Arbsz is just a sanity check */
- if((key->ek = strtomp(p, &p, base, nil)) == nil ||
- (key->n = strtomp(p, &p, base, nil)) == nil ||
- (*p != '\0' && !isspace(*p)) || mpsignif(key->n) < Arbsz) {
- mpfree(key->ek);
- mpfree(key->n);
- key->ek = nil;
- key->n = nil;
- if(z)
- *z = ' ';
- return -1;
- }
- if(host == nil){
- if(*p != '\0'){
- p += strspn(p, " \t");
- if(*p != '\0'){
- host = emalloc9p(strlen(p)+1);
- strcpy(host, p);
- }
- }
- free(s);
- }
- *sp = host;
- return 0;
- }
- RSApub*
- readpublickey(Biobuf *b, char **sp)
- {
- char *s;
- RSApub *key;
- key = emalloc9p(sizeof(RSApub));
- if(key == nil)
- return nil;
- for (; (s = Brdstr(b, '\n', 1)) != nil; free(s))
- if(s[0] != '#'){
- 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(key);
- return nil;
- }
- static int
- match(char *pattern, char *aliases)
- {
- char *s, *snext, *a, *anext, *ae;
- for(s = pattern; s && *s; s = snext){
- if((snext = strchr(s, ',')) != nil)
- *snext++ = '\0';
- for(a = aliases; a && *a; a = anext){
- if((anext = strchr(a, ',')) != nil){
- ae = anext;
- anext++;
- }else
- ae = a + strlen(a);
- if(ae - a == strlen(s) && memcmp(s, a, ae - a) == 0)
- return 0;
- }
- }
- return 1;
- }
- int
- findkey(char *keyfile, char *host, RSApub *key)
- {
- char *h;
- Biobuf *b;
- RSApub *k;
- int res;
- if ((b = Bopen(keyfile, OREAD)) == nil)
- return NoKeyFile;
- for (res = NoKey; res != KeyOk;) {
- if ((k = readpublickey(b, &h)) == nil)
- break;
- if (match(h, host) == 0) {
- if (mpcmp(k->n, key->n) == 0 &&
- mpcmp(k->ek, key->ek) == 0)
- res = KeyOk;
- else
- res = KeyWrong;
- }
- free(h);
- free(k->ek);
- free(k->n);
- free(k);
- }
- Bterm(b);
- return res;
- }
- 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;
- }
- int
- appendkey(char *keyfile, char *host, RSApub *key)
- {
- int fd, ret;
- ret = -1;
- if((fd = open(keyfile, OWRITE)) < 0){
- fd = create(keyfile, OWRITE, 0666);
- if(fd < 0){
- fprint(2, "%s: can't open nor create %s: %r\n",
- argv0, keyfile);
- return -1;
- }
- }
- if(seek(fd, 0, 2) >= 0 &&
- fprint(fd, "%s %d %.10M %.10M\n", host, mpsignif(key->n),
- key->ek, key->n) >= 0)
- ret = 0;
- close(fd);
- return ret;
- }
|