- extern ServerOptions options;
- char line[8192], file[1024];
- int authenticated;
- unsigned int bits;
- FILE *f;
- unsigned long linenum = 0;
- struct stat st;
- BIGNUM *e, *n;
-
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw->pw_uid);
-
- /* The authorized keys. */
- snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
- SSH_USER_PERMITTED_KEYS);
-
- /* Fail quietly if file does not exist */
- if (stat(file, &st) < 0)
- {
- /* Restore the privileged uid. */
- restore_uid();
- return 0;
- }
-
- /* Open the file containing the authorized keys. */
- f = fopen(file, "r");
- if (!f)
- {
- /* Restore the privileged uid. */
- restore_uid();
- packet_send_debug("Could not open %.900s for reading.", file);
- packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
- return 0;
- }
-
- if (options.strict_modes) {
- int fail=0;
- char buf[1024];
- /* Check open file in order to avoid open/stat races */
- if (fstat(fileno(f), &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
- "bad ownership or modes for '%s'.", pw->pw_name, file);
- fail=1;
- }else{
- /* Check path to SSH_USER_PERMITTED_KEYS */
- int i;
- static const char *check[] = {
- "", SSH_USER_DIR, NULL
- };
- for (i=0; check[i]; i++) {
- snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
- if (stat(line, &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
- "bad ownership or modes for '%s'.", pw->pw_name, line);
- fail=1;
- break;
- }
- }
- }
- if (fail) {
- log(buf);
- packet_send_debug(buf);
- restore_uid();
- return 0;
- }
- }
-
- /* Flag indicating whether authentication has succeeded. */
- authenticated = 0;
-
- /* Initialize mp-int variables. */
- e = BN_new();
- n = BN_new();
-
- /* Go though the accepted keys, looking for the current key. If found,
- perform a challenge-response dialog to verify that the user really has
- the corresponding private key. */
- while (fgets(line, sizeof(line), f))
- {
- char *cp;
- char *options;
-
- linenum++;
-
- /* Skip leading whitespace. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
- ;
-
- /* Skip empty and comment lines. */
- if (!*cp || *cp == '\n' || *cp == '#')
- continue;
-
- /* Check if there are options for this key, and if so, save their
- starting address and skip the option part for now. If there are no
- options, set the starting address to NULL. */
- if (*cp < '0' || *cp > '9')
- {
- int quoted = 0;
- options = cp;
- for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++)
- {
- if (*cp == '\\' && cp[1] == '"')
- cp++; /* Skip both */
- else
- if (*cp == '"')
- quoted = !quoted;
- }
+ BIGNUM *challenge, *encrypted_challenge;
+ u_char response[16];
+ int i, success;
+
+ if ((encrypted_challenge = BN_new()) == NULL)
+ fatal("auth_rsa_challenge_dialog: BN_new() failed");
+
+ challenge = PRIVSEP(auth_rsa_generate_challenge(key));
+
+ /* Encrypt the challenge with the public key. */
+ rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
+
+ /* Send the encrypted challenge to the client. */
+ packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
+ packet_put_bignum(encrypted_challenge);
+ packet_send();
+ BN_clear_free(encrypted_challenge);
+ packet_write_wait();
+
+ /* Wait for a response. */
+ packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
+ for (i = 0; i < 16; i++)
+ response[i] = packet_get_char();
+ packet_check_eom();
+
+ success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
+ BN_clear_free(challenge);
+ return (success);
+}
+
+/*
+ * check if there's user key matching client_n,
+ * return key if login is allowed, NULL otherwise
+ */
+
+int
+auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+ char line[SSH_MAX_PUBKEY_BYTES], *file;
+ int allowed = 0;
+ u_int bits;
+ FILE *f;
+ u_long linenum = 0;
+ struct stat st;
+ Key *key;
+
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw);
+
+ /* The authorized keys. */
+ file = authorized_keys_file(pw);
+ debug("trying public RSA key file %s", file);
+
+ /* Fail quietly if file does not exist */
+ if (stat(file, &st) < 0) {
+ /* Restore the privileged uid. */
+ restore_uid();
+ xfree(file);
+ return (0);