Exemple #1
0
int
needkeywrite(char *s)
{
	char *t;
	ulong tag;
	Attr *a;
	Conv *c;

	a = _parseattr(s);
	if(a == nil){
		werrstr("empty write");
		return -1;
	}
	if((t = _strfindattr(a, "tag")) == nil){
		werrstr("no tag");
		freeattr(a);
		return -1;
	}
	tag = strtoul(t, 0, 0);
	for(c=conv; c; c=c->next)
		if(c->tag == tag){
			nbsendul(c->keywait, 0);
			break;
		}
	if(c == nil){
		werrstr("tag not found");
		freeattr(a);
		return -1;
	}
	freeattr(a);
	return 0;
}
Exemple #2
0
Attr*
auth_attr(AuthRpc *rpc)
{
	if(auth_rpc(rpc, "attr", nil, 0) != ARok)
		return nil;
	return _parseattr(rpc->arg);
}
Exemple #3
0
int
needkeywrite(char *s)
{
	char *t;
	ulong tag;
	Attr *a;
	Req *r, **l;

	a = _parseattr(s);
	if(a == nil){
		werrstr("empty write");
		return -1;
	}
	if((t = _strfindattr(a, "tag")) == nil){
		werrstr("no tag");
		return -1;
	}
	tag = strtoul(t, 0, 0);
	r = nil;
	for(l=&needwait; *l; l=&(*l)->aux){
		r = *l;
		if(r->tag == tag){
			*l = r->aux;
			if(r->aux == nil)
				needlast = l;
			break;
		}
	}
	if(r == nil){
		werrstr("tag not found");
		return -1;
	}
	rpcread(r);
	return 0;
}
Exemple #4
0
int
confirmwrite(char *s)
{
	char *t, *ans;
	int allow, tagoff;
	ulong tag;
	Attr *a;
	Fsstate *fss;
	Req *r, **l;

	a = _parseattr(s);
	if(a == nil){
		werrstr("empty write");
		return -1;
	}
	if((t = _strfindattr(a, "tag")) == nil){
		werrstr("no tag");
		return -1;
	}
	tag = strtoul(t, 0, 0);
	if((ans = _strfindattr(a, "answer")) == nil){
		werrstr("no answer");
		return -1;
	}
	if(strcmp(ans, "yes") == 0)
		allow = 1;
	else if(strcmp(ans, "no") == 0)
		allow = 0;
	else{
		werrstr("bad answer");
		return -1;
	}
	r = nil;
	tagoff = -1;
	for(l=&cusewait; *l; l=&(*l)->aux){
		r = *l;
		if(hastag(r->fid->aux, tag, &tagoff)){
			*l = r->aux;
			if(r->aux == nil)
				cuselast = l;
			break;
		}
	}
	if(r == nil || tagoff == -1){
		werrstr("tag not found");
		return -1;
	}
	fss = r->fid->aux;
	fss->conf[tagoff].canuse = allow;
	rpcread(r);
	return 0;
}
Exemple #5
0
/*
 *  prompt user for a key.  don't care about memory leaks, runs standalone
 */
