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}
|