📄 sshconnect1.c
字号:
packet_write_wait(); type = packet_read(); if (type != SSH_SMSG_FAILURE && type != SSH_SMSG_AUTH_TIS_CHALLENGE) { packet_disconnect("Protocol error: got %d in response " "to SSH_CMSG_AUTH_TIS", type); } if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { debug("No challenge."); return 0; } challenge = packet_get_string(&clen); packet_check_eom(); snprintf(prompt, sizeof prompt, "%s%s", challenge, strchr(challenge, '\n') ? "" : "\nResponse: "); xfree(challenge); if (i != 0) error("Permission denied, please try again."); if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! " "Response will be transmitted in clear text."); response = read_passphrase(prompt, 0); if (strcmp(response, "") == 0) { xfree(response); break; } packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); ssh_put_password(response); memset(response, 0, strlen(response)); xfree(response); packet_send(); packet_write_wait(); type = packet_read(); if (type == SSH_SMSG_SUCCESS) return 1; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response " "to SSH_CMSG_AUTH_TIS_RESPONSE", type); } /* failure */ return 0;}/* * Tries to authenticate with plain passwd authentication. */static inttry_password_authentication(char *prompt){ int type, i; char *password; debug("Doing password authentication."); if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); for (i = 0; i < options.number_of_password_prompts; i++) { if (i != 0) error("Permission denied, please try again."); password = read_passphrase(prompt, 0); packet_start(SSH_CMSG_AUTH_PASSWORD); ssh_put_password(password); memset(password, 0, strlen(password)); xfree(password); packet_send(); packet_write_wait(); type = packet_read(); if (type == SSH_SMSG_SUCCESS) return 1; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to passwd auth", type); } /* failure */ return 0;}/* * SSH1 key exchange */voidssh_kex(char *host, struct sockaddr *hostaddr){ int i; BIGNUM *key; Key *host_key, *server_key; int bits, rbits; int ssh_cipher_default = SSH_CIPHER_3DES; u_char session_key[SSH_SESSION_KEY_LENGTH]; u_char cookie[8]; u_int supported_ciphers; u_int server_flags, client_flags; u_int32_t rand = 0; debug("Waiting for server public key."); /* Wait for a public key packet from the server. */ packet_read_expect(SSH_SMSG_PUBLIC_KEY); /* Get cookie from the packet. */ for (i = 0; i < 8; i++) cookie[i] = packet_get_char(); /* Get the public key. */ server_key = key_new(KEY_RSA1); bits = packet_get_int(); packet_get_bignum(server_key->rsa->e); packet_get_bignum(server_key->rsa->n); rbits = BN_num_bits(server_key->rsa->n); if (bits != rbits) { log("Warning: Server lies about size of server public key: " "actual size is %d bits vs. announced %d.", rbits, bits); log("Warning: This may be due to an old implementation of ssh."); } /* Get the host key. */ host_key = key_new(KEY_RSA1); bits = packet_get_int(); packet_get_bignum(host_key->rsa->e); packet_get_bignum(host_key->rsa->n); rbits = BN_num_bits(host_key->rsa->n); if (bits != rbits) { log("Warning: Server lies about size of server host key: " "actual size is %d bits vs. announced %d.", rbits, bits); log("Warning: This may be due to an old implementation of ssh."); } /* Get protocol flags. */ server_flags = packet_get_int(); packet_set_protocol_flags(server_flags); supported_ciphers = packet_get_int(); supported_authentications = packet_get_int(); packet_check_eom(); debug("Received server public key (%d bits) and host key (%d bits).", BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); if (verify_host_key(host, hostaddr, host_key) == -1) fatal("Host key verification failed."); client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; compute_session_id(session_id, cookie, host_key->rsa->n, server_key->rsa->n); /* Generate a session key. */ arc4random_stir(); /* * Generate an encryption key for the session. The key is a 256 bit * random number, interpreted as a 32-byte key, with the least * significant 8 bits being the first byte of the key. */ for (i = 0; i < 32; i++) { if (i % 4 == 0) rand = arc4random(); session_key[i] = rand & 0xff; rand >>= 8; } /* * According to the protocol spec, the first byte of the session key * is the highest byte of the integer. The session key is xored with * the first 16 bytes of the session id. */ if ((key = BN_new()) == NULL) fatal("respond_to_rsa_challenge: BN_new failed"); BN_set_word(key, 0); for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { BN_lshift(key, key, 8); if (i < 16) BN_add_word(key, session_key[i] ^ session_id[i]); else BN_add_word(key, session_key[i]); } /* * Encrypt the integer using the public key and host key of the * server (key with smaller modulus first). */ if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) { /* Public key has smaller modulus. */ if (BN_num_bits(host_key->rsa->n) < BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { fatal("respond_to_rsa_challenge: host_key %d < server_key %d + " "SSH_KEY_BITS_RESERVED %d", BN_num_bits(host_key->rsa->n), BN_num_bits(server_key->rsa->n), SSH_KEY_BITS_RESERVED); } rsa_public_encrypt(key, key, server_key->rsa); rsa_public_encrypt(key, key, host_key->rsa); } else { /* Host key has smaller modulus (or they are equal). */ if (BN_num_bits(server_key->rsa->n) < BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { fatal("respond_to_rsa_challenge: server_key %d < host_key %d + " "SSH_KEY_BITS_RESERVED %d", BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n), SSH_KEY_BITS_RESERVED); } rsa_public_encrypt(key, key, host_key->rsa); rsa_public_encrypt(key, key, server_key->rsa); } /* Destroy the public keys since we no longer need them. */ key_free(server_key); key_free(host_key); if (options.cipher == SSH_CIPHER_NOT_SET) { if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default)) options.cipher = ssh_cipher_default; } else if (options.cipher == SSH_CIPHER_ILLEGAL || !(cipher_mask_ssh1(1) & (1 << options.cipher))) { log("No valid SSH1 cipher, using %.100s instead.", cipher_name(ssh_cipher_default)); options.cipher = ssh_cipher_default; } /* Check that the selected cipher is supported. */ if (!(supported_ciphers & (1 << options.cipher))) fatal("Selected cipher type %.100s not supported by server.", cipher_name(options.cipher)); debug("Encryption type: %.100s", cipher_name(options.cipher)); /* Send the encrypted session key to the server. */ packet_start(SSH_CMSG_SESSION_KEY); packet_put_char(options.cipher); /* Send the cookie back to the server. */ for (i = 0; i < 8; i++) packet_put_char(cookie[i]); /* Send and destroy the encrypted encryption key integer. */ packet_put_bignum(key); BN_clear_free(key); /* Send protocol flags. */ packet_put_int(client_flags); /* Send the packet now. */ packet_send(); packet_write_wait(); debug("Sent encrypted session key."); /* Set the encryption key. */ packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher); /* We will no longer need the session key here. Destroy any extra copies. */ memset(session_key, 0, sizeof(session_key)); /* * Expect a success message from the server. Note that this message * will be received in encrypted form. */ packet_read_expect(SSH_SMSG_SUCCESS); debug("Received encrypted confirmation.");}/* * Authenticate user */voidssh_userauth1(const char *local_user, const char *server_user, char *host, Sensitive *sensitive){#ifdef KRB5 krb5_context context = NULL; krb5_auth_context auth_context = NULL;#endif int i, type; if (supported_authentications == 0) fatal("ssh_userauth1: server supports no auth methods"); /* Send the name of the user to log in as on the server. */ packet_start(SSH_CMSG_USER); packet_put_cstring(server_user); packet_send(); packet_write_wait(); /* * The server should respond with success if no authentication is * needed (the user has no password). Otherwise the server responds * with failure. */ type = packet_read(); /* check whether the connection was accepted without authentication. */ if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type);#ifdef KRB5 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && options.kerberos_authentication) { debug("Trying Kerberos v5 authentication."); if (try_krb5_authentication(&context, &auth_context)) { type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to Kerberos v5 auth", type); } }#endif /* KRB5 */#ifdef KRB4 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && options.kerberos_authentication) { debug("Trying Kerberos v4 authentication."); if (try_krb4_authentication()) { type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to Kerberos v4 auth", type); } }#endif /* KRB4 */ /* * Use rhosts authentication if running in privileged socket and we * do not wish to remain anonymous. */ if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) && options.rhosts_authentication) { debug("Trying rhosts authentication."); packet_start(SSH_CMSG_AUTH_RHOSTS); packet_put_cstring(local_user); packet_send(); packet_write_wait(); /* The server should respond with success or failure. */ type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to rhosts auth", type); } /* * Try .rhosts or /etc/hosts.equiv authentication with RSA host * authentication. */ if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) && options.rhosts_rsa_authentication) { for (i = 0; i < sensitive->nkeys; i++) { if (sensitive->keys[i] != NULL && sensitive->keys[i]->type == KEY_RSA1 && try_rhosts_rsa_authentication(local_user, sensitive->keys[i])) goto success; } } /* Try RSA authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_RSA)) && options.rsa_authentication) { /* * Try RSA authentication using the authentication agent. The * agent is tried first because no passphrase is needed for * it, whereas identity files may require passphrases. */ if (try_agent_authentication()) goto success; /* Try RSA authentication for each identity. */ for (i = 0; i < options.num_identity_files; i++) if (options.identity_keys[i] != NULL && options.identity_keys[i]->type == KEY_RSA1 && try_rsa_authentication(i)) goto success; } /* Try challenge response authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_TIS)) && options.challenge_response_authentication && !options.batch_mode) { if (try_challenge_response_authentication()) goto success; } /* Try password authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && options.password_authentication && !options.batch_mode) { char prompt[80]; snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", server_user, host); if (try_password_authentication(prompt)) goto success; } /* All authentication methods have failed. Exit with an error message. */ fatal("Permission denied."); /* NOTREACHED */ success:#ifdef KRB5 /* Try Kerberos v5 TGT passing. */ if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && options.kerberos_tgt_passing && context && auth_context) { if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); send_krb5_tgt(context, auth_context); } if (auth_context) krb5_auth_con_free(context, auth_context); if (context) krb5_free_context(context);#endif#ifdef AFS /* Try Kerberos v4 TGT passing if the server supports it. */ if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && options.kerberos_tgt_passing) { if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); send_krb4_tgt(); } /* Try AFS token passing if the server supports it. */ if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) && options.afs_token_passing && k_hasafs()) { if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! Token will be transmitted in the clear!"); send_afs_tokens(); }#endif /* AFS */ return; /* need statement after label */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -