360 lines · 7.0 KB · C
RawDownload
/*  * 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 <bio.h>#include "ssh2.h"		/* ugh */ #define MYID "SSH-2.0-Plan9" #pragma varargck type "M" mpint* enum {	Server =	0,	Client, 	Maxpktpay =	35000, 	/* qid.path components: level (2), type (4), conn (7), chan (7) */	Connshift =	7,	MAXCONN =	1 << Connshift,		/* also Maxchan */	Chanmask =	MAXCONN - 1,	Connmask =	Chanmask, 	Qtypeshift =	2 * Connshift,		/* conn + chan */ 	Qroot =		0,	Qclone =	1 << Qtypeshift,	Qctl =		2 << Qtypeshift,	Qdata =		3 << Qtypeshift,	Qlisten =	4 << Qtypeshift,	Qlocal =	5 << Qtypeshift,	Qreqrem =	6 << Qtypeshift,	/* request or remote */	Qstatus =	7 << Qtypeshift,	Qtcp =		8 << Qtypeshift,	Qtypemask =	017 << Qtypeshift, 	Levshift =	Qtypeshift + 4, 	/* levels of /net/ssh hierarchy */	Top =		0,	Connection,	Subchannel,}; /* * The stylistic anomaly with these names of unbounded length * is a result of following the RFCs in using the same names for * these constants.  I did that to make it easier to search and * cross-reference between the code and the RFCs. */enum {					/* SSH2 Protocol Packet Types */	SSH_MSG_DISCONNECT =		1,	SSH_MSG_IGNORE =		2,	SSH_MSG_UNIMPLEMENTED,	SSH_MSG_DEBUG,	SSH_MSG_SERVICE_REQUEST,	SSH_MSG_SERVICE_ACCEPT, 	SSH_MSG_KEXINIT =		20,	SSH_MSG_NEWKEYS, 	SSH_MSG_KEXDH_INIT =		30,	SSH_MSG_KEXDH_REPLY, 	SSH_MSG_USERAUTH_REQUEST =	50,	SSH_MSG_USERAUTH_FAILURE,	SSH_MSG_USERAUTH_SUCCESS,	SSH_MSG_USERAUTH_BANNER, 	SSH_MSG_USERAUTH_PK_OK =	60,	SSH_MSG_USERAUTH_PASSWD_CHANGEREQ = 60, 	SSH_MSG_GLOBAL_REQUEST =	80,	SSH_MSG_REQUEST_SUCCESS,	SSH_MSG_REQUEST_FAILURE, 	SSH_MSG_CHANNEL_OPEN =		90,	SSH_MSG_CHANNEL_OPEN_CONFIRMATION,	SSH_MSG_CHANNEL_OPEN_FAILURE,	SSH_MSG_CHANNEL_WINDOW_ADJUST,	SSH_MSG_CHANNEL_DATA,	SSH_MSG_CHANNEL_EXTENDED_DATA,	SSH_MSG_CHANNEL_EOF,	SSH_MSG_CHANNEL_CLOSE,	SSH_MSG_CHANNEL_REQUEST,	SSH_MSG_CHANNEL_SUCCESS,	SSH_MSG_CHANNEL_FAILURE,}; enum {				/* SSH2 reason codes */	SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1,	SSH_DISCONNECT_PROTOCOL_ERROR,	SSH_DISCONNECT_KEY_EXCHANGE_FAILED,	SSH_DISCONNECT_RESERVED,	SSH_DISCONNECT_MAC_ERROR,	SSH_DISCONNECT_COMPRESSION_ERROR,	SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,	SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,	SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE,	SSH_DISCONNECT_CONNECTION_LOST,	SSH_DISCONNECT_BY_APPLICATION,	SSH_DISCONNECT_TOO_MANY_CONNECTIONS,	SSH_DISCONNECT_AUTH_CANCELLED_BY_USER,	SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,	SSH_DISCONNECT_ILLEGAL_USR_NAME, 	SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1,	SSH_OPEN_CONNECT_FAILED,	SSH_OPEN_UNKNOWN_CHANNEL_TYPE,	SSH_OPEN_RESOURCE_SHORTAGE,}; enum {				/* SSH2 type code */	SSH_EXTENDED_DATA_STDERR = 1,}; enum {				/* connection and channel states */	Empty = 0,	Allocated,	Initting,	Listening,	Opening,	Negotiating,	Authing,	Established,	Eof,	Closing,	Closed,}; enum {	NoKeyFile,	NoKey,	KeyWrong,	KeyOk,}; typedef struct Cipher Cipher;typedef struct CipherState CipherState;typedef struct Conn Conn;typedef struct Kex Kex;typedef struct MBox MBox;typedef struct PKA PKA;typedef struct Packet Packet;typedef struct Plist Plist;typedef struct SSHChan SSHChan; #pragma incomplete CipherState struct Plist {	Packet	*pack;	uchar	*st;	int	rem;	Plist	*next;}; struct SSHChan {	Rendez	r;			/* awaiting input? */	int	id;	int	otherid;	int	state;	int	waker;	int	conn;	ulong	rwindow;	ulong	twindow;	ulong	sent;	ulong	inrqueue;	char	*ann;	Req	*lreq; 	/* File* for each Qid type */	File	*dir;	File	*ctl;	File	*data;	File	*listen;	File	*request;	File	*status;	File	*tcp; 	Plist	*dataq;	Plist	*datatl;	Plist	*reqq;	Plist	*reqtl; 	Channel	*inchan;	Channel	*reqchan;	QLock	xmtlock;	Rendez	xmtrendez;}; struct Conn {	QLock	l;	Rendez	r;			/* awaiting input? */ 	Ioproc	*dio;	Ioproc	*cio;	Ioproc	*rio; 	int	state;	int	role;	int	id; 	char	*remote;	char	*user;	char	*password; 	char	*service;	char	*cap;	char	*authkey;	int	nchan; 	/* underlying tcp connection */	int	datafd;	int	ctlfd;	int	stifle;		/* flag: no i/o between listen and sshsession */	int	poisoned;	int	tcpconn; 	int	rpid; 	int	inseq;	int	outseq;	int	kexalg;	int	pkalg; 	int	cscrypt;	int	ncscrypt;	int	sccrypt;	int	nsccrypt; 	int	csmac;	int	ncsmac;	int	scmac;	int	nscmac; 	int	encrypt;	int	decrypt; 	int	outmac;	int	inmac; 	/* File* for each Qid type */	File	*dir;	File	*clonefile;	File	*ctlfile;	File	*datafile;	File	*listenfile;	File	*localfile;	File	*remotefile;	File	*statusfile;	File	*tcpfile; 	Packet	*skexinit;	Packet	*rkexinit;	mpint	*x;	mpint	*e;	int	got_sessid;	uchar	sessid[SHA1dlen]; 	uchar	c2siv[SHA1dlen*2];	uchar	nc2siv[SHA1dlen*2];	uchar	s2civ[SHA1dlen*2];	uchar	ns2civ[SHA1dlen*2]; 	uchar	c2sek[SHA1dlen*2];	uchar	nc2sek[SHA1dlen*2];	uchar	s2cek[SHA1dlen*2];	uchar	ns2cek[SHA1dlen*2]; 	uchar	c2sik[SHA1dlen*2];	uchar	nc2sik[SHA1dlen*2];	uchar	s2cik[SHA1dlen*2];	uchar	ns2cik[SHA1dlen*2]; 	char	*otherid;	uchar	*inik;	uchar	*outik;	CipherState *s2ccs;	CipherState *c2scs;	CipherState *enccs;	CipherState *deccs;	SSHChan	*chans[MAXCONN]; 	char	idstring[256];		/* max allowed by SSH spec */}; struct Packet {	Conn	*c;	ulong	rlength;	ulong	tlength;	uchar	nlength[4];	uchar	pad_len;	uchar	payload[Maxpktpay];}; struct Cipher {	char	*name;	int	blklen;	CipherState *(*init)(Conn*, int);	void	(*encrypt)(CipherState*, uchar*, int);	void	(*decrypt)(CipherState*, uchar*, int);}; struct Kex {	char	*name;	int	(*serverkex)(Conn *, Packet *);	int	(*clientkex1)(Conn *, Packet *);	int	(*clientkex2)(Conn *, Packet *);}; struct PKA {	char	*name;	Packet	*(*ks)(Conn *);	Packet	*(*sign)(Conn *, uchar *, int);	int	(*verify)(Conn *, uchar *, int, char *, char *, int);}; struct MBox {	Channel	*mchan;	char	*msg;	int	state;}; extern Cipher cipheraes128, cipheraes192, cipheraes256;extern Cipher cipherblowfish, cipher3des, cipherrc4;extern int debug;extern int sshkeychan[];extern Kex dh1sha1, dh14sha1;extern MBox keymbox;extern PKA rsa_pka, dss_pka, *pkas[]; /* pubkey.c */int appendkey(char *, char *, RSApub *);int findkey(char *, char *, RSApub *);RSApub *readpublickey(Biobuf *, char **);int replacekey(char *, char *, RSApub *); /* dh.c */void dh_init(PKA *[]); /* transport.c */void	add_block(Packet *, void *, int);void	add_byte(Packet *, char);void	add_mp(Packet *, mpint *);int	add_packet(Packet *, void *, int);void	add_string(Packet *, char *);void	add_uint32(Packet *, ulong);void	dump_packet(Packet *);int	finish_packet(Packet *);mpint	*get_mp(uchar *q);uchar	*get_string(Packet *, uchar *, char *, int, int *);ulong	get_uint32(Packet *, uchar **);void	init_packet(Packet *);Packet	*new_packet(Conn *);int	undo_packet(Packet *);