- int i, len;
- BIGNUM *session_key_int;
- unsigned char session_key[SSH_SESSION_KEY_LENGTH];
- unsigned char check_bytes[8];
- char *user;
- unsigned int cipher_type, auth_mask, protocol_flags;
- int plen, slen;
- u_int32_t rand = 0;
-
- /* Generate check bytes that the client must send back in the user packet
- in order for it to be accepted; this is used to defy ip spoofing
- attacks. Note that this only works against somebody doing IP spoofing
- from a remote machine; any machine on the local network can still see
- outgoing packets and catch the random cookie. This only affects
- rhosts authentication, and this is one of the reasons why it is
- inherently insecure. */
- for (i = 0; i < 8; i++) {
- if (i % 4 == 0)
- rand = arc4random();
- check_bytes[i] = rand & 0xff;
- rand >>= 8;
- }
-
- /* Send our public key. We include in the packet 64 bits of random
- data that must be matched in the reply in order to prevent IP spoofing. */
- packet_start(SSH_SMSG_PUBLIC_KEY);
- for (i = 0; i < 8; i++)
- packet_put_char(check_bytes[i]);
-
- /* Store our public server RSA key. */
- packet_put_int(BN_num_bits(public_key->n));
- packet_put_bignum(public_key->e);
- packet_put_bignum(public_key->n);
-
- /* Store our public host RSA key. */
- packet_put_int(BN_num_bits(sensitive_data.host_key->n));
- packet_put_bignum(sensitive_data.host_key->e);
- packet_put_bignum(sensitive_data.host_key->n);
-
- /* Put protocol flags. */
- packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
-
- /* Declare which ciphers we support. */
- packet_put_int(cipher_mask());
-
- /* Declare supported authentication types. */
- auth_mask = 0;
- if (options.rhosts_authentication)
- auth_mask |= 1 << SSH_AUTH_RHOSTS;
- if (options.rhosts_rsa_authentication)
- auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
- if (options.rsa_authentication)
- auth_mask |= 1 << SSH_AUTH_RSA;
-#ifdef KRB4
- if (options.kerberos_authentication)
- auth_mask |= 1 << SSH_AUTH_KERBEROS;
-#endif
-#ifdef AFS
- if (options.kerberos_tgt_passing)
- auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
- if (options.afs_token_passing)
- auth_mask |= 1 << SSH_PASS_AFS_TOKEN;
-#endif
- if (options.password_authentication)
- auth_mask |= 1 << SSH_AUTH_PASSWORD;
- packet_put_int(auth_mask);
-
- /* Send the packet and wait for it to be sent. */
- packet_send();
- packet_write_wait();
-
- debug("Sent %d bit public key and %d bit host key.",
- BN_num_bits(public_key->n), BN_num_bits(sensitive_data.host_key->n));
-
- /* Read clients reply (cipher type and session key). */
- packet_read_expect(&plen, SSH_CMSG_SESSION_KEY);
-
- /* Get cipher type. */
- cipher_type = packet_get_char();
-
- /* Get check bytes from the packet. These must match those we sent earlier
- with the public key packet. */
- for (i = 0; i < 8; i++)
- if (check_bytes[i] != packet_get_char())
- packet_disconnect("IP Spoofing check bytes do not match.");
-
- debug("Encryption type: %.200s", cipher_name(cipher_type));
-
- /* Get the encrypted integer. */
- session_key_int = BN_new();
- packet_get_bignum(session_key_int, &slen);
-
- /* Get protocol flags. */
- protocol_flags = packet_get_int();
- packet_set_protocol_flags(protocol_flags);
-
- packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY);
-
- /* Decrypt it using our private server key and private host key (key with
- larger modulus first). */
- if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0)
- {
- /* Private key has bigger modulus. */
- if (BN_num_bits(sensitive_data.private_key->n) <
- BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
- fatal("do_connection: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
- BN_num_bits(sensitive_data.private_key->n),
- BN_num_bits(sensitive_data.host_key->n),
- SSH_KEY_BITS_RESERVED);
- }
-
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.private_key);
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.host_key);
- }
- else
- {
- /* Host key has bigger modulus (or they are equal). */
- if (BN_num_bits(sensitive_data.host_key->n) <
- BN_num_bits(sensitive_data.private_key->n) + SSH_KEY_BITS_RESERVED) {
- fatal("do_connection: host_key %d < private_key %d + SSH_KEY_BITS_RESERVED %d",
- BN_num_bits(sensitive_data.host_key->n),
- BN_num_bits(sensitive_data.private_key->n),
- SSH_KEY_BITS_RESERVED);
- }
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.host_key);
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.private_key);
- }
-
- /* Compute session id for this session. */
- compute_session_id(session_id, check_bytes,
- BN_num_bits(sensitive_data.host_key->n),
- sensitive_data.host_key->n,
- BN_num_bits(sensitive_data.private_key->n),
- sensitive_data.private_key->n);
-
- /* Extract session key from the decrypted integer. The key is in the
- least significant 256 bits of the integer; the first byte of the
- key is in the highest bits. */
- BN_mask_bits(session_key_int, sizeof(session_key) * 8);
- len = BN_num_bytes(session_key_int);
- if (len < 0 || len > sizeof(session_key))
- fatal("do_connection: bad len: session_key_int %d > sizeof(session_key) %d",
- len, sizeof(session_key));
- memset(session_key, 0, sizeof(session_key));
- BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
-
- /* Xor the first 16 bytes of the session key with the session id. */
- for (i = 0; i < 16; i++)
- session_key[i] ^= session_id[i];
-
- /* Destroy the decrypted integer. It is no longer needed. */
- BN_clear_free(session_key_int);
-
- /* Set the session key. From this on all communications will be
- encrypted. */
- packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH,
- cipher_type, 0);
-
- /* Destroy our copy of the session key. It is no longer needed. */
- memset(session_key, 0, sizeof(session_key));
-
- debug("Received session key; encryption turned on.");
-
- /* Send an acknowledgement packet. Note that this packet is sent
- encrypted. */
- packet_start(SSH_SMSG_SUCCESS);
- packet_send();
- packet_write_wait();
-
- /* Get the name of the user that we wish to log in as. */
- packet_read_expect(&plen, SSH_CMSG_USER);
-
- /* Get the user name. */
- {
- int ulen;
- user = packet_get_string(&ulen);
- packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
- }
-
- /* Destroy the private and public keys. They will no longer be needed. */
- RSA_free(public_key);
- RSA_free(sensitive_data.private_key);
- RSA_free(sensitive_data.host_key);
-
- setproctitle("%s", user);
- /* Do the authentication. */
- do_authentication(user);
-}
-
-/* Check if the user is allowed to log in via ssh. If user is listed in
- DenyUsers or user's primary group is listed in DenyGroups, false will
- be returned. If AllowUsers isn't empty and user isn't listed there, or
- if AllowGroups isn't empty and user isn't listed there, false will be
- returned. Otherwise true is returned.
- XXX This function should also check if user has a valid shell */
-
-static int
-allowed_user(struct passwd *pw)
-{
- struct group *grp;
- int i;
-
- /* Shouldn't be called if pw is NULL, but better safe than sorry... */
- if (!pw)
- return 0;
-
- /* XXX Should check for valid login shell */
-
- /* Return false if user is listed in DenyUsers */
- if (options.num_deny_users > 0)
- {
- if (!pw->pw_name)
- return 0;
- for (i = 0; i < options.num_deny_users; i++)
- if (match_pattern(pw->pw_name, options.deny_users[i]))
- return 0;
- }
-
- /* Return false if AllowUsers isn't empty and user isn't listed there */
- if (options.num_allow_users > 0)
- {
- if (!pw->pw_name)
- return 0;
- for (i = 0; i < options.num_allow_users; i++)
- if (match_pattern(pw->pw_name, options.allow_users[i]))
- break;
- /* i < options.num_allow_users iff we break for loop */
- if (i >= options.num_allow_users)
- return 0;
- }
-
- /* Get the primary group name if we need it. Return false if it fails */
- if (options.num_deny_groups > 0 || options.num_allow_groups > 0 )
- {
- grp = getgrgid(pw->pw_gid);
- if (!grp)
- return 0;
-
- /* Return false if user's group is listed in DenyGroups */
- if (options.num_deny_groups > 0)
- {
- if (!grp->gr_name)
- return 0;
- for (i = 0; i < options.num_deny_groups; i++)
- if (match_pattern(grp->gr_name, options.deny_groups[i]))
- return 0;
- }
-
- /* Return false if AllowGroups isn't empty and user's group isn't
- listed there */
- if (options.num_allow_groups > 0)
- {
- if (!grp->gr_name)
- return 0;
- for (i = 0; i < options.num_allow_groups; i++)
- if (match_pattern(grp->gr_name, options.allow_groups[i]))
- break;
- /* i < options.num_allow_groups iff we break for loop */
- if (i >= options.num_allow_groups)
- return 0;
- }
- }
-
- /* We found no reason not to let this user try to log on... */
- return 1;