Main Page | Namespace List | Class List | Directories | File List | Class Members | File Members

auth-rsa.c File Reference

#include "includes.h"
#include <openssl/rsa.h>
#include <openssl/md5.h>
#include "rsa.h"
#include "packet.h"
#include "xmalloc.h"
#include "ssh1.h"
#include "uidswap.h"
#include "match.h"
#include "auth-options.h"
#include "pathnames.h"
#include "log.h"
#include "servconf.h"
#include "auth.h"
#include "hostfile.h"
#include "monitor_wrap.h"
#include "ssh.h"
#include "misc.h"

Go to the source code of this file.

Functions

 RCSID ("$OpenBSD: auth-rsa.c,v 1.63 2005/06/17 02:44:32 djm Exp $")
BIGNUM * auth_rsa_generate_challenge (Key *key)
int auth_rsa_verify_response (Key *key, BIGNUM *challenge, u_char response[16])
int auth_rsa_challenge_dialog (Key *key)
int auth_rsa_key_allowed (struct passwd *pw, BIGNUM *client_n, Key **rkey)
int auth_rsa (Authctxt *authctxt, BIGNUM *client_n)

Variables

ServerOptions options
u_char session_id [16]


Function Documentation

int auth_rsa Authctxt authctxt,
BIGNUM *  client_n
 

Definition at line 287 of file auth-rsa.c.

References auth_clear_options(), auth_rsa_challenge_dialog(), auth_rsa_key_allowed(), key_fingerprint(), key_free(), key_type(), packet_send_debug(), PRIVSEP, Authctxt::pw, SSH_FP_HEX, SSH_FP_MD5, Authctxt::valid, verbose(), and xfree().

Referenced by auth1_process_rsa().

00288 {
00289         Key *key;
00290         char *fp;
00291         struct passwd *pw = authctxt->pw;
00292 
00293         /* no user given */
00294         if (!authctxt->valid)
00295                 return 0;
00296 
00297         if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
00298                 auth_clear_options();
00299                 return (0);
00300         }
00301 
00302         /* Perform the challenge-response dialog for this key. */
00303         if (!auth_rsa_challenge_dialog(key)) {
00304                 /* Wrong response. */
00305                 verbose("Wrong response to RSA authentication challenge.");
00306                 packet_send_debug("Wrong response to RSA authentication challenge.");
00307                 /*
00308                  * Break out of the loop. Otherwise we might send
00309                  * another challenge and break the protocol.
00310                  */
00311                 key_free(key);
00312                 return (0);
00313         }
00314         /*
00315          * Correct response.  The client has been successfully
00316          * authenticated. Note that we have not yet processed the
00317          * options; this will be reset if the options cause the
00318          * authentication to be rejected.
00319          */
00320         fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
00321         verbose("Found matching %s key: %s",
00322             key_type(key), fp);
00323         xfree(fp);
00324         key_free(key);
00325 
00326         packet_send_debug("RSA authentication accepted.");
00327         return (1);
00328 }

int auth_rsa_challenge_dialog Key key  ) 
 

Definition at line 116 of file auth-rsa.c.

References auth_rsa_generate_challenge(), auth_rsa_verify_response(), fatal(), packet_check_eom, packet_get_char(), packet_put_bignum(), packet_read_expect(), packet_send(), packet_start(), packet_write_wait(), PRIVSEP, response(), Key::rsa, rsa_public_encrypt(), SSH_CMSG_AUTH_RSA_RESPONSE, and SSH_SMSG_AUTH_RSA_CHALLENGE.

Referenced by auth_rhosts_rsa(), and auth_rsa().

00117 {
00118         BIGNUM *challenge, *encrypted_challenge;
00119         u_char response[16];
00120         int i, success;
00121 
00122         if ((encrypted_challenge = BN_new()) == NULL)
00123                 fatal("auth_rsa_challenge_dialog: BN_new() failed");
00124 
00125         challenge = PRIVSEP(auth_rsa_generate_challenge(key));
00126 
00127         /* Encrypt the challenge with the public key. */
00128         rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
00129 
00130         /* Send the encrypted challenge to the client. */
00131         packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
00132         packet_put_bignum(encrypted_challenge);
00133         packet_send();
00134         BN_clear_free(encrypted_challenge);
00135         packet_write_wait();
00136 
00137         /* Wait for a response. */
00138         packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
00139         for (i = 0; i < 16; i++)
00140                 response[i] = packet_get_char();
00141         packet_check_eom();
00142 
00143         success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
00144         BN_clear_free(challenge);
00145         return (success);
00146 }

BIGNUM* auth_rsa_generate_challenge Key key  ) 
 

Definition at line 58 of file auth-rsa.c.

References fatal(), and Key::rsa.

Referenced by auth_rsa_challenge_dialog(), and mm_answer_rsa_challenge().

00059 {
00060         BIGNUM *challenge;
00061         BN_CTX *ctx;
00062 
00063         if ((challenge = BN_new()) == NULL)
00064                 fatal("auth_rsa_generate_challenge: BN_new() failed");
00065         /* Generate a random challenge. */
00066         BN_rand(challenge, 256, 0, 0);
00067         if ((ctx = BN_CTX_new()) == NULL)
00068                 fatal("auth_rsa_generate_challenge: BN_CTX_new() failed");
00069         BN_mod(challenge, challenge, key->rsa->n, ctx);
00070         BN_CTX_free(ctx);
00071 
00072         return challenge;
00073 }

int auth_rsa_key_allowed struct passwd *  pw,
BIGNUM *  client_n,
Key **  rkey
 

Definition at line 154 of file auth-rsa.c.

References auth_parse_options(), authorized_keys_file(), bits, debug(), file, hostfile_read_key(), key_free(), key_new(), KEY_RSA1, logit(), read_keyfile_line(), restore_uid(), secure_filename(), SSH_MAX_PUBKEY_BYTES, ServerOptions::strict_modes, temporarily_use_uid(), and xfree().

Referenced by auth_rsa(), and mm_answer_rsa_keyallowed().

00155 {
00156         char line[SSH_MAX_PUBKEY_BYTES], *file;
00157         int allowed = 0;
00158         u_int bits;
00159         FILE *f;
00160         u_long linenum = 0;
00161         struct stat st;
00162         Key *key;
00163 
00164         /* Temporarily use the user's uid. */
00165         temporarily_use_uid(pw);
00166 
00167         /* The authorized keys. */
00168         file = authorized_keys_file(pw);
00169         debug("trying public RSA key file %s", file);
00170 
00171         /* Fail quietly if file does not exist */
00172         if (stat(file, &st) < 0) {
00173                 /* Restore the privileged uid. */
00174                 restore_uid();
00175                 xfree(file);
00176                 return (0);
00177         }
00178         /* Open the file containing the authorized keys. */
00179         f = fopen(file, "r");
00180         if (!f) {
00181                 /* Restore the privileged uid. */
00182                 restore_uid();
00183                 xfree(file);
00184                 return (0);
00185         }
00186         if (options.strict_modes &&
00187             secure_filename(f, file, pw, line, sizeof(line)) != 0) {
00188                 xfree(file);
00189                 fclose(f);
00190                 logit("Authentication refused: %s", line);
00191                 restore_uid();
00192                 return (0);
00193         }
00194 
00195         /* Flag indicating whether the key is allowed. */
00196         allowed = 0;
00197 
00198         key = key_new(KEY_RSA1);
00199 
00200         /*
00201          * Go though the accepted keys, looking for the current key.  If
00202          * found, perform a challenge-response dialog to verify that the
00203          * user really has the corresponding private key.
00204          */
00205         while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
00206                 char *cp;
00207                 char *key_options;
00208                 int keybits;
00209 
00210                 /* Skip leading whitespace, empty and comment lines. */
00211                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
00212                         ;
00213                 if (!*cp || *cp == '\n' || *cp == '#')
00214                         continue;
00215 
00216                 /*
00217                  * Check if there are options for this key, and if so,
00218                  * save their starting address and skip the option part
00219                  * for now.  If there are no options, set the starting
00220                  * address to NULL.
00221                  */
00222                 if (*cp < '0' || *cp > '9') {
00223                         int quoted = 0;
00224                         key_options = cp;
00225                         for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
00226                                 if (*cp == '\\' && cp[1] == '"')
00227                                         cp++;   /* Skip both */
00228                                 else if (*cp == '"')
00229                                         quoted = !quoted;
00230                         }
00231                 } else
00232                         key_options = NULL;
00233 
00234                 /* Parse the key from the line. */
00235                 if (hostfile_read_key(&cp, &bits, key) == 0) {
00236                         debug("%.100s, line %lu: non ssh1 key syntax",
00237                             file, linenum);
00238                         continue;
00239                 }
00240                 /* cp now points to the comment part. */
00241 
00242                 /* Check if the we have found the desired key (identified by its modulus). */
00243                 if (BN_cmp(key->rsa->n, client_n) != 0)
00244                         continue;
00245 
00246                 /* check the real bits  */
00247                 keybits = BN_num_bits(key->rsa->n);
00248                 if (keybits < 0 || bits != (u_int)keybits)
00249                         logit("Warning: %s, line %lu: keysize mismatch: "
00250                             "actual %d vs. announced %d.",
00251                             file, linenum, BN_num_bits(key->rsa->n), bits);
00252 
00253                 /* We have found the desired key. */
00254                 /*
00255                  * If our options do not allow this key to be used,
00256                  * do not send challenge.
00257                  */
00258                 if (!auth_parse_options(pw, key_options, file, linenum))
00259                         continue;
00260 
00261                 /* break out, this key is allowed */
00262                 allowed = 1;
00263                 break;
00264         }
00265 
00266         /* Restore the privileged uid. */
00267         restore_uid();
00268 
00269         /* Close the file. */
00270         xfree(file);
00271         fclose(f);
00272 
00273         /* return key if allowed */
00274         if (allowed && rkey != NULL)
00275                 *rkey = key;
00276         else
00277                 key_free(key);
00278         return (allowed);
00279 }

int auth_rsa_verify_response Key key,
BIGNUM *  challenge,
u_char  response[16]
 

Definition at line 76 of file auth-rsa.c.

References error(), fatal(), Key::rsa, session_id, and SSH_RSA_MINIMUM_MODULUS_SIZE.

Referenced by auth_rsa_challenge_dialog(), and mm_answer_rsa_response().

00077 {
00078         u_char buf[32], mdbuf[16];
00079         MD5_CTX md;
00080         int len;
00081 
00082         /* don't allow short keys */
00083         if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
00084                 error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
00085                     BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
00086                 return (0);
00087         }
00088 
00089         /* The response is MD5 of decrypted challenge plus session id. */
00090         len = BN_num_bytes(challenge);
00091         if (len <= 0 || len > 32)
00092                 fatal("auth_rsa_verify_response: bad challenge length %d", len);
00093         memset(buf, 0, 32);
00094         BN_bn2bin(challenge, buf + 32 - len);
00095         MD5_Init(&md);
00096         MD5_Update(&md, buf, 32);
00097         MD5_Update(&md, session_id, 16);
00098         MD5_Final(mdbuf, &md);
00099 
00100         /* Verify that the response is the original challenge. */
00101         if (memcmp(response, mdbuf, 16) != 0) {
00102                 /* Wrong answer. */
00103                 return (0);
00104         }
00105         /* Correct answer. */
00106         return (1);
00107 }

RCSID "$OpenBSD: auth-rsa.  c,
v 1.63 2005/06/17 02:44:32 djm Exp $" 
 


Variable Documentation

ServerOptions options
 

Definition at line 110 of file ssh.c.

u_char session_id[16]
 

Definition at line 41 of file sshconnect1.c.

Referenced by auth_rsa_verify_response(), do_ssh1_kex(), mm_answer_sessid(), process_authentication_challenge1(), respond_to_rsa_challenge(), ssh_kex(), and try_agent_authentication().


© sourcejam.com 2005-2008