Beispiel #1
0
void
handleagentopen(Msg *m)
{
	int i;
	uint32_t remote;

	assert(m->type == SSH_SMSG_AGENT_OPEN);
	remote = getlong(m);
	debug(DBG_AUTH, "agent open %d\n", remote);

	for(i=0; i<nelem(achan); i++)
		if(achan[i].open == 0 && achan[i].needeof == 0 && achan[i].needclosed == 0)
			break;
	if(i == nelem(achan)){
		m = allocmsg(m->c, SSH_MSG_CHANNEL_OPEN_FAILURE, 4);
		putlong(m, remote);
		sendmsg(m);
		return;
	}

	debug(DBG_AUTH, "\tremote %d is local %d\n", remote, i);
	achan[i].open = 1;
	achan[i].needeof = 1;
	achan[i].needclosed = 1;
	achan[i].nlbuf = 0;
	achan[i].chan = remote;
	m = allocmsg(m->c, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8);
	putlong(m, remote);
	putlong(m, i);
	sendmsg(m);
}
Beispiel #2
0
static int
authtisfn(Conn *c)
{
	int fd, n;
	char *chal, resp[256];
	Msg *m;

	if(!c->interactive)
		return -1;

	debug(DBG_AUTH, "try TIS\n");
	sendmsg(allocmsg(c, SSH_CMSG_AUTH_TIS, 0));

	m = recvmsg(c, -1);
	switch(m->type){
	default:
		badmsg(m, SSH_SMSG_AUTH_TIS_CHALLENGE);
	case SSH_SMSG_FAILURE:
		free(m);
		return -1;
	case SSH_SMSG_AUTH_TIS_CHALLENGE:
		break;
	}

	chal = getstring(m);
	free(m);

	if((fd = open("/dev/cons", ORDWR)) < 0)
		error("can't open console");

	fprint(fd, "TIS Authentication\n%s", chal);
	n = read(fd, resp, sizeof resp-1);
	if(n < 0)
		resp[0] = '\0';
	else
		resp[n] = '\0';

	if(resp[0] == 0 || resp[0] == '\n')
		return -1;

	m = allocmsg(c, SSH_CMSG_AUTH_TIS_RESPONSE, 4+strlen(resp));
	putstring(m, resp);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	default:
		badmsg(m, 0);
	case SSH_SMSG_SUCCESS:
		free(m);
		return 0;
	case SSH_SMSG_FAILURE:
		free(m);
		return -1;
	}
}
Beispiel #3
0
static void
sendwritemsg(Conn *c, char *buf, int n)
{
	Msg *m;

	if(n==0)
		m = allocmsg(c, SSH_CMSG_EOF, 0);
	else{
		m = allocmsg(c, SSH_CMSG_STDIN_DATA, 4+n);
		putlong(m, n);
		putbytes(m, buf, n);
	}
	sendmsg(m);
}
Beispiel #4
0
static void
authsrvuser(Conn *c)
{
	int i;
	char *ns, *user;
	AuthInfo *ai;
	Msg *m;

	m = recvmsg(c, SSH_CMSG_USER);
	user = getstring(m);
	c->user = emalloc(strlen(user)+1);
	strcpy(c->user, user);
	free(m);

	ai = authusername(c);
	while(ai == nil){
		/*
		 * clumsy: if the client aborted the auth_tis early
		 * we don't send a new failure.  we check this by
		 * looking at c->unget, which is only used in that
		 * case.
		 */
		if(c->unget != nil)
			goto skipfailure;
		sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
	skipfailure:
		m = recvmsg(c, -1);
		for(i=0; i<c->nokauthsrv; i++)
			if(c->okauthsrv[i]->firstmsg == m->type){
				ai = (*c->okauthsrv[i]->fn)(c, m);
				break;
			}
		if(i==c->nokauthsrv)
			badmsg(m, 0);
	}
	sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));

	if(noworld(ai->cuid))
		ns = "/lib/namespace.noworld";
	else
		ns = nil;
	if(auth_chuid(ai, ns) < 0){
		sshlog("auth_chuid to %s: %r", ai->cuid);
		sysfatal("auth_chuid: %r");
	}
	sshlog("logged in as %s", ai->cuid);
	auth_freeAI(ai);
}
Beispiel #5
0
void
copyout(Conn *c, int fd, int mtype)
{
	char buf[8192];
	int n, max, pid;
	Msg *m;

	max = sizeof buf;
	if(max > maxmsg - 32)	/* 32 is an overestimate of packet overhead */
		max = maxmsg - 32;
	if(max <= 0)
		sysfatal("maximum message size too small");
	
	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
	case -1:
		sysfatal("fork: %r");
	case 0:
		break;
	default:
		atexitkill(pid);
		return;
	}

	while((n = read(fd, buf, max)) > 0){
		m = allocmsg(c, mtype, 4+n);
		putlong(m, n);
		putbytes(m, buf, n);
		sendmsg(m);
	}
	exits(nil);
}
Beispiel #6
0
void StatusItem::GeneratePopUp(BPoint point, BRect openrect)
{
	BString str(value);
	str.Append(" ");
	BString url;
	URLCrunch crunch(str.String(), str.Length());
	BPopUpMenu* menu = new BPopUpMenu("URLs");
	BMessage msg(M_LOAD_URL);
	BMessage* allocmsg(NULL);
	BMenuItem* item(NULL);

	while (crunch.Crunch(&url) != B_ERROR) {
		allocmsg = new BMessage(msg);
		allocmsg->AddString("url", url.String());
		item = new BMenuItem(url.String(), allocmsg);
		menu->AddItem(item);
		allocmsg = NULL;
	}

	if (menu->CountItems() > 0) {
		menu->SetTargetForItems(be_app);
		menu->SetAsyncAutoDestruct(true);
		menu->Go(point, true, true, openrect, true);
	} else {
		delete menu;
	}
}
Beispiel #7
0
static int
authuser(Conn *c)
{
	int i;
	Msg *m;

	m = allocmsg(c, SSH_CMSG_USER, 4+strlen(c->user));
	putstring(m, c->user);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	case SSH_SMSG_SUCCESS:
		free(m);
		return 0;
	case SSH_SMSG_FAILURE:
		free(m);
		break;
	default:
		badmsg(m, 0);
	}

	for(i=0; i<c->nokauth; i++){
		debug(DBG_AUTH, "authmask %#lux, consider %s (%#x)\n",
			c->authmask, c->okauth[i]->name, 1<<c->okauth[i]->id);
		if(c->authmask & (1<<c->okauth[i]->id))
			if((*c->okauth[i]->fn)(c) == 0)
				return 0;
	}

	debug(DBG_AUTH, "no auth methods worked; (authmask=%#lux)\n", c->authmask);
	return -1;
}
Beispiel #8
0
int
startagent(Conn *c)
{
	int ret;
	Msg *m;

	m = allocmsg(c, SSH_CMSG_AGENT_REQUEST_FORWARDING, 0);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	case SSH_SMSG_SUCCESS:
		debug(DBG_AUTH, "agent allocated\n");
		ret = 0;
		break;
	case SSH_SMSG_FAILURE:
		debug(DBG_AUTH, "agent failed to allocate\n");
		ret = -1;
		break;
	default:
		badmsg(m, 0);
		ret = -1;
		break;
	}
	free(m);
	return ret;
}
Beispiel #9
0
static int
authpasswordfn(Conn *c)
{
	Msg *m;
	UserPasswd *up;

	up = auth_getuserpasswd(c->interactive ? auth_getkey : nil, "proto=pass service=ssh server=%q user=%q", c->host, c->user);
	if(up == nil){
		debug(DBG_AUTH, "getuserpasswd returned nothing (interactive=%d)\n", c->interactive);
		return -1;
	}

	debug(DBG_AUTH, "try using password from factotum\n");
	m = allocmsg(c, SSH_CMSG_AUTH_PASSWORD, 4+strlen(up->passwd));
	putstring(m, up->passwd);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	default:
		badmsg(m, 0);
	case SSH_SMSG_SUCCESS:
		free(m);
		return 0;
	case SSH_SMSG_FAILURE:
		free(m);
		return -1;
	}
}
Beispiel #10
0
void
sendwindowsize(Conn *c, int nrow, int ncol, int width, int height)
{
	Msg *m;

	m = allocmsg(c, SSH_CMSG_WINDOW_SIZE, 4*4);
	putlong(m, nrow);
	putlong(m, ncol);
	putlong(m, width);
	putlong(m, height);
	sendmsg(m);
}
Beispiel #11
0
static void
send_ssh_cmsg_session_key(Conn *c)
{
	int i, n, buflen, serverkeylen, hostkeylen;
	mpint *b;
	uchar *buf;
	Msg *m;
	RSApub *ksmall, *kbig;

	m = allocmsg(c, SSH_CMSG_SESSION_KEY, 2048);
	putbyte(m, c->cipher->id);
	putbytes(m, c->cookie, COOKIELEN);

	serverkeylen = mpsignif(c->serverkey->n);
	hostkeylen = mpsignif(c->hostkey->n);
	ksmall = kbig = nil;
	if(serverkeylen+128 <= hostkeylen){
		ksmall = c->serverkey;
		kbig = c->hostkey;
	}else if(hostkeylen+128 <= serverkeylen){
		ksmall = c->hostkey;
		kbig = c->serverkey;
	}else
		error("server session and host keys do not differ by at least 128 bits");
	
	buflen = (mpsignif(kbig->n)+7)/8;
	buf = emalloc(buflen);

	debug(DBG_CRYPTO, "session key is %.*H\n", SESSKEYLEN, c->sesskey);
	memmove(buf, c->sesskey, SESSKEYLEN);
	for(i = 0; i < SESSIDLEN; i++)
		buf[i] ^= c->sessid[i];
	debug(DBG_CRYPTO, "munged session key is %.*H\n", SESSKEYLEN, buf);

	b = rsaencryptbuf(ksmall, buf, SESSKEYLEN);
	n = (mpsignif(ksmall->n)+7) / 8;
	mptoberjust(b, buf, n);
	mpfree(b);
	debug(DBG_CRYPTO, "encrypted with ksmall is %.*H\n", n, buf);

	b = rsaencryptbuf(kbig, buf, n);
	putmpint(m, b);
	debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b);
	mpfree(b);

	memset(buf, 0, buflen);
	free(buf);

	putlong(m, c->flags);
	sendmsg(m);
}
Beispiel #12
0
void
handleagentoclose(Msg *m)
{
	uint32_t local;

	assert(m->type == SSH_MSG_CHANNEL_OUTPUT_CLOSED);
	local = getlong(m);
	debug(DBG_AUTH, "agent close %d\n", local);
	if(local < nelem(achan)){
		debug(DBG_AUTH, "\tlocal %d is remote %d\n", local, achan[local].chan);
		if(achan[local].needclosed){
			achan[local].needclosed = 0;
			m = allocmsg(m->c, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
			putlong(m, achan[local].chan);
			sendmsg(m);
		}
	}
}
Beispiel #13
0
static void
send_ssh_smsg_public_key(Conn *c)
{
	int i;
	Msg *m;

	m = allocmsg(c, SSH_SMSG_PUBLIC_KEY, 2048);
	putbytes(m, c->cookie, COOKIELEN);
	putRSApub(m, c->serverkey);
	putRSApub(m, c->hostkey);
	putlong(m, c->flags);

	for(i=0; i<c->nokcipher; i++)
		c->ciphermask |= 1<<c->okcipher[i]->id;
	putlong(m, c->ciphermask);
	for(i=0; i<c->nokauthsrv; i++)
		c->authmask |= 1<<c->okauthsrv[i]->id;
	putlong(m, c->authmask);

	sendmsg(m);
}
Beispiel #14
0
void
requestpty(Conn *c)
{
	char *term;
	int nrow, ncol, width, height;
	Msg *m;

	m = allocmsg(c, SSH_CMSG_REQUEST_PTY, 1024);
	if((term = getenv("TERM")) == nil)
		term = "9term";
	putstring(m, term);

	readgeom(&nrow, &ncol, &width, &height);
	putlong(m, nrow);	/* characters */
	putlong(m, ncol);
	putlong(m, width);	/* pixels */
	putlong(m, height);

	if(rawhack)
		putbytes(m, rawptyopt, sizeof rawptyopt);
	else
		putbytes(m, ptyopt, sizeof ptyopt);

	sendmsg(m);

	m = recvmsg(c, 0);
	switch(m->type){
	case SSH_SMSG_SUCCESS:
		debug(DBG_IO, "PTY allocated\n");
		break;
	case SSH_SMSG_FAILURE:
		debug(DBG_IO, "PTY allocation failed\n");
		break;
	default:
		badmsg(m, 0);
	}
	free(m);
}
Beispiel #15
0
void
handleagentieof(Msg *m)
{
	uint32_t local;

	assert(m->type == SSH_MSG_CHANNEL_INPUT_EOF);
	local = getlong(m);
	debug(DBG_AUTH, "agent close %d\n", local);
	if(local < nelem(achan)){
		debug(DBG_AUTH, "\tlocal %d is remote %d\n", local, achan[local].chan);
		achan[local].open = 0;
/*
		m = allocmsg(m->c, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
		putlong(m, achan[local].chan);
		sendmsg(m);
*/
		if(achan[local].needeof){
			achan[local].needeof = 0;
			m = allocmsg(m->c, SSH_MSG_CHANNEL_INPUT_EOF, 4);
			putlong(m, achan[local].chan);
			sendmsg(m);
		}
	}
}
Beispiel #16
0
void
handlefullmsg(Conn *c, Achan *a)
{
	int i;
	uint32_t chan, len, n, rt;
	uint8_t type;
	Msg *m, mm;
	Msg *r;
	Key *k;
	int nk;
	mpint *mod, *ek, *chal;
	uint8_t sessid[16];
	uint8_t chalbuf[32];
	uint8_t digest[16];
	DigestState *s;
	static int first;

	assert(a->len == a->ndata);

	chan = a->chan;
	mm.rp = a->data;
	mm.ep = a->data+a->ndata;
	mm.c = c;
	m = &mm;

	type = getbyte(m);

	if(first == 0){
		first++;
		fmtinstall('H', encodefmt);
	}

	switch(type){
	default:
		debug(DBG_AUTH, "unknown msg type\n");
	Failure:
		debug(DBG_AUTH, "agent sending failure\n");
		r = allocmsg(m->c, SSH_MSG_CHANNEL_DATA, 13);
		putlong(r, chan);
		putlong(r, 5);
		putlong(r, 1);
		putbyte(r, SSH_AGENT_FAILURE);
		sendmsg(r);
		return;

	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
		debug(DBG_AUTH, "agent request identities\n");
		nk = listkeys(&k);
		if(nk < 0)
			goto Failure;
		len = 1+4;	/* type, nk */
		for(i=0; i<nk; i++){
			len += 4;
			len += 2+(mpsignif(k[i].ek)+7)/8;
			len += 2+(mpsignif(k[i].mod)+7)/8;
			len += 4+strlen(k[i].comment);
		}
		r = allocmsg(m->c, SSH_MSG_CHANNEL_DATA, 12+len);
		putlong(r, chan);
		putlong(r, len+4);
		putlong(r, len);
		putbyte(r, SSH_AGENT_RSA_IDENTITIES_ANSWER);
		putlong(r, nk);
		for(i=0; i<nk; i++){
			debug(DBG_AUTH, "\t%B %B %s\n", k[i].ek, k[i].mod, k[i].comment);
			putlong(r, mpsignif(k[i].mod));
			putmpint(r, k[i].ek);
			putmpint(r, k[i].mod);
			putstring(r, k[i].comment);
			mpfree(k[i].ek);
			mpfree(k[i].mod);
			free(k[i].comment);
		}
		free(k);
		sendmsg(r);
		break;

	case SSH_AGENTC_RSA_CHALLENGE:
		n = getlong(m);
		USED(n);	/* number of bits in key; who cares? */
		ek = getmpint(m);
		mod = getmpint(m);
		chal = getmpint(m);
		memmove(sessid, getbytes(m, 16), 16);
		rt = getlong(m);
		debug(DBG_AUTH, "agent challenge %B %B %B %ud (%p %p)\n",
			ek, mod, chal, rt, m->rp, m->ep);
		if(rt != 1 || dorsa(mod, ek, chal, chalbuf) < 0){
			mpfree(ek);
			mpfree(mod);
			mpfree(chal);
			goto Failure;
		}
		s = md5(chalbuf, 32, nil, nil);
		md5(sessid, 16, digest, s);
		r = allocmsg(m->c, SSH_MSG_CHANNEL_DATA, 12+1+16);
		putlong(r, chan);
		putlong(r, 4+16+1);
		putlong(r, 16+1);
		putbyte(r, SSH_AGENT_RSA_RESPONSE);
		putbytes(r, digest, 16);
		debug(DBG_AUTH, "digest %.16H\n", digest);
		sendmsg(r);
		mpfree(ek);
		mpfree(mod);
		mpfree(chal);
		return;

	case SSH_AGENTC_ADD_RSA_IDENTITY:
		goto Failure;
/*
		n = getlong(m);
		pubmod = getmpint(m);
		pubexp = getmpint(m);
		privexp = getmpint(m);
		pinversemodq = getmpint(m);
		p = getmpint(m);
		q = getmpint(m);
		comment = getstring(m);
		add to factotum;
		send SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE;
*/

	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
		goto Failure;
/*
		n = getlong(m);
		pubmod = getmpint(m);
		pubexp = getmpint(m);
		tell factotum to del key
		send SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE;
*/
	}
}
Beispiel #17
0
static int
authrsafn(Conn *c)
{
	uint8_t chalbuf[32+SESSIDLEN], response[MD5dlen];
	char *s, *p;
	int afd, ret;
	AuthRpc *rpc;
	Msg *m;
	mpint *chal, *decr, *unpad, *mod;

	debug(DBG_AUTH, "rsa!\n");

	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
		debug(DBG_AUTH, "open /mnt/factotum/rpc: %r\n");
		return -1;
	}
	if((rpc = auth_allocrpc(afd)) == nil){
		debug(DBG_AUTH, "auth_allocrpc: %r\n");
		close(afd);
		return -1;
	}
	s = "proto=rsa role=client";
	if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){
		debug(DBG_AUTH, "auth_rpc start %s failed: %r\n", s);
		auth_freerpc(rpc);
		close(afd);
		return -1;
	}

	ret = -1;
	debug(DBG_AUTH, "trying factotum rsa keys\n");
	while(auth_rpc(rpc, "read", nil, 0) == ARok){
		debug(DBG_AUTH, "try %s\n", (char*)rpc->arg);
		mod = strtomp(rpc->arg, nil, 16, nil);
		m = allocmsg(c, SSH_CMSG_AUTH_RSA, 16+(mpsignif(mod)+7/8));
		putmpint(m, mod);
		sendmsg(m);
		mpfree(mod);
		m = recvmsg(c, -1);
		switch(m->type){
		case SSH_SMSG_FAILURE:
			debug(DBG_AUTH, "\tnot accepted %s\n",
			      (char*)rpc->arg);
			free(m);
			continue;
		default:
			badmsg(m, 0);
		case SSH_SMSG_AUTH_RSA_CHALLENGE:
			break;
		}
		chal = getmpint(m);
		debug(DBG_AUTH, "\tgot challenge %B\n", chal);
		free(m);
		p = mptoa(chal, 16, nil, 0);
		mpfree(chal);
		if(p == nil){
			debug(DBG_AUTH, "\tmptoa failed: %r\n");
			unpad = mpnew(0);
			goto Keepgoing;
		}
		if(auth_rpc(rpc, "write", p, strlen(p)) != ARok){
			debug(DBG_AUTH, "\tauth_rpc write failed: %r\n");
			free(p);
			unpad = mpnew(0);	/* it will fail, we'll go round again */
			goto Keepgoing;
		}
		free(p);
		if(auth_rpc(rpc, "read", nil, 0) != ARok){
			debug(DBG_AUTH, "\tauth_rpc read failed: %r\n");
			unpad = mpnew(0);
			goto Keepgoing;
		}
		decr = strtomp(rpc->arg, nil, 16, nil);
		debug(DBG_AUTH, "\tdecrypted %B\n", decr);
		unpad = rsaunpad(decr);
		debug(DBG_AUTH, "\tunpadded %B\n", unpad);
		mpfree(decr);
	Keepgoing:
		mptoberjust(unpad, chalbuf, 32);
		mpfree(unpad);
		debug(DBG_AUTH, "\trjusted %.*H\n", 32, chalbuf);
		memmove(chalbuf+32, c->sessid, SESSIDLEN);
		debug(DBG_AUTH, "\tappend sesskey %.*H\n", 32, chalbuf);
		md5(chalbuf, 32+SESSIDLEN, response, nil);
		m = allocmsg(c, SSH_CMSG_AUTH_RSA_RESPONSE, MD5dlen);
		putbytes(m, response, MD5dlen);
		sendmsg(m);

		m = recvmsg(c, -1);
		switch(m->type){
		case SSH_SMSG_FAILURE:
			free(m);
			continue;
		default:
			badmsg(m, 0);
		case SSH_SMSG_SUCCESS:
			break;
		}
		ret = 0;
		break;
	}
	auth_freerpc(rpc);
	close(afd);
	return ret;
}
Beispiel #18
0
void
startcmd(Conn *c, char *cmd, int *kidpid, int *kidin)
{
	int i, pid, kpid;
	int pfd[3][2];
	char *dir;
	char *sysname, *tz;
	Msg *m;
	Waitmsg *w;

	for(i=0; i<3; i++)
		if(pipe(pfd[i]) < 0)
			sysfatal("pipe: %r");

	sysname = getenv("sysname");
	tz = getenv("timezone");

	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
	case -1:
		sysfatal("fork: %r");
	case 0:
		switch(kpid = rfork(RFPROC|RFNOTEG|RFENVG|RFFDG)){
		case -1:
			sysfatal("fork: %r");
		case 0:
			for(i=0; i<3; i++){
				if(dup(pfd[i][1], i) < 0)
					sysfatal("dup: %r");
				close(pfd[i][0]);
				close(pfd[i][1]);
			}
			putenv("user", c->user);
			if(sysname)
				putenv("sysname", sysname);
			if(tz)
				putenv("tz", tz);
	
			dir = smprint("/usr/%s", c->user);
			if(dir == nil || chdir(dir) < 0)
				chdir("/");
			if(cmd){
				putenv("service", "rx");
				execl("/bin/rc", "rc", "-lc", cmd, nil);
				sysfatal("cannot exec /bin/rc: %r");
			}else{
				putenv("service", "con");
				execl("/bin/ip/telnetd", "telnetd", "-tn", nil);
				sysfatal("cannot exec /bin/ip/telnetd: %r");
			}
		default:
			*kidpid = kpid;
			rendezvous(kidpid, 0);
			for(;;){
				if((w = wait()) == nil)
					sysfatal("wait: %r");
				if(w->pid == kpid)
					break;
				free(w);
			}
			if(w->msg[0]){
				m = allocmsg(c, SSH_MSG_DISCONNECT, 4+strlen(w->msg));
				putstring(m, w->msg);
				sendmsg(m);
			}else{
				m = allocmsg(c, SSH_SMSG_EXITSTATUS, 4);
				putlong(m, 0);
				sendmsg(m);
			}
			for(i=0; i<3; i++)
				close(pfd[i][0]);
			free(w);
			exits(nil);	
			break;
		}
	default:
		atexitkill(pid);
		rendezvous(kidpid, 0);
		break;
	}

	for(i=0; i<3; i++)
		close(pfd[i][1]);

	copyout(c, pfd[1][0], SSH_SMSG_STDOUT_DATA);
	copyout(c, pfd[2][0], SSH_SMSG_STDERR_DATA);
	*kidin = pfd[0][0];
}
Beispiel #19
0
void
fromnet(Conn *c)
{
	int infd, kidpid, n;
	char *cmd;
	Msg *m;

	infd = kidpid = -1;
	for(;;){
		m = recvmsg(c, -1);
		if(m == nil)
			exits(nil);
		switch(m->type){
		default:
			//badmsg(m, 0);
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
			break;

		case SSH_MSG_DISCONNECT:
			sysfatal("client disconnected");

		case SSH_CMSG_REQUEST_PTY:
			sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
			break;

		case SSH_CMSG_X11_REQUEST_FORWARDING:
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
			break;

		case SSH_CMSG_MAX_PACKET_SIZE:
			maxmsg = getlong(m);
			sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
			break;

		case SSH_CMSG_REQUEST_COMPRESSION:
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
			break;

		case SSH_CMSG_EXEC_SHELL:
			startcmd(c, nil, &kidpid, &infd);
			goto InteractiveMode;

		case SSH_CMSG_EXEC_CMD:
			cmd = getstring(m);
			startcmd(c, cmd, &kidpid, &infd);
			goto InteractiveMode;
		}
		free(m);
	}

InteractiveMode:
	for(;;){
		free(m);
		m = recvmsg(c, -1);
		if(m == nil)
			exits(nil);
		switch(m->type){
		default:
			badmsg(m, 0);

		case SSH_MSG_DISCONNECT:
			postnote(PNGROUP, kidpid, "hangup");
			sysfatal("client disconnected");

		case SSH_CMSG_STDIN_DATA:
			if(infd != 0){
				n = getlong(m);
				write(infd, getbytes(m, n), n);
			}
			break;

		case SSH_CMSG_EOF:
			close(infd);
			infd = -1;
			break;

		case SSH_CMSG_EXIT_CONFIRMATION:
			/* sent by some clients as dying breath */
			exits(nil);
	
		case SSH_CMSG_WINDOW_SIZE:
			/* we don't care */
			break;
		}
	}
}
Beispiel #20
0
void
main(int argc, char **argv)
{
	int i, dowinchange, fd, usepty;
	char *host, *cmd, *user, *p;
	char *f[16];
	Conn c;
	Msg *m;

	fmtinstall('B', mpfmt);
	fmtinstall('H', encodefmt);
	atexit(atexitkiller);
	atexitkill(getpid());

	dowinchange = 0;
	if(getenv("LINES"))
		dowinchange = 1;
	usepty = -1;
	user = nil;
	ARGBEGIN{
	case 'B':	/* undocumented, debugging */
		doabort = 1;
		break;
	case 'D':	/* undocumented, debugging */
		debuglevel = strtol(EARGF(usage()), nil, 0);
		break;
	case 'l':	/* deprecated */
	case 'u':
		user = EARGF(usage());
		break;
	case 'a':	/* used by Unix scp implementations; we must ignore them. */
	case 'x':
		break;

	case 'A':
		authlist = EARGF(usage());
		break;
	case 'C':
		cooked = 1;
		break;
	case 'c':
		cipherlist = EARGF(usage());
		break;
	case 'f':
		forwardagent = 1;
		break;
	case 'I':
		interactive = 0;
		break;
	case 'i':
		interactive = 1;
		break;
	case 'm':
		usemenu = 0;
		break;
	case 'P':
		usepty = 0;
		break;
	case 'p':
		usepty = 1;
		break;
	case 'R':
		rawhack = 1;
		break;
	case 'r':
		crstrip = 1;
		break;
	default:
		usage();
	}ARGEND

	if(argc < 1)
		usage();

	host = argv[0];

	cmd = nil;
	if(argc > 1)
		cmd = buildcmd(argc-1, argv+1);

	if((p = strchr(host, '@')) != nil){
		*p++ = '\0';
		user = host;
		host = p;
	}
	if(user == nil)
		user = getenv("user");
	if(user == nil)
		sysfatal("cannot find user name");

	privatefactotum();
	if(interactive==-1)
		interactive = isatty(0);

	if((fd = dial(netmkaddr(host, "tcp", "ssh"), nil, nil, nil)) < 0)
		sysfatal("dialing %s: %r", host);

	memset(&c, 0, sizeof c);
	c.interactive = interactive;
	c.fd[0] = c.fd[1] = fd;
	c.user = user;
	c.host = host;
	setaliases(&c, host);

	c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", ");
	c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher);
	for(i=0; i<c.nokcipher; i++)
		c.okcipher[i] = findcipher(f[i], allcipher, nelem(allcipher));

	c.nokauth = getfields(authlist, f, nelem(f), 1, ", ");
	c.okauth = emalloc(sizeof(Auth*)*c.nokauth);
	for(i=0; i<c.nokauth; i++)
		c.okauth[i] = findauth(f[i], allauth, nelem(allauth));

	sshclienthandshake(&c);

	if(forwardagent){
		if(startagent(&c) < 0)
			forwardagent = 0;
	}
	if(usepty == -1)
		usepty = cmd==nil;
	if(usepty)
		requestpty(&c);
	if(cmd){
		m = allocmsg(&c, SSH_CMSG_EXEC_CMD, 4+strlen(cmd));
		putstring(m, cmd);
	}else
		m = allocmsg(&c, SSH_CMSG_EXEC_SHELL, 0);
	sendmsg(m);

	fromstdin(&c);
	rfork(RFNOTEG);	/* only fromstdin gets notes */
	if(dowinchange)
		winchanges(&c);
	fromnet(&c);
	exits(0);
}
Beispiel #21
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);
}