auth-options.c (207319) | auth-options.c (215116) |
---|---|
1/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk Exp $ */ | 1/* $OpenBSD: auth-options.c,v 1.52 2010/05/20 23:46:02 djm Exp $ */ |
2/* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * As far as I am concerned, the code I have written for this software 7 * can be used freely for any purpose. Any derived versions of this 8 * software must be clearly marked as such, and if the derived work is 9 * incompatible with the protocol description in the RFC file, it must be --- 12 unchanged lines hidden (view full) --- 22 23#include "openbsd-compat/sys-queue.h" 24#include "xmalloc.h" 25#include "match.h" 26#include "log.h" 27#include "canohost.h" 28#include "buffer.h" 29#include "channels.h" | 2/* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * As far as I am concerned, the code I have written for this software 7 * can be used freely for any purpose. Any derived versions of this 8 * software must be clearly marked as such, and if the derived work is 9 * incompatible with the protocol description in the RFC file, it must be --- 12 unchanged lines hidden (view full) --- 22 23#include "openbsd-compat/sys-queue.h" 24#include "xmalloc.h" 25#include "match.h" 26#include "log.h" 27#include "canohost.h" 28#include "buffer.h" 29#include "channels.h" |
30#include "auth-options.h" | |
31#include "servconf.h" 32#include "misc.h" 33#include "key.h" | 30#include "servconf.h" 31#include "misc.h" 32#include "key.h" |
33#include "auth-options.h" |
|
34#include "hostfile.h" 35#include "auth.h" 36#ifdef GSSAPI 37#include "ssh-gss.h" 38#endif 39#include "monitor_wrap.h" 40 41/* Flags set authorized_keys flags */ --- 8 unchanged lines hidden (view full) --- 50char *forced_command = NULL; 51 52/* "environment=" options. */ 53struct envstring *custom_environment = NULL; 54 55/* "tunnel=" option. */ 56int forced_tun_device = -1; 57 | 34#include "hostfile.h" 35#include "auth.h" 36#ifdef GSSAPI 37#include "ssh-gss.h" 38#endif 39#include "monitor_wrap.h" 40 41/* Flags set authorized_keys flags */ --- 8 unchanged lines hidden (view full) --- 50char *forced_command = NULL; 51 52/* "environment=" options. */ 53struct envstring *custom_environment = NULL; 54 55/* "tunnel=" option. */ 56int forced_tun_device = -1; 57 |
58/* "principals=" option. */ 59char *authorized_principals = NULL; 60 |
|
58extern ServerOptions options; 59 60void 61auth_clear_options(void) 62{ 63 no_agent_forwarding_flag = 0; 64 no_port_forwarding_flag = 0; 65 no_pty_flag = 0; --- 5 unchanged lines hidden (view full) --- 71 custom_environment = ce->next; 72 xfree(ce->s); 73 xfree(ce); 74 } 75 if (forced_command) { 76 xfree(forced_command); 77 forced_command = NULL; 78 } | 61extern ServerOptions options; 62 63void 64auth_clear_options(void) 65{ 66 no_agent_forwarding_flag = 0; 67 no_port_forwarding_flag = 0; 68 no_pty_flag = 0; --- 5 unchanged lines hidden (view full) --- 74 custom_environment = ce->next; 75 xfree(ce->s); 76 xfree(ce); 77 } 78 if (forced_command) { 79 xfree(forced_command); 80 forced_command = NULL; 81 } |
82 if (authorized_principals) { 83 xfree(authorized_principals); 84 authorized_principals = NULL; 85 } |
|
79 forced_tun_device = -1; 80 channel_clear_permitted_opens(); 81} 82 83/* 84 * return 1 if access is granted, 0 if not. 85 * side effect: sets key option flags 86 */ --- 49 unchanged lines hidden (view full) --- 136 auth_debug_add("User rc file execution disabled."); 137 no_user_rc = 1; 138 opts += strlen(cp); 139 goto next_option; 140 } 141 cp = "command=\""; 142 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 143 opts += strlen(cp); | 86 forced_tun_device = -1; 87 channel_clear_permitted_opens(); 88} 89 90/* 91 * return 1 if access is granted, 0 if not. 92 * side effect: sets key option flags 93 */ --- 49 unchanged lines hidden (view full) --- 143 auth_debug_add("User rc file execution disabled."); 144 no_user_rc = 1; 145 opts += strlen(cp); 146 goto next_option; 147 } 148 cp = "command=\""; 149 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 150 opts += strlen(cp); |
151 if (forced_command != NULL) 152 xfree(forced_command); |
|
144 forced_command = xmalloc(strlen(opts) + 1); 145 i = 0; 146 while (*opts) { 147 if (*opts == '"') 148 break; 149 if (*opts == '\\' && opts[1] == '"') { 150 opts += 2; 151 forced_command[i++] = '"'; --- 10 unchanged lines hidden (view full) --- 162 forced_command = NULL; 163 goto bad_option; 164 } 165 forced_command[i] = '\0'; 166 auth_debug_add("Forced command: %.900s", forced_command); 167 opts++; 168 goto next_option; 169 } | 153 forced_command = xmalloc(strlen(opts) + 1); 154 i = 0; 155 while (*opts) { 156 if (*opts == '"') 157 break; 158 if (*opts == '\\' && opts[1] == '"') { 159 opts += 2; 160 forced_command[i++] = '"'; --- 10 unchanged lines hidden (view full) --- 171 forced_command = NULL; 172 goto bad_option; 173 } 174 forced_command[i] = '\0'; 175 auth_debug_add("Forced command: %.900s", forced_command); 176 opts++; 177 goto next_option; 178 } |
179 cp = "principals=\""; 180 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 181 opts += strlen(cp); 182 if (authorized_principals != NULL) 183 xfree(authorized_principals); 184 authorized_principals = xmalloc(strlen(opts) + 1); 185 i = 0; 186 while (*opts) { 187 if (*opts == '"') 188 break; 189 if (*opts == '\\' && opts[1] == '"') { 190 opts += 2; 191 authorized_principals[i++] = '"'; 192 continue; 193 } 194 authorized_principals[i++] = *opts++; 195 } 196 if (!*opts) { 197 debug("%.100s, line %lu: missing end quote", 198 file, linenum); 199 auth_debug_add("%.100s, line %lu: missing end quote", 200 file, linenum); 201 xfree(authorized_principals); 202 authorized_principals = NULL; 203 goto bad_option; 204 } 205 authorized_principals[i] = '\0'; 206 auth_debug_add("principals: %.900s", 207 authorized_principals); 208 opts++; 209 goto next_option; 210 } |
|
170 cp = "environment=\""; 171 if (options.permit_user_env && 172 strncasecmp(opts, cp, strlen(cp)) == 0) { 173 char *s; 174 struct envstring *new_envstring; 175 176 opts += strlen(cp); 177 s = xmalloc(strlen(opts) + 1); --- 193 unchanged lines hidden (view full) --- 371 file, linenum, opts); 372 auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 373 file, linenum, opts); 374 375 /* deny access */ 376 return 0; 377} 378 | 211 cp = "environment=\""; 212 if (options.permit_user_env && 213 strncasecmp(opts, cp, strlen(cp)) == 0) { 214 char *s; 215 struct envstring *new_envstring; 216 217 opts += strlen(cp); 218 s = xmalloc(strlen(opts) + 1); --- 193 unchanged lines hidden (view full) --- 412 file, linenum, opts); 413 auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 414 file, linenum, opts); 415 416 /* deny access */ 417 return 0; 418} 419 |
379/* 380 * Set options from certificate constraints. These supersede user key options 381 * so this must be called after auth_parse_options(). 382 */ 383int 384auth_cert_constraints(Buffer *c_orig, struct passwd *pw) | 420#define OPTIONS_CRITICAL 1 421#define OPTIONS_EXTENSIONS 2 422static int 423parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, 424 u_int which, int crit, 425 int *cert_no_port_forwarding_flag, 426 int *cert_no_agent_forwarding_flag, 427 int *cert_no_x11_forwarding_flag, 428 int *cert_no_pty_flag, 429 int *cert_no_user_rc, 430 char **cert_forced_command, 431 int *cert_source_address_done) |
385{ | 432{ |
433 char *command, *allowed; 434 const char *remote_ip; |
|
386 u_char *name = NULL, *data_blob = NULL; 387 u_int nlen, dlen, clen; 388 Buffer c, data; | 435 u_char *name = NULL, *data_blob = NULL; 436 u_int nlen, dlen, clen; 437 Buffer c, data; |
389 int ret = -1; | 438 int ret = -1, found; |
390 | 439 |
391 int cert_no_port_forwarding_flag = 1; 392 int cert_no_agent_forwarding_flag = 1; 393 int cert_no_x11_forwarding_flag = 1; 394 int cert_no_pty_flag = 1; 395 int cert_no_user_rc = 1; 396 char *cert_forced_command = NULL; 397 int cert_source_address_done = 0; 398 | |
399 buffer_init(&data); 400 401 /* Make copy to avoid altering original */ 402 buffer_init(&c); | 440 buffer_init(&data); 441 442 /* Make copy to avoid altering original */ 443 buffer_init(&c); |
403 buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig)); | 444 buffer_append(&c, optblob, optblob_len); |
404 405 while (buffer_len(&c) > 0) { 406 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || 407 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { | 445 446 while (buffer_len(&c) > 0) { 447 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || 448 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { |
408 error("Certificate constraints corrupt"); | 449 error("Certificate options corrupt"); |
409 goto out; 410 } 411 buffer_append(&data, data_blob, dlen); | 450 goto out; 451 } 452 buffer_append(&data, data_blob, dlen); |
412 debug3("found certificate constraint \"%.100s\" len %u", | 453 debug3("found certificate option \"%.100s\" len %u", |
413 name, dlen); 414 if (strlen(name) != nlen) { 415 error("Certificate constraint name contains \\0"); 416 goto out; 417 } | 454 name, dlen); 455 if (strlen(name) != nlen) { 456 error("Certificate constraint name contains \\0"); 457 goto out; 458 } |
418 if (strcmp(name, "permit-X11-forwarding") == 0) 419 cert_no_x11_forwarding_flag = 0; 420 else if (strcmp(name, "permit-agent-forwarding") == 0) 421 cert_no_agent_forwarding_flag = 0; 422 else if (strcmp(name, "permit-port-forwarding") == 0) 423 cert_no_port_forwarding_flag = 0; 424 else if (strcmp(name, "permit-pty") == 0) 425 cert_no_pty_flag = 0; 426 else if (strcmp(name, "permit-user-rc") == 0) 427 cert_no_user_rc = 0; 428 else if (strcmp(name, "force-command") == 0) { 429 char *command = buffer_get_string_ret(&data, &clen); 430 431 if (command == NULL) { 432 error("Certificate constraint \"%s\" corrupt", 433 name); 434 goto out; | 459 found = 0; 460 if ((which & OPTIONS_EXTENSIONS) != 0) { 461 if (strcmp(name, "permit-X11-forwarding") == 0) { 462 *cert_no_x11_forwarding_flag = 0; 463 found = 1; 464 } else if (strcmp(name, 465 "permit-agent-forwarding") == 0) { 466 *cert_no_agent_forwarding_flag = 0; 467 found = 1; 468 } else if (strcmp(name, 469 "permit-port-forwarding") == 0) { 470 *cert_no_port_forwarding_flag = 0; 471 found = 1; 472 } else if (strcmp(name, "permit-pty") == 0) { 473 *cert_no_pty_flag = 0; 474 found = 1; 475 } else if (strcmp(name, "permit-user-rc") == 0) { 476 *cert_no_user_rc = 0; 477 found = 1; |
435 } | 478 } |
436 if (strlen(command) != clen) { 437 error("force-command constraint contains \\0"); 438 goto out; | 479 } 480 if (!found && (which & OPTIONS_CRITICAL) != 0) { 481 if (strcmp(name, "force-command") == 0) { 482 if ((command = buffer_get_string_ret(&data, 483 &clen)) == NULL) { 484 error("Certificate constraint \"%s\" " 485 "corrupt", name); 486 goto out; 487 } 488 if (strlen(command) != clen) { 489 error("force-command constraint " 490 "contains \\0"); 491 goto out; 492 } 493 if (*cert_forced_command != NULL) { 494 error("Certificate has multiple " 495 "force-command options"); 496 xfree(command); 497 goto out; 498 } 499 *cert_forced_command = command; 500 found = 1; |
439 } | 501 } |
440 if (cert_forced_command != NULL) { 441 error("Certificate has multiple " 442 "force-command constraints"); 443 xfree(command); 444 goto out; | 502 if (strcmp(name, "source-address") == 0) { 503 if ((allowed = buffer_get_string_ret(&data, 504 &clen)) == NULL) { 505 error("Certificate constraint " 506 "\"%s\" corrupt", name); 507 goto out; 508 } 509 if (strlen(allowed) != clen) { 510 error("source-address constraint " 511 "contains \\0"); 512 goto out; 513 } 514 if ((*cert_source_address_done)++) { 515 error("Certificate has multiple " 516 "source-address options"); 517 xfree(allowed); 518 goto out; 519 } 520 remote_ip = get_remote_ipaddr(); 521 switch (addr_match_cidr_list(remote_ip, 522 allowed)) { 523 case 1: 524 /* accepted */ 525 xfree(allowed); 526 break; 527 case 0: 528 /* no match */ 529 logit("Authentication tried for %.100s " 530 "with valid certificate but not " 531 "from a permitted host " 532 "(ip=%.200s).", pw->pw_name, 533 remote_ip); 534 auth_debug_add("Your address '%.200s' " 535 "is not permitted to use this " 536 "certificate for login.", 537 remote_ip); 538 xfree(allowed); 539 goto out; 540 case -1: 541 error("Certificate source-address " 542 "contents invalid"); 543 xfree(allowed); 544 goto out; 545 } 546 found = 1; |
445 } | 547 } |
446 cert_forced_command = command; 447 } else if (strcmp(name, "source-address") == 0) { 448 char *allowed = buffer_get_string_ret(&data, &clen); 449 const char *remote_ip = get_remote_ipaddr(); 450 451 if (allowed == NULL) { 452 error("Certificate constraint \"%s\" corrupt", 453 name); 454 goto out; 455 } 456 if (strlen(allowed) != clen) { 457 error("source-address constraint contains \\0"); 458 goto out; 459 } 460 if (cert_source_address_done++) { 461 error("Certificate has multiple " 462 "source-address constraints"); 463 xfree(allowed); 464 goto out; 465 } 466 switch (addr_match_cidr_list(remote_ip, allowed)) { 467 case 1: 468 /* accepted */ 469 xfree(allowed); 470 break; 471 case 0: 472 /* no match */ 473 logit("Authentication tried for %.100s with " 474 "valid certificate but not from a " 475 "permitted host (ip=%.200s).", 476 pw->pw_name, remote_ip); 477 auth_debug_add("Your address '%.200s' is not " 478 "permitted to use this certificate for " 479 "login.", remote_ip); 480 xfree(allowed); 481 goto out; 482 case -1: 483 error("Certificate source-address contents " 484 "invalid"); 485 xfree(allowed); 486 goto out; 487 } 488 } else { 489 error("Certificate constraint \"%s\" is not supported", 490 name); 491 goto out; | |
492 } 493 | 548 } 549 |
494 if (buffer_len(&data) != 0) { 495 error("Certificate constraint \"%s\" corrupt " | 550 if (!found) { 551 if (crit) { 552 error("Certificate critical option \"%s\" " 553 "is not supported", name); 554 goto out; 555 } else { 556 logit("Certificate extension \"%s\" " 557 "is not supported", name); 558 } 559 } else if (buffer_len(&data) != 0) { 560 error("Certificate option \"%s\" corrupt " |
496 "(extra data)", name); 497 goto out; 498 } 499 buffer_clear(&data); 500 xfree(name); 501 xfree(data_blob); 502 name = data_blob = NULL; 503 } | 561 "(extra data)", name); 562 goto out; 563 } 564 buffer_clear(&data); 565 xfree(name); 566 xfree(data_blob); 567 name = data_blob = NULL; 568 } |
504 505 /* successfully parsed all constraints */ | 569 /* successfully parsed all options */ |
506 ret = 0; 507 | 570 ret = 0; 571 |
572 out: 573 if (ret != 0 && 574 cert_forced_command != NULL && 575 *cert_forced_command != NULL) { 576 xfree(*cert_forced_command); 577 *cert_forced_command = NULL; 578 } 579 if (name != NULL) 580 xfree(name); 581 if (data_blob != NULL) 582 xfree(data_blob); 583 buffer_free(&data); 584 buffer_free(&c); 585 return ret; 586} 587 588/* 589 * Set options from critical certificate options. These supersede user key 590 * options so this must be called after auth_parse_options(). 591 */ 592int 593auth_cert_options(Key *k, struct passwd *pw) 594{ 595 int cert_no_port_forwarding_flag = 1; 596 int cert_no_agent_forwarding_flag = 1; 597 int cert_no_x11_forwarding_flag = 1; 598 int cert_no_pty_flag = 1; 599 int cert_no_user_rc = 1; 600 char *cert_forced_command = NULL; 601 int cert_source_address_done = 0; 602 603 if (key_cert_is_legacy(k)) { 604 /* All options are in the one field for v00 certs */ 605 if (parse_option_list(buffer_ptr(&k->cert->critical), 606 buffer_len(&k->cert->critical), pw, 607 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, 608 &cert_no_port_forwarding_flag, 609 &cert_no_agent_forwarding_flag, 610 &cert_no_x11_forwarding_flag, 611 &cert_no_pty_flag, 612 &cert_no_user_rc, 613 &cert_forced_command, 614 &cert_source_address_done) == -1) 615 return -1; 616 } else { 617 /* Separate options and extensions for v01 certs */ 618 if (parse_option_list(buffer_ptr(&k->cert->critical), 619 buffer_len(&k->cert->critical), pw, 620 OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, 621 &cert_forced_command, 622 &cert_source_address_done) == -1) 623 return -1; 624 if (parse_option_list(buffer_ptr(&k->cert->extensions), 625 buffer_len(&k->cert->extensions), pw, 626 OPTIONS_EXTENSIONS, 1, 627 &cert_no_port_forwarding_flag, 628 &cert_no_agent_forwarding_flag, 629 &cert_no_x11_forwarding_flag, 630 &cert_no_pty_flag, 631 &cert_no_user_rc, 632 NULL, NULL) == -1) 633 return -1; 634 } 635 |
|
508 no_port_forwarding_flag |= cert_no_port_forwarding_flag; 509 no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; 510 no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; 511 no_pty_flag |= cert_no_pty_flag; 512 no_user_rc |= cert_no_user_rc; 513 /* CA-specified forced command supersedes key option */ 514 if (cert_forced_command != NULL) { 515 if (forced_command != NULL) 516 xfree(forced_command); 517 forced_command = cert_forced_command; 518 } | 636 no_port_forwarding_flag |= cert_no_port_forwarding_flag; 637 no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; 638 no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; 639 no_pty_flag |= cert_no_pty_flag; 640 no_user_rc |= cert_no_user_rc; 641 /* CA-specified forced command supersedes key option */ 642 if (cert_forced_command != NULL) { 643 if (forced_command != NULL) 644 xfree(forced_command); 645 forced_command = cert_forced_command; 646 } |
519 520 out: 521 if (name != NULL) 522 xfree(name); 523 if (data_blob != NULL) 524 xfree(data_blob); 525 buffer_free(&data); 526 buffer_free(&c); 527 return ret; | 647 return 0; |
528} 529 | 648} 649 |