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