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

📄 ssh.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 5 页
字号:
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")))) {
	/*
	 * 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];
	sprintf(verstring, "SSH-2.0-%s", sshver);
	SHA_Init(&ssh->exhashbase);
	/*
	 * Hash our version string and their version string.
	 */
	sha_string(&ssh->exhashbase, verstring, strlen(verstring));
	sha_string(&ssh->exhashbase, s->vstring, strcspn(s->vstring, "\r\n"));
	sprintf(vlog, "We claim version: %s", verstring);
	logevent(vlog);
	strcat(verstring, "\012");
	logevent("Using SSH protocol version 2");
	sk_write(ssh->s, verstring, strlen(verstring));
	ssh->protocol = ssh2_protocol;
	ssh->version = 2;
	ssh->s_rdpkt = ssh2_rdpkt;
    } else {
	/*
	 * Use v1 protocol.
	 */
	char verstring[80], vlog[100];
	sprintf(verstring, "SSH-%s-%s",
		(ssh_versioncmp(s->version, "1.5") <= 0 ? s->version : "1.5"),
		sshver);
	sprintf(vlog, "We claim version: %s", verstring);
	logevent(vlog);
	strcat(verstring, "\012");

	logevent("Using SSH protocol version 1");
	sk_write(ssh->s, verstring, strlen(verstring));
	ssh->protocol = ssh1_protocol;
	ssh->version = 1;
	ssh->s_rdpkt = ssh1_rdpkt;
    }
    update_specials_menu(ssh->frontend);
    ssh->state = SSH_STATE_BEFORE_SIZE;

    sfree(s->vstring);

    crFinish(0);
}

static void ssh_gotdata(Ssh ssh, unsigned char *data, int datalen)
{
    crBegin(ssh->ssh_gotdata_crstate);

    /*
     * To begin with, feed the characters one by one to the
     * protocol initialisation / selection function do_ssh_init().
     * When that returns 0, we're done with the initial greeting
     * exchange and can move on to packet discipline.
     */
    while (1) {
	int ret;		       /* need not be kept across crReturn */
	if (datalen == 0)
	    crReturnV;		       /* more data please */
	ret = do_ssh_init(ssh, *data);
	data++;
	datalen--;
	if (ret == 0)
	    break;
    }

    /*
     * We emerge from that loop when the initial negotiation is
     * over and we have selected an s_rdpkt function. Now pass
     * everything to s_rdpkt, and then pass the resulting packets
     * to the proper protocol handler.
     */
    if (datalen == 0)
	crReturnV;
    while (1) {
	while (datalen > 0) {
	    if (ssh->s_rdpkt(ssh, &data, &datalen) == 0) {
		if (ssh->state == SSH_STATE_CLOSED) {
		    return;
		}
		ssh->protocol(ssh, NULL, 0, 1);
		if (ssh->state == SSH_STATE_CLOSED) {
		    return;
		}
	    }
	}
	crReturnV;
    }
    crFinishV;
}

static void ssh_do_close(Ssh ssh)
{
    int i;
    struct ssh_channel *c;

    ssh->state = 

⌨️ 快捷键说明

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