Exemplo n.º 1
0
int
auth_respond(void *chal, uint nchal, char *user, uint nuser, void *resp, uint nresp, AuthGetkey *getkey, char *fmt, ...)
{
	char *p, *s;
	va_list arg;
	int afd;
	AuthRpc *rpc;
	Attr *a;

	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
		return -1;
	
	if((rpc = auth_allocrpc(afd)) == nil){
		close(afd);
		return -1;
	}

	quotefmtinstall();	/* just in case */
	va_start(arg, fmt);
	p = vsmprint(fmt, arg);
	va_end(arg);

	if(p==nil
	|| dorpc(rpc, "start", p, strlen(p), getkey) != ARok
	|| dorpc(rpc, "write", chal, nchal, getkey) != ARok
	|| dorpc(rpc, "read", nil, 0, getkey) != ARok){
		free(p);
		close(afd);
		auth_freerpc(rpc);
		return -1;
	}
	free(p);

	if(rpc->narg < nresp)
		nresp = rpc->narg;
	memmove(resp, rpc->arg, nresp);

	if((a = auth_attr(rpc)) != nil
	&& (s = _strfindattr(a, "user")) != nil && strlen(s) < nuser)
		strcpy(user, s);
	else if(nuser > 0)
		user[0] = '\0';

	_freeattr(a);
	close(afd);
	auth_freerpc(rpc);
	return nresp;	
}
Exemplo n.º 2
0
Attr*
_delattr(Attr *a, char *name)
{
    Attr *fa;
    Attr **la;

    for(la=&a; *la; ) {
        if(strcmp((*la)->name, name) == 0) {
            fa = *la;
            *la = (*la)->next;
            fa->next = nil;
            _freeattr(fa);
        } else
            la=&(*la)->next;
    }
    return a;
}
Exemplo n.º 3
0
static Attr*
cleanattr(Attr *a)
{
    Attr *fa;
    Attr **la;

    for(la=&a; *la; ) {
        if((*la)->type==AttrQuery && _findattr(a, (*la)->name)) {
            fa = *la;
            *la = (*la)->next;
            fa->next = nil;
            _freeattr(fa);
        } else
            la=&(*la)->next;
    }
    return a;
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
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;
	}
}
Exemplo n.º 6
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;
	}
}