static Attr*
promptforkey(char *params)
{
	char *v;
	int fd;
	Attr *a, *attr;
	char *def;

	fd = open("/dev/cons", ORDWR);
	if(fd < 0)
		sysfatal("opening /dev/cons: %r");

	attr = _parseattr(params);
	fprint(fd, "\n!Adding key:");
	for(a=attr; a; a=a->next)
		if(a->type != AttrQuery && a->name[0] != '!')
			fprint(fd, " %q=%q", a->name, a->val);
	fprint(fd, "\n");

	for(a=attr; a; a=a->next){
		v = a->name;
		if(a->type != AttrQuery || v[0]=='!')
			continue;
		def = nil;
		if(strcmp(v, "user") == 0)
			def = getuser();
		a->val = readcons(v, def, 0);
		if(a->val == nil)
			sysfatal("user terminated key input");
		a->type = AttrNameval;
	}
	for(a=attr; a; a=a->next){
		v = a->name;
		if(a->type != AttrQuery || v[0]!='!')
			continue;
		def = nil;
		if(strcmp(v+1, "user") == 0)
			def = getuser();
		a->val = readcons(v+1, def, 1);
		if(a->val == nil)
			sysfatal("user terminated key input");
		a->type = AttrNameval;
	}
	fprint(fd, "!\n");
	close(fd);
	return attr;
}
Exemple #6
0
int
confirmwrite(char *s)
{
	char *t, *ans;
	int allow;
	ulong tag;
	Attr *a;
	Conv *c;

	a = _parseattr(s);
	if(a == nil){
		werrstr("bad attr");
		return -1;
	}
	if((t = _strfindattr(a, "tag")) == nil){
		flog("bad confirm write: no tag");
		werrstr("no tag");
		return -1;
	}
	tag = strtoul(t, 0, 0);
	if((ans = _strfindattr(a, "answer")) == nil){
		flog("bad confirm write: no answer");
		werrstr("no answer");
		return -1;
	}
	if(strcmp(ans, "yes") == 0)
		allow = 1;
	else if(strcmp(ans, "no") == 0)
		allow = 0;
	else{
		flog("bad confirm write: bad answer");
		werrstr("bad answer");
		return -1;
	}
	for(c=conv; c; c=c->next){
		if(tag == c->tag){
			nbsendul(c->keywait, allow);
			break;
		}
	}
	if(c == nil){
		werrstr("tag not found");
		return -1;
	}
	return 0;
}
Exemple #7
0
void
sshserverhandshake(Conn *c)
{
	char *p, buf[128];
	Biobuf *b;
	Attr *a;
	int i, afd;
	mpint *m;
	AuthRpc *rpc;
	RSApub *key;

	/*
	 * BUG: should use `attr' to get the key attributes
	 * after the read, but that's not implemented yet.
	 */
	if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil)
		sysfatal("open /mnt/factotum/ctl: %r");
	while((p = Brdline(b, '\n')) != nil){
		p[Blinelen(b)-1] = '\0';
		if(strstr(p, " proto=rsa ") && strstr(p, " service=sshserve "))
			break;
	}
	if(p == nil)
		sysfatal("no sshserve keys found in /mnt/factotum/ctl");
	a = _parseattr(p);
	Bterm(b);
	key = emalloc(sizeof(*key));
	if((p = _strfindattr(a, "n")) == nil)
		sysfatal("no n in sshserve key");
	if((key->n = strtomp(p, &p, 16, nil)) == nil || *p != 0)
		sysfatal("bad n in sshserve key");
	if((p = _strfindattr(a, "ek")) == nil)
		sysfatal("no ek in sshserve key");
	if((key->ek = strtomp(p, &p, 16, nil)) == nil || *p != 0)
		sysfatal("bad ek in sshserve key");
	_freeattr(a);

	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
		sysfatal("open /mnt/factotum/rpc: %r");
	if((rpc = auth_allocrpc(afd)) == nil)
		sysfatal("auth_allocrpc: %r");
	p = "proto=rsa role=client service=sshserve";
	if(auth_rpc(rpc, "start", p, strlen(p)) != ARok)
		sysfatal("auth_rpc start %s: %r", p);
	if(auth_rpc(rpc, "read", nil, 0) != ARok)
		sysfatal("auth_rpc read: %r");
	m = strtomp(rpc->arg, nil, 16, nil);
	if(mpcmp(m, key->n) != 0)
		sysfatal("key in /mnt/factotum/ctl does not match rpc key");
	mpfree(m);
	c->hostkey = key;

	/* send id string */
	fprint(c->fd[0], "SSH-1.5-Plan9\n");

	/* receive id string */
	if(readstrnl(c->fd[0], buf, sizeof buf) < 0)
		sysfatal("reading server version: %r");

	/* id string is "SSH-m.n-comment".  We need m=1, n>=5. */
	if(strncmp(buf, "SSH-", 4) != 0
	|| strtol(buf+4, &p, 10) != 1
	|| *p != '.'
	|| strtol(p+1, &p, 10) < 5
	|| *p != '-')
		sysfatal("protocol mismatch; got %s, need SSH-1.x for x>=5", buf);

	for(i=0; i<COOKIELEN; i++)
		c->cookie[i] = fastrand();
	calcsessid(c);
	send_ssh_smsg_public_key(c);
	recv_ssh_cmsg_session_key(c, rpc);
	auth_freerpc(rpc);
	close(afd);

	c->cstate = (*c->cipher->init)(c, 1);		/* turns on encryption */
	sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));

	authsrvuser(c);
}
Exemple #8
0
RSApriv*
getkey(int argc, char **argv, int needprivate, Attr **pa)
{
    char *file, *s, *p;
    int sz;
    RSApriv *key;
    Biobuf *b;
    int regen;
    Attr *a;

    if(argc == 0)
        file = "#d/0";
    else
        file = argv[0];

    key = mallocz(sizeof(RSApriv), 1);
    if(key == nil)
        return nil;

    if((b = Bopen(file, OREAD)) == nil) {
        werrstr("open %s: %r", file);
        return nil;
    }
    s = Brdstr(b, '\n', 1);
    if(s == nil) {
        werrstr("read %s: %r", file);
        return nil;
    }
    if(strncmp(s, "key ", 4) != 0) {
        werrstr("bad key format");
        return nil;
    }

    regen = 0;
    a = _parseattr(s+4);
    if(a == nil) {
        werrstr("empty key");
        return nil;
    }
    if((p = _strfindattr(a, "proto")) == nil) {
        werrstr("no proto");
        return nil;
    }
    if(strcmp(p, "rsa") != 0) {
        werrstr("proto not rsa");
        return nil;
    }
    if((p = _strfindattr(a, "ek")) == nil) {
        werrstr("no ek");
        return nil;
    }
    if((key->pub.ek = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad ek");
        return nil;
    }
    if((p = _strfindattr(a, "n")) == nil) {
        werrstr("no n");
        return nil;
    }
    if((key->pub.n = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad n");
        return nil;
    }
    if((p = _strfindattr(a, "size")) == nil)
        fprint(2, "warning: missing size; will add\n");
    else if((sz = strtol(p, &p, 10)) == 0 || *p != 0)
        fprint(2, "warning: bad size; will correct\n");
    else if(sz != mpsignif(key->pub.n))
        fprint(2, "warning: wrong size (got %d, expected %d); will correct\n",
               sz, mpsignif(key->pub.n));
    if(!needprivate)
        goto call;
    if((p = _strfindattr(a, "!dk")) == nil) {
        werrstr("no !dk");
        return nil;
    }
    if((key->dk = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad !dk");
        return nil;
    }
    if((p = _strfindattr(a, "!p")) == nil) {
        werrstr("no !p");
        return nil;
    }
    if((key->p = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad !p");
        return nil;
    }
    if((p = _strfindattr(a, "!q")) == nil) {
        werrstr("no !q");
        return nil;
    }
    if((key->q = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad !q");
        return nil;
    }
    if((p = _strfindattr(a, "!kp")) == nil) {
        fprint(2, "warning: no !kp\n");
        regen = 1;
        goto regen;
    }
    if((key->kp = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        fprint(2, "warning: bad !kp\n");
        regen = 1;
        goto regen;
    }
    if((p = _strfindattr(a, "!kq")) == nil) {
        fprint(2, "warning: no !kq\n");
        regen = 1;
        goto regen;
    }
    if((key->kq = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        fprint(2, "warning: bad !kq\n");
        regen = 1;
        goto regen;
    }
    if((p = _strfindattr(a, "!c2")) == nil) {
        fprint(2, "warning: no !c2\n");
        regen = 1;
        goto regen;
    }
    if((key->c2 = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        fprint(2, "warning: bad !c2\n");
        regen = 1;
        goto regen;
    }
regen:
    if(regen) {
        RSApriv *k2;

        k2 = rsafill(key->pub.n, key->pub.ek, key->dk, key->p, key->q);
        if(k2 == nil) {
            werrstr("regenerating chinese-remainder parts failed: %r");
            return nil;
        }
        key = k2;
    }
call:
    a = _delattr(a, "ek");
    a = _delattr(a, "n");
    a = _delattr(a, "size");
    a = _delattr(a, "!dk");
    a = _delattr(a, "!p");
    a = _delattr(a, "!q");
    a = _delattr(a, "!c2");
    a = _delattr(a, "!kp");
    a = _delattr(a, "!kq");
    if(pa)
        *pa = a;
    return key;
}
Exemple #9
0
DSApriv*
getdsakey(int argc, char **argv, int needprivate, Attr **pa)
{
    char *file, *s, *p;
    DSApriv *key;
    Biobuf *b;
    Attr *a;

    if(argc == 0)
        file = "#d/0";
    else
        file = argv[0];

    key = mallocz(sizeof(RSApriv), 1);
    if(key == nil)
        return nil;

    if((b = Bopen(file, OREAD)) == nil) {
        werrstr("open %s: %r", file);
        return nil;
    }
    s = Brdstr(b, '\n', 1);
    if(s == nil) {
        werrstr("read %s: %r", file);
        return nil;
    }
    if(strncmp(s, "key ", 4) != 0) {
        werrstr("bad key format");
        return nil;
    }

    a = _parseattr(s+4);
    if(a == nil) {
        werrstr("empty key");
        return nil;
    }
    if((p = _strfindattr(a, "proto")) == nil) {
        werrstr("no proto");
        return nil;
    }
    if(strcmp(p, "dsa") != 0) {
        werrstr("proto not dsa");
        return nil;
    }
    if((p = _strfindattr(a, "p")) == nil) {
        werrstr("no p");
        return nil;
    }
    if((key->pub.p = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad p");
        return nil;
    }
    if((p = _strfindattr(a, "q")) == nil) {
        werrstr("no q");
        return nil;
    }
    if((key->pub.q = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad q");
        return nil;
    }
    if((p = _strfindattr(a, "alpha")) == nil) {
        werrstr("no alpha");
        return nil;
    }
    if((key->pub.alpha = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad alpha");
        return nil;
    }
    if((p = _strfindattr(a, "key")) == nil) {
        werrstr("no key=");
        return nil;
    }
    if((key->pub.key = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad key=");
        return nil;
    }
    if(!needprivate)
        goto call;
    if((p = _strfindattr(a, "!secret")) == nil) {
        werrstr("no !secret");
        return nil;
    }
    if((key->secret = strtomp(p, &p, 16, nil)) == nil || *p != 0) {
        werrstr("bad !secret");
        return nil;
    }
call:
    a = _delattr(a, "p");
    a = _delattr(a, "q");
    a = _delattr(a, "alpha");
    a = _delattr(a, "key");
    a = _delattr(a, "!secret");
    if(pa)
        *pa = a;
    return key;
}
Exemple #10
0
int
ctlwrite(char *a, int atzero)
{
	char *p;
	int i, nmatch, ret;
	Attr *attr, **l, **lpriv, **lprotos, *pa, *priv, *protos;
	Key *k;
	Proto *proto;

	if(a[0] == '#' || a[0] == '\0')
		return 0;

	/*
	 * it would be nice to emit a warning of some sort here.
	 * we ignore all but the first line of the write.  this helps
	 * both with things like "echo delkey >/mnt/factotum/ctl"
	 * and writes that (incorrectly) contain multiple key lines.
	 */
	if((p = strchr(a, '\n')) != nil){
		if(p[1] != '\0'){
			werrstr("multiline write not allowed");
			return -1;
		}
		*p = '\0';
	}

	if((p = strchr(a, ' ')) == nil)
		p = "";
	else
		*p++ = '\0';
	switch(classify(a, ctltab, nelem(ctltab))){
	default:
	case Vunknown:
		werrstr("unknown verb");
		return -1;
	case Vdebug:
		debug ^= 1;
		return 0;
	case Vdelkey:
		nmatch = 0;
		attr = _parseattr(p);
		for(pa=attr; pa; pa=pa->next){
			if(pa->type != AttrQuery && pa->name[0]=='!'){
				werrstr("only !private? patterns are allowed for private fields");
				_freeattr(attr);
				return -1;
			}
		}
		for(i=0; i<ring->nkey; ){
			if(matchattr(attr, ring->key[i]->attr, ring->key[i]->privattr)){
				nmatch++;
				closekey(ring->key[i]);
				ring->nkey--;
				memmove(&ring->key[i], &ring->key[i+1], (ring->nkey-i)*sizeof(ring->key[0]));
			}else
				i++;
		}
		_freeattr(attr);
		if(nmatch == 0){
			werrstr("found no keys to delete");
			return -1;
		}
		return 0;
	case Vaddkey:
		attr = _parseattr(p);
		/* separate out proto= attributes */
		lprotos = &protos;
		for(l=&attr; (*l); ){
			if(strcmp((*l)->name, "proto") == 0){
				*lprotos = *l;
				lprotos = &(*l)->next;
				*l = (*l)->next;
			}else
				l = &(*l)->next;
		}
		*lprotos = nil;
		if(protos == nil){
			werrstr("key without protos");
			_freeattr(attr);
			return -1;
		}

		/* separate out private attributes */
		lpriv = &priv;
		for(l=&attr; (*l); ){
			if((*l)->name[0] == '!'){
				*lpriv = *l;
				lpriv = &(*l)->next;
				*l = (*l)->next;
			}else
				l = &(*l)->next;
		}
		*lpriv = nil;

		/* add keys */
		ret = 0;
		for(pa=protos; pa; pa=pa->next){
			if((proto = findproto(pa->val)) == nil){
				werrstr("unknown proto %s", pa->val);
				ret = -1;
				continue;
			}
			if(proto->addkey == nil){
				werrstr("proto %s doesn't take keys", proto->name);
				ret = -1;
				continue;
			}
			k = emalloc(sizeof(Key));
			k->attr = _mkattr(AttrNameval, "proto", proto->name, _copyattr(attr));
			k->privattr = _copyattr(priv);
			k->ref = 1;
			k->proto = proto;
			if(proto->addkey(k, atzero) < 0){
				ret = -1;
				closekey(k);
				continue;
			}
			closekey(k);
		}
		_freeattr(attr);
		_freeattr(priv);
		_freeattr(protos);
		return ret;
	}
}
Exemple #11
0
void
rpcread(Req *r)
{
	Attr *attr;
	char *p;
	int ophase, ret;
	uint8_t *e;
	uint count;
	Fsstate *fss;
	Proto *proto;

	if(r->ifcall.count < 64){
		respond(r, "rpc read too small");
		return;
	}
	fss = r->fid->aux;
	if(!fss->pending){
		respond(r, "no rpc pending");
		return;
	}
	switch(fss->rpc.iverb){
	default:
	case Vunknown:
		retstring(r, fss, "error unknown verb");
		break;

	case Vstart:
		if(fss->phase != Notstarted){
			flog("%d: implicit close due to second start; old attr '%A'", fss->seqnum, fss->attr);
			if(fss->proto && fss->ps)
				(*fss->proto->close)(fss);
			fss->ps = nil;
			fss->proto = nil;
			_freeattr(fss->attr);
			fss->attr = nil;
			fss->phase = Notstarted;
		}
		attr = _parseattr(fss->rpc.arg);
		if((p = _strfindattr(attr, "proto")) == nil){
			retstring(r, fss, "error did not specify proto");
			_freeattr(attr);
			break;
		}
		if((proto = findproto(p)) == nil){
			snprint(fss->rpc.buf, Maxrpc, "error unknown protocol %q", p);
			retstring(r, fss, fss->rpc.buf);
			_freeattr(attr);
			break;
		}
		fss->attr = attr;
		fss->proto = proto;
		fss->seqnum = ++seqnum;
		ret = (*proto->init)(proto, fss);
		rpcstartlog(attr, fss, ret);
		if(ret != RpcOk){
			_freeattr(fss->attr);
			fss->attr = nil;
			fss->phase = Notstarted;
		}
		retrpc(r, ret, fss);
		break;

	case Vread:
		if(fss->rpc.arg && fss->rpc.arg[0]){
			retstring(r, fss, "error read needs no parameters");
			break;
		}
		if(rdwrcheck(r, fss) < 0)
			break;
		count = r->ifcall.count - 3;
		ophase = fss->phase;
		ret = fss->proto->read(fss, (uint8_t*)r->ofcall.data+3,
				       &count);
		rpcrdwrlog(fss, "read", count, ophase, ret);
		if(ret == RpcOk){
			memmove(r->ofcall.data, "ok ", 3);
			if(count == 0)
				r->ofcall.count = 2;
			else
				r->ofcall.count = 3+count;
			fss->pending = 0;
			respond(r, nil);
		}else
			retrpc(r, ret, fss);
		break;

	case Vwrite:
		if(rdwrcheck(r, fss) < 0)
			break;
		ophase = fss->phase;
		ret = fss->proto->write(fss, fss->rpc.arg, fss->rpc.narg);
		rpcrdwrlog(fss, "write", fss->rpc.narg, ophase, ret);
		retrpc(r, ret, fss);
		break;

	case Vauthinfo:
		if(fss->phase != Established){
			retstring(r, fss, "error authentication unfinished");
			break;
		}
		if(!fss->haveai){
			retstring(r, fss, "error no authinfo available");
			break;
		}
		memmove(r->ofcall.data, "ok ", 3);
		fss->ai.cap = mkcap(r->fid->uid, fss->ai.suid);
		e = convAI2M(&fss->ai, (uint8_t*)r->ofcall.data+3,
			     r->ifcall.count-3);
		free(fss->ai.cap);
		fss->ai.cap = nil;
		if(e == nil){
			retstring(r, fss, "error read too small");
			break;
		}
		r->ofcall.count = e - (uint8_t*)r->ofcall.data;
		fss->pending = 0;
		respond(r, nil);
		break;

	case Vattr:
		snprint(fss->rpc.buf, Maxrpc, "ok %A", fss->attr);
		retstring(r, fss, fss->rpc.buf);
		break;
	}
}