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

📄 ssh.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* * Construct an SSH2 packet and add it to a deferred data block. * Useful for sending multiple packets in a single sk_write() call, * to prevent a traffic-analysing listener from being able to work * out the length of any particular packet (such as the password * packet). *  * Note that because SSH2 sequence-numbers its packets, this can * NOT be used as an m4-style `defer' allowing packets to be * constructed in one order and sent in another. */static void ssh2_pkt_defer(Ssh ssh){    int len = ssh2_pkt_construct(ssh);    if (ssh->deferred_len + len > ssh->deferred_size) {	ssh->deferred_size = ssh->deferred_len + len + 128;	ssh->deferred_send_data = sresize(ssh->deferred_send_data,					  ssh->deferred_size,					  unsigned char);    }    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);    ssh->deferred_len += len;}/* * Send the whole deferred data block constructed by * ssh2_pkt_defer() or SSH1's defer_packet(). */static void ssh_pkt_defersend(Ssh ssh){    int backlog;    backlog = sk_write(ssh->s, (char *)ssh->deferred_send_data,		       ssh->deferred_len);    ssh->deferred_len = ssh->deferred_size = 0;    sfree(ssh->deferred_send_data);    ssh->deferred_send_data = NULL;    if (backlog > SSH_MAX_BACKLOG)	ssh_throttle_all(ssh, 1, backlog);}#if 0void bndebug(char *string, Bignum b){    unsigned char *p;    int i, len;    p = ssh2_mpint_fmt(b, &len);    debug(("%s", string));    for (i = 0; i < len; i++)	debug((" %02x", p[i]));    debug(("\n"));    sfree(p);}#endifstatic void sha_mpint(SHA_State * s, Bignum b){    unsigned char *p;    int len;    p = ssh2_mpint_fmt(b, &len);    sha_string(s, p, len);    sfree(p);}/* * Packet decode functions for both SSH1 and SSH2. */static unsigned long ssh_pkt_getuint32(Ssh ssh){    unsigned long value;    if (ssh->pktin.length - ssh->pktin.savedpos < 4)	return 0;		       /* arrgh, no way to decline (FIXME?) */    value = GET_32BIT(ssh->pktin.body + ssh->pktin.savedpos);    ssh->pktin.savedpos += 4;    return value;}static int ssh2_pkt_getbool(Ssh ssh){    unsigned long value;    if (ssh->pktin.length - ssh->pktin.savedpos < 1)	return 0;		       /* arrgh, no way to decline (FIXME?) */    value = ssh->pktin.body[ssh->pktin.savedpos] != 0;    ssh->pktin.savedpos++;    return value;}static void ssh_pkt_getstring(Ssh ssh, char **p, int *length){    int len;    *p = NULL;    *length = 0;    if (ssh->pktin.length - ssh->pktin.savedpos < 4)	return;    len = GET_32BIT(ssh->pktin.body + ssh->pktin.savedpos);    if (len < 0)	return;    *length = len;    ssh->pktin.savedpos += 4;    if (ssh->pktin.length - ssh->pktin.savedpos < *length)	return;    *p = (char *)(ssh->pktin.body + ssh->pktin.savedpos);    ssh->pktin.savedpos += *length;}static void *ssh_pkt_getdata(Ssh ssh, int length){    if (ssh->pktin.length - ssh->pktin.savedpos < length)	return NULL;    ssh->pktin.savedpos += length;    return ssh->pktin.body + (ssh->pktin.savedpos - length);}static int ssh1_pkt_getrsakey(Ssh ssh, struct RSAKey *key,			      unsigned char **keystr){    int j;    j = makekey(ssh->pktin.body + ssh->pktin.savedpos,		ssh->pktin.length - ssh->pktin.savedpos,		key, keystr, 0);    if (j < 0)	return FALSE;        ssh->pktin.savedpos += j;    assert(ssh->pktin.savedpos < ssh->pktin.length);    return TRUE;}static Bignum ssh1_pkt_getmp(Ssh ssh){    int j;    Bignum b;    j = ssh1_read_bignum(ssh->pktin.body + ssh->pktin.savedpos,			 ssh->pktin.length - ssh->pktin.savedpos, &b);    if (j < 0)	return NULL;    ssh->pktin.savedpos += j;    return b;}static Bignum ssh2_pkt_getmp(Ssh ssh){    char *p;    int length;    Bignum b;    ssh_pkt_getstring(ssh, &p, &length);    if (!p)	return NULL;    if (p[0] & 0x80) {	bombout(("internal error: Can't handle negative mpints"));	return NULL;    }    b = bignum_from_bytes((unsigned char *)p, length);    return b;}/* * Helper function to add an SSH2 signature blob to a packet. * Expects to be shown the public key blob as well as the signature * blob. Normally works just like ssh2_pkt_addstring, but will * fiddle with the signature packet if necessary for * BUG_SSH2_RSA_PADDING. */static void ssh2_add_sigblob(Ssh ssh, void *pkblob_v, int pkblob_len,			     void *sigblob_v, int sigblob_len){    unsigned char *pkblob = (unsigned char *)pkblob_v;    unsigned char *sigblob = (unsigned char *)sigblob_v;    /* dmemdump(pkblob, pkblob_len); */    /* dmemdump(sigblob, sigblob_len); */    /*     * See if this is in fact an ssh-rsa signature and a buggy     * server; otherwise we can just do this the easy way.     */    if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) &&	(GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {	int pos, len, siglen;	/*	 * Find the byte length of the modulus.	 */	pos = 4+7;		       /* skip over "ssh-rsa" */	pos += 4 + GET_32BIT(pkblob+pos);   /* skip over exponent */	len = GET_32BIT(pkblob+pos);   /* find length of modulus */	pos += 4;		       /* find modulus itself */	while (len > 0 && pkblob[pos] == 0)	    len--, pos++;	/* debug(("modulus length is %d\n", len)); */	/*	 * Now find the signature integer.	 */	pos = 4+7;		       /* skip over "ssh-rsa" */	siglen = GET_32BIT(sigblob+pos);	/* debug(("signature length is %d\n", siglen)); */	if (len != siglen) {	    unsigned char newlen[4];	    ssh2_pkt_addstring_start(ssh);	    ssh2_pkt_addstring_data(ssh, (char *)sigblob, pos);	    /* dmemdump(sigblob, pos); */	    pos += 4;		       /* point to start of actual sig */	    PUT_32BIT(newlen, len);	    ssh2_pkt_addstring_data(ssh, (char *)newlen, 4);	    /* dmemdump(newlen, 4); */	    newlen[0] = 0;	    while (len-- > siglen) {		ssh2_pkt_addstring_data(ssh, (char *)newlen, 1);		/* dmemdump(newlen, 1); */	    }	    ssh2_pkt_addstring_data(ssh, (char *)(sigblob+pos), siglen);	    /* dmemdump(sigblob+pos, siglen); */	    return;	}	/* Otherwise fall through and do it the easy way. */    }    ssh2_pkt_addstring_start(ssh);    ssh2_pkt_addstring_data(ssh, (char *)sigblob, sigblob_len);}/* * Examine the remote side's version string and compare it against * a list of known buggy implementations. */static void ssh_detect_bugs(Ssh ssh, char *vstring){    char *imp;			       /* pointer to implementation part */    imp = vstring;    imp += strcspn(imp, "-");    if (*imp) imp++;    imp += strcspn(imp, "-");    if (*imp) imp++;    ssh->remote_bugs = 0;    if (ssh->cfg.sshbug_ignore1 == FORCE_ON ||	(ssh->cfg.sshbug_ignore1 == AUTO &&	 (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||	  !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||	  !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") ||	  !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) {	/*	 * These versions don't support SSH1_MSG_IGNORE, so we have	 * to use a different defence against password length	 * sniffing.	 */	ssh->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;	logevent("We believe remote version has SSH1 ignore bug");    }    if (ssh->cfg.sshbug_plainpw1 == FORCE_ON ||	(ssh->cfg.sshbug_plainpw1 == AUTO &&	 (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {	/*	 * These versions need a plain password sent; they can't	 * handle having a null and a random length of data after	 * the password.	 */	ssh->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;	logevent("We believe remote version needs a plain SSH1 password");    }    if (ssh->cfg.sshbug_rsa1 == FORCE_ON ||	(ssh->cfg.sshbug_rsa1 == AUTO &&	 (!strcmp(imp, "Cisco-1.25")))) {	/*	 * These versions apparently have no clue whatever about	 * RSA authentication and will panic and die if they see	 * an AUTH_RSA message.	 */	ssh->remote_bugs |= BUG_CHOKES_ON_RSA;	logevent("We believe remote version can't handle RSA authentication");    }    if (ssh->cfg.sshbug_hmac2 == FORCE_ON ||	(ssh->cfg.sshbug_hmac2 == AUTO &&	 !wc_match("* VShell", imp) &&	 (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||	  wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||	  wc_match("2.1 *", imp)))) {	/*	 * These versions have the HMAC bug.	 */	ssh->remote_bugs |= BUG_SSH2_HMAC;	logevent("We believe remote version has SSH2 HMAC bug");    }    if (ssh->cfg.sshbug_derivekey2 == FORCE_ON ||	(ssh->cfg.sshbug_derivekey2 == AUTO &&	 !wc_match("* VShell", imp) &&	 (wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {	/*	 * These versions have the key-derivation bug (failing to	 * include the literal shared secret in the hashes that	 * generate the keys).	 */	ssh->remote_bugs |= BUG_SSH2_DERIVEKEY;	logevent("We believe remote version has SSH2 key-derivation bug");    }    if (ssh->cfg.sshbug_rsapad2 == FORCE_ON ||	(ssh->cfg.sshbug_rsapad2 == AUTO &&	 (wc_match("OpenSSH_2.[5-9]*", imp) ||	  wc_match("OpenSSH_3.[0-2]*", imp)))) {	/*	 * These versions have the SSH2 RSA padding bug.	 */	ssh->remote_bugs |= BUG_SSH2_RSA_PADDING;	logevent("We believe remote version has SSH2 RSA padding bug");    }    if (ssh->cfg.sshbug_pksessid2 == FORCE_ON ||	(ssh->cfg.sshbug_pksessid2 == AUTO &&	 wc_match("OpenSSH_2.[0-2]*", imp))) {	/*	 * These versions have the SSH2 session-ID bug in	 * public-key authentication.	 */	ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;	logevent("We believe remote version has SSH2 public-key-session-ID bug");    }    if (ssh->cfg.sshbug_dhgex2 == FORCE_ON) {	/*	 * User specified the SSH2 DH GEX bug.	 */	ssh->remote_bugs |= BUG_SSH2_DH_GEX;	logevent("We believe remote version has SSH2 DH group exchange bug");    }}static int do_ssh_init(Ssh ssh, unsigned char c){    struct do_ssh_init_state {	int vslen;	char version[10];	char *vstring;	int vstrsize;	int i;	int proto1, proto2;    };    crState(do_ssh_init_state);    crBegin(ssh->do_ssh_init_crstate);    /* Search for the string "SSH-" in the input. */    s->i = 0;    while (1) {	static const int transS[] = { 1, 2, 2, 1 };	static const int transH[] = { 0, 0, 3, 0 };	static const int transminus[] = { 0, 0, 0, -1 };	if (c == 'S')	    s->i = transS[s->i];	else if (c == 'H')	    s->i = transH[s->i];	else if (c == '-')	    s->i = transminus[s->i];	else	    s->i = 0;	if (s->i < 0)	    break;	crReturn(1);		       /* get another character */    }    s->vstrsize = 16;    s->vstring = snewn(s->vstrsize, char);    strcpy(s->vstring, "SSH-");    s->vslen = 4;    s->i = 0;    while (1) {	crReturn(1);		       /* get another char */	if (s->vslen >= s->vstrsize - 1) {	    s->vstrsize += 16;	    s->vstring = sresize(s->vstring, s->vstrsize, char);	}	s->vstring[s->vslen++] = c;	if (s->i >= 0) {	    if (c == '-') {		s->version[s->i] = '\0';		s->i = -1;	    } else if (s->i < sizeof(s->version) - 1)		s->version[s->i++] = c;	} else if (c == '\012')	    break;    }    ssh->agentfwd_enabled = FALSE;    ssh->rdpkt2_state.incoming_sequence = 0;    s->vstring[s->vslen] = 0;    s->vstring[strcspn(s->vstring, "\r\n")] = '\0';/* remove EOL chars */    {	char *vlog;	vlog = snewn(20 + s->vslen, char);	sprintf(vlog, "Server version: %s", s->vstring);	logevent(vlog);	sfree(vlog);    }    ssh_detect_bugs(ssh, s->vstring);    /*     * Decide which SSH protocol version to support.     */    /* Anything strictly below "2.0" means protocol 1 is supported. */    s->proto1 = ssh_versioncmp(s->version, "2.0") < 0;    /* Anything greater or equal to "1.99" means protocol 2 is supported. */    s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;    if (ssh->cfg.sshprot == 0 && !s->proto1) {	bombout(("SSH protocol version 1 required by user but not provided by server"));	crStop(0);    }    if (ssh->cfg.sshprot == 3 && !s->proto2) {	bombout(("SSH protocol version 2 required by user but not provided by server"));	crStop(0);    }    if (s->proto2 && (ssh->cfg.sshprot >= 2 || !s->proto1)) {	/*	 * Use v2 protocol.	 */	char verstring[80], vlog[100];	sp

⌨️ 快捷键说明

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