Deleted Added
full compact
auth-rsa.c (57430) auth-rsa.c (57464)
1/*
2 *
3 * auth-rsa.c
4 *
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 *
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 * All rights reserved
9 *
10 * Created: Mon Mar 27 01:46:52 1995 ylo
11 *
12 * RSA-based authentication. This code determines whether to admit a login
13 * based on RSA authentication. This file also contains functions to check
14 * validity of the host key.
15 *
1/*
2 *
3 * auth-rsa.c
4 *
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 *
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 * All rights reserved
9 *
10 * Created: Mon Mar 27 01:46:52 1995 ylo
11 *
12 * RSA-based authentication. This code determines whether to admit a login
13 * based on RSA authentication. This file also contains functions to check
14 * validity of the host key.
15 *
16 * $FreeBSD: head/crypto/openssh/auth-rsa.c 57464 2000-02-25 01:53:12Z green $
16 */
17
18#include "includes.h"
19RCSID("$Id: auth-rsa.c,v 1.18 2000/02/11 10:59:11 markus Exp $");
20
21#include "rsa.h"
22#include "packet.h"
23#include "xmalloc.h"
24#include "ssh.h"
25#include "mpaux.h"
26#include "uidswap.h"
27#include "servconf.h"
28
17 */
18
19#include "includes.h"
20RCSID("$Id: auth-rsa.c,v 1.18 2000/02/11 10:59:11 markus Exp $");
21
22#include "rsa.h"
23#include "packet.h"
24#include "xmalloc.h"
25#include "ssh.h"
26#include "mpaux.h"
27#include "uidswap.h"
28#include "servconf.h"
29
29#include
30#include
30#include <openssl/rsa.h>
31#include <openssl/md5.h>
31
32/* Flags that may be set in authorized_keys options. */
33extern int no_port_forwarding_flag;
34extern int no_agent_forwarding_flag;
35extern int no_x11_forwarding_flag;
36extern int no_pty_flag;
37extern char *forced_command;
38extern struct envstring *custom_environment;
39
40/*
41 * Session identifier that is used to bind key exchange and authentication
42 * responses to a particular session.
43 */
44extern unsigned char session_id[16];
45
46/*
47 * The .ssh/authorized_keys file contains public keys, one per line, in the
48 * following format:
49 * options bits e n comment
50 * where bits, e and n are decimal numbers,
51 * and comment is any string of characters up to newline. The maximum
52 * length of a line is 8000 characters. See the documentation for a
53 * description of the options.
54 */
55
56/*
57 * Performs the RSA authentication challenge-response dialog with the client,
58 * and returns true (non-zero) if the client gave the correct answer to
59 * our challenge; returns zero if the client gives a wrong answer.
60 */
61
62int
63auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n)
64{
65 BIGNUM *challenge, *encrypted_challenge;
66 RSA *pk;
67 BN_CTX *ctx;
68 unsigned char buf[32], mdbuf[16], response[16];
69 MD5_CTX md;
70 unsigned int i;
71 int plen, len;
72
73 encrypted_challenge = BN_new();
74 challenge = BN_new();
75
76 /* Generate a random challenge. */
77 BN_rand(challenge, 256, 0, 0);
78 ctx = BN_CTX_new();
79 BN_mod(challenge, challenge, n, ctx);
80 BN_CTX_free(ctx);
81
82 /* Create the public key data structure. */
83 pk = RSA_new();
84 pk->e = BN_new();
85 BN_copy(pk->e, e);
86 pk->n = BN_new();
87 BN_copy(pk->n, n);
88
89 /* Encrypt the challenge with the public key. */
90 rsa_public_encrypt(encrypted_challenge, challenge, pk);
91 RSA_free(pk);
92
93 /* Send the encrypted challenge to the client. */
94 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
95 packet_put_bignum(encrypted_challenge);
96 packet_send();
97 BN_clear_free(encrypted_challenge);
98 packet_write_wait();
99
100 /* Wait for a response. */
101 packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE);
102 packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE);
103 for (i = 0; i < 16; i++)
104 response[i] = packet_get_char();
105
106 /* The response is MD5 of decrypted challenge plus session id. */
107 len = BN_num_bytes(challenge);
108 if (len <= 0 || len > 32)
109 fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
110 memset(buf, 0, 32);
111 BN_bn2bin(challenge, buf + 32 - len);
112 MD5_Init(&md);
113 MD5_Update(&md, buf, 32);
114 MD5_Update(&md, session_id, 16);
115 MD5_Final(mdbuf, &md);
116 BN_clear_free(challenge);
117
118 /* Verify that the response is the original challenge. */
119 if (memcmp(response, mdbuf, 16) != 0) {
120 /* Wrong answer. */
121 return 0;
122 }
123 /* Correct answer. */
124 return 1;
125}
126
127/*
128 * Performs the RSA authentication dialog with the client. This returns
129 * 0 if the client could not be authenticated, and 1 if authentication was
130 * successful. This may exit if there is a serious protocol violation.
131 */
132
133int
134auth_rsa(struct passwd *pw, BIGNUM *client_n)
135{
136 extern ServerOptions options;
137 char line[8192], file[1024];
138 int authenticated;
139 unsigned int bits;
140 FILE *f;
141 unsigned long linenum = 0;
142 struct stat st;
143 BIGNUM *e, *n;
144
145 /* Temporarily use the user's uid. */
146 temporarily_use_uid(pw->pw_uid);
147
148 /* The authorized keys. */
149 snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
150 SSH_USER_PERMITTED_KEYS);
151
152 /* Fail quietly if file does not exist */
153 if (stat(file, &st) < 0) {
154 /* Restore the privileged uid. */
155 restore_uid();
156 return 0;
157 }
158 /* Open the file containing the authorized keys. */
159 f = fopen(file, "r");
160 if (!f) {
161 /* Restore the privileged uid. */
162 restore_uid();
163 packet_send_debug("Could not open %.900s for reading.", file);
164 packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
165 return 0;
166 }
167 if (options.strict_modes) {
168 int fail = 0;
169 char buf[1024];
170 /* Check open file in order to avoid open/stat races */
171 if (fstat(fileno(f), &st) < 0 ||
172 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
173 (st.st_mode & 022) != 0) {
174 snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
175 "bad ownership or modes for '%s'.", pw->pw_name, file);
176 fail = 1;
177 } else {
178 /* Check path to SSH_USER_PERMITTED_KEYS */
179 int i;
180 static const char *check[] = {
181 "", SSH_USER_DIR, NULL
182 };
183 for (i = 0; check[i]; i++) {
184 snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
185 if (stat(line, &st) < 0 ||
186 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
187 (st.st_mode & 022) != 0) {
188 snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
189 "bad ownership or modes for '%s'.", pw->pw_name, line);
190 fail = 1;
191 break;
192 }
193 }
194 }
195 if (fail) {
196 log(buf);
197 packet_send_debug(buf);
198 restore_uid();
199 return 0;
200 }
201 }
202 /* Flag indicating whether authentication has succeeded. */
203 authenticated = 0;
204
205 e = BN_new();
206 n = BN_new();
207
208 /*
209 * Go though the accepted keys, looking for the current key. If
210 * found, perform a challenge-response dialog to verify that the
211 * user really has the corresponding private key.
212 */
213 while (fgets(line, sizeof(line), f)) {
214 char *cp;
215 char *options;
216
217 linenum++;
218
219 /* Skip leading whitespace, empty and comment lines. */
220 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
221 ;
222 if (!*cp || *cp == '\n' || *cp == '#')
223 continue;
224
225 /*
226 * Check if there are options for this key, and if so,
227 * save their starting address and skip the option part
228 * for now. If there are no options, set the starting
229 * address to NULL.
230 */
231 if (*cp < '0' || *cp > '9') {
232 int quoted = 0;
233 options = cp;
234 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
235 if (*cp == '\\' && cp[1] == '"')
236 cp++; /* Skip both */
237 else if (*cp == '"')
238 quoted = !quoted;
239 }
240 } else
241 options = NULL;
242
243 /* Parse the key from the line. */
244 if (!auth_rsa_read_key(&cp, &bits, e, n)) {
245 debug("%.100s, line %lu: bad key syntax",
246 SSH_USER_PERMITTED_KEYS, linenum);
247 packet_send_debug("%.100s, line %lu: bad key syntax",
248 SSH_USER_PERMITTED_KEYS, linenum);
249 continue;
250 }
251 /* cp now points to the comment part. */
252
253 /* Check if the we have found the desired key (identified by its modulus). */
254 if (BN_cmp(n, client_n) != 0)
255 continue;
256
257 /* check the real bits */
258 if (bits != BN_num_bits(n))
259 log("Warning: %s, line %ld: keysize mismatch: "
260 "actual %d vs. announced %d.",
261 file, linenum, BN_num_bits(n), bits);
262
263 /* We have found the desired key. */
264
265 /* Perform the challenge-response dialog for this key. */
266 if (!auth_rsa_challenge_dialog(e, n)) {
267 /* Wrong response. */
268 verbose("Wrong response to RSA authentication challenge.");
269 packet_send_debug("Wrong response to RSA authentication challenge.");
270 continue;
271 }
272 /*
273 * Correct response. The client has been successfully
274 * authenticated. Note that we have not yet processed the
275 * options; this will be reset if the options cause the
276 * authentication to be rejected.
277 */
278 authenticated = 1;
279
280 /* RSA part of authentication was accepted. Now process the options. */
281 if (options) {
282 while (*options && *options != ' ' && *options != '\t') {
283 cp = "no-port-forwarding";
284 if (strncmp(options, cp, strlen(cp)) == 0) {
285 packet_send_debug("Port forwarding disabled.");
286 no_port_forwarding_flag = 1;
287 options += strlen(cp);
288 goto next_option;
289 }
290 cp = "no-agent-forwarding";
291 if (strncmp(options, cp, strlen(cp)) == 0) {
292 packet_send_debug("Agent forwarding disabled.");
293 no_agent_forwarding_flag = 1;
294 options += strlen(cp);
295 goto next_option;
296 }
297 cp = "no-X11-forwarding";
298 if (strncmp(options, cp, strlen(cp)) == 0) {
299 packet_send_debug("X11 forwarding disabled.");
300 no_x11_forwarding_flag = 1;
301 options += strlen(cp);
302 goto next_option;
303 }
304 cp = "no-pty";
305 if (strncmp(options, cp, strlen(cp)) == 0) {
306 packet_send_debug("Pty allocation disabled.");
307 no_pty_flag = 1;
308 options += strlen(cp);
309 goto next_option;
310 }
311 cp = "command=\"";
312 if (strncmp(options, cp, strlen(cp)) == 0) {
313 int i;
314 options += strlen(cp);
315 forced_command = xmalloc(strlen(options) + 1);
316 i = 0;
317 while (*options) {
318 if (*options == '"')
319 break;
320 if (*options == '\\' && options[1] == '"') {
321 options += 2;
322 forced_command[i++] = '"';
323 continue;
324 }
325 forced_command[i++] = *options++;
326 }
327 if (!*options) {
328 debug("%.100s, line %lu: missing end quote",
329 SSH_USER_PERMITTED_KEYS, linenum);
330 packet_send_debug("%.100s, line %lu: missing end quote",
331 SSH_USER_PERMITTED_KEYS, linenum);
332 continue;
333 }
334 forced_command[i] = 0;
335 packet_send_debug("Forced command: %.900s", forced_command);
336 options++;
337 goto next_option;
338 }
339 cp = "environment=\"";
340 if (strncmp(options, cp, strlen(cp)) == 0) {
341 int i;
342 char *s;
343 struct envstring *new_envstring;
344 options += strlen(cp);
345 s = xmalloc(strlen(options) + 1);
346 i = 0;
347 while (*options) {
348 if (*options == '"')
349 break;
350 if (*options == '\\' && options[1] == '"') {
351 options += 2;
352 s[i++] = '"';
353 continue;
354 }
355 s[i++] = *options++;
356 }
357 if (!*options) {
358 debug("%.100s, line %lu: missing end quote",
359 SSH_USER_PERMITTED_KEYS, linenum);
360 packet_send_debug("%.100s, line %lu: missing end quote",
361 SSH_USER_PERMITTED_KEYS, linenum);
362 continue;
363 }
364 s[i] = 0;
365 packet_send_debug("Adding to environment: %.900s", s);
366 debug("Adding to environment: %.900s", s);
367 options++;
368 new_envstring = xmalloc(sizeof(struct envstring));
369 new_envstring->s = s;
370 new_envstring->next = custom_environment;
371 custom_environment = new_envstring;
372 goto next_option;
373 }
374 cp = "from=\"";
375 if (strncmp(options, cp, strlen(cp)) == 0) {
376 char *patterns = xmalloc(strlen(options) + 1);
377 int i;
378 options += strlen(cp);
379 i = 0;
380 while (*options) {
381 if (*options == '"')
382 break;
383 if (*options == '\\' && options[1] == '"') {
384 options += 2;
385 patterns[i++] = '"';
386 continue;
387 }
388 patterns[i++] = *options++;
389 }
390 if (!*options) {
391 debug("%.100s, line %lu: missing end quote",
392 SSH_USER_PERMITTED_KEYS, linenum);
393 packet_send_debug("%.100s, line %lu: missing end quote",
394 SSH_USER_PERMITTED_KEYS, linenum);
395 continue;
396 }
397 patterns[i] = 0;
398 options++;
399 if (!match_hostname(get_canonical_hostname(), patterns,
400 strlen(patterns)) &&
401 !match_hostname(get_remote_ipaddr(), patterns,
402 strlen(patterns))) {
403 log("RSA authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
404 pw->pw_name, get_canonical_hostname(),
405 get_remote_ipaddr());
406 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
407 get_canonical_hostname());
408 xfree(patterns);
409 /* key invalid for this host, reset flags */
410 authenticated = 0;
411 no_agent_forwarding_flag = 0;
412 no_port_forwarding_flag = 0;
413 no_pty_flag = 0;
414 no_x11_forwarding_flag = 0;
415 while (custom_environment) {
416 struct envstring *ce = custom_environment;
417 custom_environment = ce->next;
418 xfree(ce->s);
419 xfree(ce);
420 }
421 if (forced_command) {
422 xfree(forced_command);
423 forced_command = NULL;
424 }
425 break;
426 }
427 xfree(patterns);
428 /* Host name matches. */
429 goto next_option;
430 }
431 bad_option:
432 log("Bad options in %.100s file, line %lu: %.50s",
433 SSH_USER_PERMITTED_KEYS, linenum, options);
434 packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
435 SSH_USER_PERMITTED_KEYS, linenum, options);
436 authenticated = 0;
437 break;
438
439 next_option:
440 /*
441 * Skip the comma, and move to the next option
442 * (or break out if there are no more).
443 */
444 if (!*options)
445 fatal("Bugs in auth-rsa.c option processing.");
446 if (*options == ' ' || *options == '\t')
447 break; /* End of options. */
448 if (*options != ',')
449 goto bad_option;
450 options++;
451 /* Process the next option. */
452 continue;
453 }
454 }
455 /*
456 * Break out of the loop if authentication was successful;
457 * otherwise continue searching.
458 */
459 if (authenticated)
460 break;
461 }
462
463 /* Restore the privileged uid. */
464 restore_uid();
465
466 /* Close the file. */
467 fclose(f);
468
469 BN_clear_free(n);
470 BN_clear_free(e);
471
472 if (authenticated)
473 packet_send_debug("RSA authentication accepted.");
474
475 /* Return authentication result. */
476 return authenticated;
477}
32
33/* Flags that may be set in authorized_keys options. */
34extern int no_port_forwarding_flag;
35extern int no_agent_forwarding_flag;
36extern int no_x11_forwarding_flag;
37extern int no_pty_flag;
38extern char *forced_command;
39extern struct envstring *custom_environment;
40
41/*
42 * Session identifier that is used to bind key exchange and authentication
43 * responses to a particular session.
44 */
45extern unsigned char session_id[16];
46
47/*
48 * The .ssh/authorized_keys file contains public keys, one per line, in the
49 * following format:
50 * options bits e n comment
51 * where bits, e and n are decimal numbers,
52 * and comment is any string of characters up to newline. The maximum
53 * length of a line is 8000 characters. See the documentation for a
54 * description of the options.
55 */
56
57/*
58 * Performs the RSA authentication challenge-response dialog with the client,
59 * and returns true (non-zero) if the client gave the correct answer to
60 * our challenge; returns zero if the client gives a wrong answer.
61 */
62
63int
64auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n)
65{
66 BIGNUM *challenge, *encrypted_challenge;
67 RSA *pk;
68 BN_CTX *ctx;
69 unsigned char buf[32], mdbuf[16], response[16];
70 MD5_CTX md;
71 unsigned int i;
72 int plen, len;
73
74 encrypted_challenge = BN_new();
75 challenge = BN_new();
76
77 /* Generate a random challenge. */
78 BN_rand(challenge, 256, 0, 0);
79 ctx = BN_CTX_new();
80 BN_mod(challenge, challenge, n, ctx);
81 BN_CTX_free(ctx);
82
83 /* Create the public key data structure. */
84 pk = RSA_new();
85 pk->e = BN_new();
86 BN_copy(pk->e, e);
87 pk->n = BN_new();
88 BN_copy(pk->n, n);
89
90 /* Encrypt the challenge with the public key. */
91 rsa_public_encrypt(encrypted_challenge, challenge, pk);
92 RSA_free(pk);
93
94 /* Send the encrypted challenge to the client. */
95 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
96 packet_put_bignum(encrypted_challenge);
97 packet_send();
98 BN_clear_free(encrypted_challenge);
99 packet_write_wait();
100
101 /* Wait for a response. */
102 packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE);
103 packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE);
104 for (i = 0; i < 16; i++)
105 response[i] = packet_get_char();
106
107 /* The response is MD5 of decrypted challenge plus session id. */
108 len = BN_num_bytes(challenge);
109 if (len <= 0 || len > 32)
110 fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
111 memset(buf, 0, 32);
112 BN_bn2bin(challenge, buf + 32 - len);
113 MD5_Init(&md);
114 MD5_Update(&md, buf, 32);
115 MD5_Update(&md, session_id, 16);
116 MD5_Final(mdbuf, &md);
117 BN_clear_free(challenge);
118
119 /* Verify that the response is the original challenge. */
120 if (memcmp(response, mdbuf, 16) != 0) {
121 /* Wrong answer. */
122 return 0;
123 }
124 /* Correct answer. */
125 return 1;
126}
127
128/*
129 * Performs the RSA authentication dialog with the client. This returns
130 * 0 if the client could not be authenticated, and 1 if authentication was
131 * successful. This may exit if there is a serious protocol violation.
132 */
133
134int
135auth_rsa(struct passwd *pw, BIGNUM *client_n)
136{
137 extern ServerOptions options;
138 char line[8192], file[1024];
139 int authenticated;
140 unsigned int bits;
141 FILE *f;
142 unsigned long linenum = 0;
143 struct stat st;
144 BIGNUM *e, *n;
145
146 /* Temporarily use the user's uid. */
147 temporarily_use_uid(pw->pw_uid);
148
149 /* The authorized keys. */
150 snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
151 SSH_USER_PERMITTED_KEYS);
152
153 /* Fail quietly if file does not exist */
154 if (stat(file, &st) < 0) {
155 /* Restore the privileged uid. */
156 restore_uid();
157 return 0;
158 }
159 /* Open the file containing the authorized keys. */
160 f = fopen(file, "r");
161 if (!f) {
162 /* Restore the privileged uid. */
163 restore_uid();
164 packet_send_debug("Could not open %.900s for reading.", file);
165 packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
166 return 0;
167 }
168 if (options.strict_modes) {
169 int fail = 0;
170 char buf[1024];
171 /* Check open file in order to avoid open/stat races */
172 if (fstat(fileno(f), &st) < 0 ||
173 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
174 (st.st_mode & 022) != 0) {
175 snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
176 "bad ownership or modes for '%s'.", pw->pw_name, file);
177 fail = 1;
178 } else {
179 /* Check path to SSH_USER_PERMITTED_KEYS */
180 int i;
181 static const char *check[] = {
182 "", SSH_USER_DIR, NULL
183 };
184 for (i = 0; check[i]; i++) {
185 snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
186 if (stat(line, &st) < 0 ||
187 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
188 (st.st_mode & 022) != 0) {
189 snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
190 "bad ownership or modes for '%s'.", pw->pw_name, line);
191 fail = 1;
192 break;
193 }
194 }
195 }
196 if (fail) {
197 log(buf);
198 packet_send_debug(buf);
199 restore_uid();
200 return 0;
201 }
202 }
203 /* Flag indicating whether authentication has succeeded. */
204 authenticated = 0;
205
206 e = BN_new();
207 n = BN_new();
208
209 /*
210 * Go though the accepted keys, looking for the current key. If
211 * found, perform a challenge-response dialog to verify that the
212 * user really has the corresponding private key.
213 */
214 while (fgets(line, sizeof(line), f)) {
215 char *cp;
216 char *options;
217
218 linenum++;
219
220 /* Skip leading whitespace, empty and comment lines. */
221 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
222 ;
223 if (!*cp || *cp == '\n' || *cp == '#')
224 continue;
225
226 /*
227 * Check if there are options for this key, and if so,
228 * save their starting address and skip the option part
229 * for now. If there are no options, set the starting
230 * address to NULL.
231 */
232 if (*cp < '0' || *cp > '9') {
233 int quoted = 0;
234 options = cp;
235 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
236 if (*cp == '\\' && cp[1] == '"')
237 cp++; /* Skip both */
238 else if (*cp == '"')
239 quoted = !quoted;
240 }
241 } else
242 options = NULL;
243
244 /* Parse the key from the line. */
245 if (!auth_rsa_read_key(&cp, &bits, e, n)) {
246 debug("%.100s, line %lu: bad key syntax",
247 SSH_USER_PERMITTED_KEYS, linenum);
248 packet_send_debug("%.100s, line %lu: bad key syntax",
249 SSH_USER_PERMITTED_KEYS, linenum);
250 continue;
251 }
252 /* cp now points to the comment part. */
253
254 /* Check if the we have found the desired key (identified by its modulus). */
255 if (BN_cmp(n, client_n) != 0)
256 continue;
257
258 /* check the real bits */
259 if (bits != BN_num_bits(n))
260 log("Warning: %s, line %ld: keysize mismatch: "
261 "actual %d vs. announced %d.",
262 file, linenum, BN_num_bits(n), bits);
263
264 /* We have found the desired key. */
265
266 /* Perform the challenge-response dialog for this key. */
267 if (!auth_rsa_challenge_dialog(e, n)) {
268 /* Wrong response. */
269 verbose("Wrong response to RSA authentication challenge.");
270 packet_send_debug("Wrong response to RSA authentication challenge.");
271 continue;
272 }
273 /*
274 * Correct response. The client has been successfully
275 * authenticated. Note that we have not yet processed the
276 * options; this will be reset if the options cause the
277 * authentication to be rejected.
278 */
279 authenticated = 1;
280
281 /* RSA part of authentication was accepted. Now process the options. */
282 if (options) {
283 while (*options && *options != ' ' && *options != '\t') {
284 cp = "no-port-forwarding";
285 if (strncmp(options, cp, strlen(cp)) == 0) {
286 packet_send_debug("Port forwarding disabled.");
287 no_port_forwarding_flag = 1;
288 options += strlen(cp);
289 goto next_option;
290 }
291 cp = "no-agent-forwarding";
292 if (strncmp(options, cp, strlen(cp)) == 0) {
293 packet_send_debug("Agent forwarding disabled.");
294 no_agent_forwarding_flag = 1;
295 options += strlen(cp);
296 goto next_option;
297 }
298 cp = "no-X11-forwarding";
299 if (strncmp(options, cp, strlen(cp)) == 0) {
300 packet_send_debug("X11 forwarding disabled.");
301 no_x11_forwarding_flag = 1;
302 options += strlen(cp);
303 goto next_option;
304 }
305 cp = "no-pty";
306 if (strncmp(options, cp, strlen(cp)) == 0) {
307 packet_send_debug("Pty allocation disabled.");
308 no_pty_flag = 1;
309 options += strlen(cp);
310 goto next_option;
311 }
312 cp = "command=\"";
313 if (strncmp(options, cp, strlen(cp)) == 0) {
314 int i;
315 options += strlen(cp);
316 forced_command = xmalloc(strlen(options) + 1);
317 i = 0;
318 while (*options) {
319 if (*options == '"')
320 break;
321 if (*options == '\\' && options[1] == '"') {
322 options += 2;
323 forced_command[i++] = '"';
324 continue;
325 }
326 forced_command[i++] = *options++;
327 }
328 if (!*options) {
329 debug("%.100s, line %lu: missing end quote",
330 SSH_USER_PERMITTED_KEYS, linenum);
331 packet_send_debug("%.100s, line %lu: missing end quote",
332 SSH_USER_PERMITTED_KEYS, linenum);
333 continue;
334 }
335 forced_command[i] = 0;
336 packet_send_debug("Forced command: %.900s", forced_command);
337 options++;
338 goto next_option;
339 }
340 cp = "environment=\"";
341 if (strncmp(options, cp, strlen(cp)) == 0) {
342 int i;
343 char *s;
344 struct envstring *new_envstring;
345 options += strlen(cp);
346 s = xmalloc(strlen(options) + 1);
347 i = 0;
348 while (*options) {
349 if (*options == '"')
350 break;
351 if (*options == '\\' && options[1] == '"') {
352 options += 2;
353 s[i++] = '"';
354 continue;
355 }
356 s[i++] = *options++;
357 }
358 if (!*options) {
359 debug("%.100s, line %lu: missing end quote",
360 SSH_USER_PERMITTED_KEYS, linenum);
361 packet_send_debug("%.100s, line %lu: missing end quote",
362 SSH_USER_PERMITTED_KEYS, linenum);
363 continue;
364 }
365 s[i] = 0;
366 packet_send_debug("Adding to environment: %.900s", s);
367 debug("Adding to environment: %.900s", s);
368 options++;
369 new_envstring = xmalloc(sizeof(struct envstring));
370 new_envstring->s = s;
371 new_envstring->next = custom_environment;
372 custom_environment = new_envstring;
373 goto next_option;
374 }
375 cp = "from=\"";
376 if (strncmp(options, cp, strlen(cp)) == 0) {
377 char *patterns = xmalloc(strlen(options) + 1);
378 int i;
379 options += strlen(cp);
380 i = 0;
381 while (*options) {
382 if (*options == '"')
383 break;
384 if (*options == '\\' && options[1] == '"') {
385 options += 2;
386 patterns[i++] = '"';
387 continue;
388 }
389 patterns[i++] = *options++;
390 }
391 if (!*options) {
392 debug("%.100s, line %lu: missing end quote",
393 SSH_USER_PERMITTED_KEYS, linenum);
394 packet_send_debug("%.100s, line %lu: missing end quote",
395 SSH_USER_PERMITTED_KEYS, linenum);
396 continue;
397 }
398 patterns[i] = 0;
399 options++;
400 if (!match_hostname(get_canonical_hostname(), patterns,
401 strlen(patterns)) &&
402 !match_hostname(get_remote_ipaddr(), patterns,
403 strlen(patterns))) {
404 log("RSA authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
405 pw->pw_name, get_canonical_hostname(),
406 get_remote_ipaddr());
407 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
408 get_canonical_hostname());
409 xfree(patterns);
410 /* key invalid for this host, reset flags */
411 authenticated = 0;
412 no_agent_forwarding_flag = 0;
413 no_port_forwarding_flag = 0;
414 no_pty_flag = 0;
415 no_x11_forwarding_flag = 0;
416 while (custom_environment) {
417 struct envstring *ce = custom_environment;
418 custom_environment = ce->next;
419 xfree(ce->s);
420 xfree(ce);
421 }
422 if (forced_command) {
423 xfree(forced_command);
424 forced_command = NULL;
425 }
426 break;
427 }
428 xfree(patterns);
429 /* Host name matches. */
430 goto next_option;
431 }
432 bad_option:
433 log("Bad options in %.100s file, line %lu: %.50s",
434 SSH_USER_PERMITTED_KEYS, linenum, options);
435 packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
436 SSH_USER_PERMITTED_KEYS, linenum, options);
437 authenticated = 0;
438 break;
439
440 next_option:
441 /*
442 * Skip the comma, and move to the next option
443 * (or break out if there are no more).
444 */
445 if (!*options)
446 fatal("Bugs in auth-rsa.c option processing.");
447 if (*options == ' ' || *options == '\t')
448 break; /* End of options. */
449 if (*options != ',')
450 goto bad_option;
451 options++;
452 /* Process the next option. */
453 continue;
454 }
455 }
456 /*
457 * Break out of the loop if authentication was successful;
458 * otherwise continue searching.
459 */
460 if (authenticated)
461 break;
462 }
463
464 /* Restore the privileged uid. */
465 restore_uid();
466
467 /* Close the file. */
468 fclose(f);
469
470 BN_clear_free(n);
471 BN_clear_free(e);
472
473 if (authenticated)
474 packet_send_debug("RSA authentication accepted.");
475
476 /* Return authentication result. */
477 return authenticated;
478}