⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmsg.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "ssh.h"static voidrecv_ssh_smsg_public_key(Conn *c){	Msg *m;	m = recvmsg(c, SSH_SMSG_PUBLIC_KEY);	memmove(c->cookie, getbytes(m, COOKIELEN), COOKIELEN);	c->serverkey = getRSApub(m);	c->hostkey = getRSApub(m);	c->flags = getlong(m);	c->ciphermask = getlong(m);	c->authmask = getlong(m);	free(m);}static voidsend_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);}static intauthuser(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 %#x, 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=%#x)\n", c->authmask);	return -1;}static charask(Conn *c, char *answers, char *question){	int fd;	char buf[256];	if(!c->interactive)		return answers[0];	if((fd = open("/dev/cons", ORDWR)) < 0)		return answers[0];	fprint(fd, "%s", question);	if(read(fd, buf, 256) <= 0 || buf[0]=='\n'){		close(fd);		return answers[0];	}	close(fd);	return buf[0];}static voidcheckkey(Conn *c){	char *home, *keyfile;	debug(DBG_CRYPTO, "checking key %B %B\n", c->hostkey->n, c->hostkey->ek);	switch(findkey("/sys/lib/ssh/keyring", c->aliases, c->hostkey)){	default:		abort();	case KeyOk:		return;	case KeyWrong:		fprint(2, "server presented public key different than expected\n");		fprint(2, "(expected key in /sys/lib/ssh/keyring).  will not continue.\n");		error("bad server key");	case NoKey:	case NoKeyFile:		break;	}	home = getenv("home");	if(home == nil){		fprint(2, "server %s not on keyring; will not continue.\n", c->host);		error("bad server key");	}		keyfile = smprint("%s/lib/keyring", home);	if(keyfile == nil)		error("out of memory");	switch(findkey(keyfile, c->aliases, c->hostkey)){	default:		abort();	case KeyOk:		return;	case KeyWrong:		fprint(2, "server %s presented public key different than expected\n", c->host);		fprint(2, "(expected key in %s).  will not continue.\n", keyfile);		fprint(2, "this could be a man-in-the-middle attack.\n");		switch(ask(c, "eri", "replace key in keyfile (r), continue without replacing key (c), or exit (e) [e]")){		case 'e':			error("bad key");		case 'r':			if(replacekey(keyfile, c->aliases, c->hostkey) < 0)				error("replacekey: %r");			break;		case 'c':			break;		}		return;	case NoKey:	case NoKeyFile:		fprint(2, "server %s not on keyring.\n", c->host);		switch(ask(c, "eac", "add key to keyfile (a), continue without adding key (c), or exit (e) [e]")){		case 'e':			error("bad key");		case 'a':			if(appendkey(keyfile, c->aliases, c->hostkey) < 0)				error("appendkey: %r");			break;		case 'c':			break;		}		return;	}}voidsshclienthandshake(Conn *c){	char buf[128], *p;	int i;	Msg *m;	/* receive id string */	if(readstrnl(c->fd[0], buf, sizeof buf) < 0)		error("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 != '-')		error("protocol mismatch; got %s, need SSH-1.x for x>=5", buf);	/* send id string */	fprint(c->fd[1], "SSH-1.5-Plan 9\n");	recv_ssh_smsg_public_key(c);	checkkey(c);	for(i=0; i<SESSKEYLEN; i++)		c->sesskey[i] = fastrand();	c->cipher = nil;	for(i=0; i<c->nokcipher; i++)		if((1<<c->okcipher[i]->id) & c->ciphermask){			c->cipher = c->okcipher[i];			break;		}	if(c->cipher == nil)		error("can't agree on ciphers: remote side supports %#lux", c->ciphermask);	calcsessid(c);	send_ssh_cmsg_session_key(c);	c->cstate = (*c->cipher->init)(c, 0);		/* turns on encryption */	m = recvmsg(c, SSH_SMSG_SUCCESS);	free(m);		if(authuser(c) < 0)		error("client authentication failed");}static intintgetenv(char *name, int def){	char *s;	int n, val;	val = def;	if((s = getenv(name))!=nil){		if((n=atoi(s)) > 0)			val = n;		free(s);	}	return val;}/* * assumes that if you care, you're running under vt * and therefore these are set. */intreadgeom(int *nrow, int *ncol, int *width, int *height){	static int fd = -1;	char buf[64];	if(fd < 0 && (fd = open("/dev/wctl", OREAD)) < 0)		return -1;	/* wait for event, but don't care what it says */	if(read(fd, buf, sizeof buf) < 0)		return -1;	*nrow = intgetenv("LINES", 24);	*ncol = intgetenv("COLS", 80);	*width = intgetenv("XPIXELS", 640);	*height = intgetenv("YPIXELS", 480);	return 0;}voidsendwindowsize(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);}/* * In each option line, the first byte is the option number * and the second is either a boolean bit or actually an * ASCII code. */static uchar ptyopt[] ={	0x01, 0x7F,	/* interrupt = DEL */	0x02, 0x11,	/* quit = ^Q */	0x03, 0x08,	/* backspace = ^H */	0x04, 0x15,	/* line kill = ^U */	0x05, 0x04,	/* EOF = ^D */	0x20, 0x00,	/* don't strip high bit */	0x48, 0x01,	/* give us CRs */	0x00,		/* end options */};static uchar rawptyopt[] = {	30,	0,		/* ignpar */	31,	0,		/* parmrk */	32,	0,		/* inpck */	33,	0,		/* istrip */	34,	0,		/* inlcr */	35,	0,		/* igncr */	36,	0,		/* icnrl */	37,	0,		/* iuclc */	38,	0,		/* ixon */	39,	1,		/* ixany */	40,	0,		/* ixoff */	41,	0,		/* imaxbel */	50,	0,		/* isig: intr, quit, susp processing */	51,	0,		/* icanon: erase and kill processing */	52,	0,		/* xcase */	53,	0,		/* echo */	57,	0,		/* noflsh */	58,	0,		/* tostop */	59,	0,		/* iexten: impl defined control chars */	70,	0,		/* opost */	0x00,};voidrequestpty(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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -