00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "includes.h"
00017 RCSID("$OpenBSD: auth-rsa.c,v 1.63 2005/06/17 02:44:32 djm Exp $");
00018
00019 #include <openssl/rsa.h>
00020 #include <openssl/md5.h>
00021
00022 #include "rsa.h"
00023 #include "packet.h"
00024 #include "xmalloc.h"
00025 #include "ssh1.h"
00026 #include "uidswap.h"
00027 #include "match.h"
00028 #include "auth-options.h"
00029 #include "pathnames.h"
00030 #include "log.h"
00031 #include "servconf.h"
00032 #include "auth.h"
00033 #include "hostfile.h"
00034 #include "monitor_wrap.h"
00035 #include "ssh.h"
00036 #include "misc.h"
00037
00038
00039 extern ServerOptions options;
00040
00041
00042
00043
00044
00045 extern u_char session_id[16];
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 BIGNUM *
00058 auth_rsa_generate_challenge(Key *key)
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
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 }
00074
00075 int
00076 auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
00077 {
00078 u_char buf[32], mdbuf[16];
00079 MD5_CTX md;
00080 int len;
00081
00082
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
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
00101 if (memcmp(response, mdbuf, 16) != 0) {
00102
00103 return (0);
00104 }
00105
00106 return (1);
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 int
00116 auth_rsa_challenge_dialog(Key *key)
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
00128 rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
00129
00130
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
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 }
00147
00148
00149
00150
00151
00152
00153 int
00154 auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
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
00165 temporarily_use_uid(pw);
00166
00167
00168 file = authorized_keys_file(pw);
00169 debug("trying public RSA key file %s", file);
00170
00171
00172 if (stat(file, &st) < 0) {
00173
00174 restore_uid();
00175 xfree(file);
00176 return (0);
00177 }
00178
00179 f = fopen(file, "r");
00180 if (!f) {
00181
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
00196 allowed = 0;
00197
00198 key = key_new(KEY_RSA1);
00199
00200
00201
00202
00203
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
00211 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
00212 ;
00213 if (!*cp || *cp == '\n' || *cp == '#')
00214 continue;
00215
00216
00217
00218
00219
00220
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++;
00228 else if (*cp == '"')
00229 quoted = !quoted;
00230 }
00231 } else
00232 key_options = NULL;
00233
00234
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
00241
00242
00243 if (BN_cmp(key->rsa->n, client_n) != 0)
00244 continue;
00245
00246
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
00254
00255
00256
00257
00258 if (!auth_parse_options(pw, key_options, file, linenum))
00259 continue;
00260
00261
00262 allowed = 1;
00263 break;
00264 }
00265
00266
00267 restore_uid();
00268
00269
00270 xfree(file);
00271 fclose(f);
00272
00273
00274 if (allowed && rkey != NULL)
00275 *rkey = key;
00276 else
00277 key_free(key);
00278 return (allowed);
00279 }
00280
00281
00282
00283
00284
00285
00286 int
00287 auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
00288 {
00289 Key *key;
00290 char *fp;
00291 struct passwd *pw = authctxt->pw;
00292
00293
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
00303 if (!auth_rsa_challenge_dialog(key)) {
00304
00305 verbose("Wrong response to RSA authentication challenge.");
00306 packet_send_debug("Wrong response to RSA authentication challenge.");
00307
00308
00309
00310
00311 key_free(key);
00312 return (0);
00313 }
00314
00315
00316
00317
00318
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 }