summaryrefslogtreecommitdiff
path: root/auth-rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-rsa.c')
-rw-r--r--auth-rsa.c202
1 files changed, 117 insertions, 85 deletions
diff --git a/auth-rsa.c b/auth-rsa.c
index f7ae03cfd..ff9bf3b64 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $"); 17RCSID("$OpenBSD: auth-rsa.c,v 1.51 2002/03/14 16:56:33 markus Exp $");
18 18
19#include <openssl/rsa.h> 19#include <openssl/rsa.h>
20#include <openssl/md5.h> 20#include <openssl/md5.h>
@@ -52,6 +52,51 @@ extern u_char session_id[16];
52 * description of the options. 52 * description of the options.
53 */ 53 */
54 54
55static BIGNUM *
56auth_rsa_generate_challenge(Key *key)
57{
58 BIGNUM *challenge;
59 BN_CTX *ctx;
60
61 if ((challenge = BN_new()) == NULL)
62 fatal("auth_rsa_generate_challenge: BN_new() failed");
63 /* Generate a random challenge. */
64 BN_rand(challenge, 256, 0, 0);
65 if ((ctx = BN_CTX_new()) == NULL)
66 fatal("auth_rsa_generate_challenge: BN_CTX_new() failed");
67 BN_mod(challenge, challenge, key->rsa->n, ctx);
68 BN_CTX_free(ctx);
69
70 return challenge;
71}
72
73static int
74auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
75{
76 u_char buf[32], mdbuf[16];
77 MD5_CTX md;
78 int len;
79
80 /* The response is MD5 of decrypted challenge plus session id. */
81 len = BN_num_bytes(challenge);
82 if (len <= 0 || len > 32)
83 fatal("auth_rsa_verify_response: bad challenge length %d", len);
84 memset(buf, 0, 32);
85 BN_bn2bin(challenge, buf + 32 - len);
86 MD5_Init(&md);
87 MD5_Update(&md, buf, 32);
88 MD5_Update(&md, session_id, 16);
89 MD5_Final(mdbuf, &md);
90
91 /* Verify that the response is the original challenge. */
92 if (memcmp(response, mdbuf, 16) != 0) {
93 /* Wrong answer. */
94 return (0);
95 }
96 /* Correct answer. */
97 return (1);
98}
99
55/* 100/*
56 * Performs the RSA authentication challenge-response dialog with the client, 101 * Performs the RSA authentication challenge-response dialog with the client,
57 * and returns true (non-zero) if the client gave the correct answer to 102 * and returns true (non-zero) if the client gave the correct answer to
@@ -59,29 +104,19 @@ extern u_char session_id[16];
59 */ 104 */
60 105
61int 106int
62auth_rsa_challenge_dialog(RSA *pk) 107auth_rsa_challenge_dialog(Key *key)
63{ 108{
64 BIGNUM *challenge, *encrypted_challenge; 109 BIGNUM *challenge, *encrypted_challenge;
65 BN_CTX *ctx; 110 u_char response[16];
66 u_char buf[32], mdbuf[16], response[16]; 111 int i, success;
67 MD5_CTX md;
68 u_int i;
69 int len;
70 112
71 if ((encrypted_challenge = BN_new()) == NULL) 113 if ((encrypted_challenge = BN_new()) == NULL)
72 fatal("auth_rsa_challenge_dialog: BN_new() failed"); 114 fatal("auth_rsa_challenge_dialog: BN_new() failed");
73 if ((challenge = BN_new()) == NULL)
74 fatal("auth_rsa_challenge_dialog: BN_new() failed");
75 115
76 /* Generate a random challenge. */ 116 challenge = auth_rsa_generate_challenge(key);
77 BN_rand(challenge, 256, 0, 0);
78 if ((ctx = BN_CTX_new()) == NULL)
79 fatal("auth_rsa_challenge_dialog: BN_CTX_new() failed");
80 BN_mod(challenge, challenge, pk->n, ctx);
81 BN_CTX_free(ctx);
82 117
83 /* Encrypt the challenge with the public key. */ 118 /* Encrypt the challenge with the public key. */
84 rsa_public_encrypt(encrypted_challenge, challenge, pk); 119 rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
85 120
86 /* Send the encrypted challenge to the client. */ 121 /* Send the encrypted challenge to the client. */
87 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); 122 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
@@ -96,48 +131,26 @@ auth_rsa_challenge_dialog(RSA *pk)
96 response[i] = packet_get_char(); 131 response[i] = packet_get_char();
97 packet_check_eom(); 132 packet_check_eom();
98 133
99 /* The response is MD5 of decrypted challenge plus session id. */ 134 success = auth_rsa_verify_response(key, challenge, response);
100 len = BN_num_bytes(challenge);
101 if (len <= 0 || len > 32)
102 fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
103 memset(buf, 0, 32);
104 BN_bn2bin(challenge, buf + 32 - len);
105 MD5_Init(&md);
106 MD5_Update(&md, buf, 32);
107 MD5_Update(&md, session_id, 16);
108 MD5_Final(mdbuf, &md);
109 BN_clear_free(challenge); 135 BN_clear_free(challenge);
110 136 return (success);
111 /* Verify that the response is the original challenge. */
112 if (memcmp(response, mdbuf, 16) != 0) {
113 /* Wrong answer. */
114 return 0;
115 }
116 /* Correct answer. */
117 return 1;
118} 137}
119 138
120/* 139/*
121 * Performs the RSA authentication dialog with the client. This returns 140 * check if there's user key matching client_n,
122 * 0 if the client could not be authenticated, and 1 if authentication was 141 * return key if login is allowed, NULL otherwise
123 * successful. This may exit if there is a serious protocol violation.
124 */ 142 */
125 143
126int 144static int
127auth_rsa(struct passwd *pw, BIGNUM *client_n) 145auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
128{ 146{
129 char line[8192], *file; 147 char line[8192], *file;
130 int authenticated; 148 int allowed;
131 u_int bits; 149 u_int bits;
132 FILE *f; 150 FILE *f;
133 u_long linenum = 0; 151 u_long linenum = 0;
134 struct stat st; 152 struct stat st;
135 Key *key; 153 Key *key;
136 char *fp;
137
138 /* no user given */
139 if (pw == NULL)
140 return 0;
141 154
142 /* Temporarily use the user's uid. */ 155 /* Temporarily use the user's uid. */
143 temporarily_use_uid(pw); 156 temporarily_use_uid(pw);
@@ -151,29 +164,27 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
151 /* Restore the privileged uid. */ 164 /* Restore the privileged uid. */
152 restore_uid(); 165 restore_uid();
153 xfree(file); 166 xfree(file);
154 return 0; 167 return (NULL);
155 } 168 }
156 /* Open the file containing the authorized keys. */ 169 /* Open the file containing the authorized keys. */
157 f = fopen(file, "r"); 170 f = fopen(file, "r");
158 if (!f) { 171 if (!f) {
159 /* Restore the privileged uid. */ 172 /* Restore the privileged uid. */
160 restore_uid(); 173 restore_uid();
161 packet_send_debug("Could not open %.900s for reading.", file);
162 packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
163 xfree(file); 174 xfree(file);
164 return 0; 175 return (NULL);
165 } 176 }
166 if (options.strict_modes && 177 if (options.strict_modes &&
167 secure_filename(f, file, pw, line, sizeof(line)) != 0) { 178 secure_filename(f, file, pw, line, sizeof(line)) != 0) {
168 xfree(file); 179 xfree(file);
169 fclose(f); 180 fclose(f);
170 log("Authentication refused: %s", line); 181 log("Authentication refused: %s", line);
171 packet_send_debug("Authentication refused: %s", line);
172 restore_uid(); 182 restore_uid();
173 return 0; 183 return (NULL);
174 } 184 }
175 /* Flag indicating whether authentication has succeeded. */ 185
176 authenticated = 0; 186 /* Flag indicating whether the key is allowed. */
187 allowed = 0;
177 188
178 key = key_new(KEY_RSA1); 189 key = key_new(KEY_RSA1);
179 190
@@ -238,32 +249,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
238 if (!auth_parse_options(pw, options, file, linenum)) 249 if (!auth_parse_options(pw, options, file, linenum))
239 continue; 250 continue;
240 251
241 /* Perform the challenge-response dialog for this key. */ 252 /* break out, this key is allowed */
242 if (!auth_rsa_challenge_dialog(key->rsa)) { 253 allowed = 1;
243 /* Wrong response. */
244 verbose("Wrong response to RSA authentication challenge.");
245 packet_send_debug("Wrong response to RSA authentication challenge.");
246 /*
247 * Break out of the loop. Otherwise we might send
248 * another challenge and break the protocol.
249 */
250 break;
251 }
252 /*
253 * Correct response. The client has been successfully
254 * authenticated. Note that we have not yet processed the
255 * options; this will be reset if the options cause the
256 * authentication to be rejected.
257 * Break out of the loop if authentication was successful;
258 * otherwise continue searching.
259 */
260 authenticated = 1;
261
262 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
263 verbose("Found matching %s key: %s",
264 key_type(key), fp);
265 xfree(fp);
266
267 break; 254 break;
268 } 255 }
269 256
@@ -274,13 +261,58 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
274 xfree(file); 261 xfree(file);
275 fclose(f); 262 fclose(f);
276 263
277 key_free(key); 264 /* return key if allowed */
278 265 if (allowed && rkey != NULL)
279 if (authenticated) 266 *rkey = key;
280 packet_send_debug("RSA authentication accepted.");
281 else 267 else
268 key_free(key);
269 return (allowed);
270}
271
272/*
273 * Performs the RSA authentication dialog with the client. This returns
274 * 0 if the client could not be authenticated, and 1 if authentication was
275 * successful. This may exit if there is a serious protocol violation.
276 */
277int
278auth_rsa(struct passwd *pw, BIGNUM *client_n)
279{
280 Key *key;
281 char *fp;
282
283 /* no user given */
284 if (pw == NULL)
285 return 0;
286
287 if (auth_rsa_key_allowed(pw, client_n, &key) == 0) {
282 auth_clear_options(); 288 auth_clear_options();
289 return (0);
290 }
291
292 /* Perform the challenge-response dialog for this key. */
293 if (!auth_rsa_challenge_dialog(key)) {
294 /* Wrong response. */
295 verbose("Wrong response to RSA authentication challenge.");
296 packet_send_debug("Wrong response to RSA authentication challenge.");
297 /*
298 * Break out of the loop. Otherwise we might send
299 * another challenge and break the protocol.
300 */
301 key_free(key);
302 return (0);
303 }
304 /*
305 * Correct response. The client has been successfully
306 * authenticated. Note that we have not yet processed the
307 * options; this will be reset if the options cause the
308 * authentication to be rejected.
309 */
310 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
311 verbose("Found matching %s key: %s",
312 key_type(key), fp);
313 xfree(fp);
314 key_free(key);
283 315
284 /* Return authentication result. */ 316 packet_send_debug("RSA authentication accepted.");
285 return authenticated; 317 return (1);
286} 318}