diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 218 |
1 files changed, 141 insertions, 77 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.492 2017/09/12 06:32:07 djm Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.506 2018/03/03 03:15:51 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -123,6 +123,7 @@ | |||
123 | #endif | 123 | #endif |
124 | #include "monitor_wrap.h" | 124 | #include "monitor_wrap.h" |
125 | #include "ssh-sandbox.h" | 125 | #include "ssh-sandbox.h" |
126 | #include "auth-options.h" | ||
126 | #include "version.h" | 127 | #include "version.h" |
127 | #include "ssherr.h" | 128 | #include "ssherr.h" |
128 | 129 | ||
@@ -159,7 +160,12 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; | |||
159 | */ | 160 | */ |
160 | int debug_flag = 0; | 161 | int debug_flag = 0; |
161 | 162 | ||
162 | /* Flag indicating that the daemon should only test the configuration and keys. */ | 163 | /* |
164 | * Indicating that the daemon should only test the configuration and keys. | ||
165 | * If test_flag > 1 ("-T" flag), then sshd will also dump the effective | ||
166 | * configuration, optionally using connection information provided by the | ||
167 | * "-C" flag. | ||
168 | */ | ||
163 | int test_flag = 0; | 169 | int test_flag = 0; |
164 | 170 | ||
165 | /* Flag indicating that the daemon is being started from inetd. */ | 171 | /* Flag indicating that the daemon is being started from inetd. */ |
@@ -242,6 +248,9 @@ static int privsep_chroot = 1; | |||
242 | /* global authentication context */ | 248 | /* global authentication context */ |
243 | Authctxt *the_authctxt = NULL; | 249 | Authctxt *the_authctxt = NULL; |
244 | 250 | ||
251 | /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ | ||
252 | struct sshauthopt *auth_opts = NULL; | ||
253 | |||
245 | /* sshd_config buffer */ | 254 | /* sshd_config buffer */ |
246 | Buffer cfg; | 255 | Buffer cfg; |
247 | 256 | ||
@@ -293,7 +302,6 @@ sighup_handler(int sig) | |||
293 | int save_errno = errno; | 302 | int save_errno = errno; |
294 | 303 | ||
295 | received_sighup = 1; | 304 | received_sighup = 1; |
296 | signal(SIGHUP, sighup_handler); | ||
297 | errno = save_errno; | 305 | errno = save_errno; |
298 | } | 306 | } |
299 | 307 | ||
@@ -343,8 +351,6 @@ main_sigchld_handler(int sig) | |||
343 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || | 351 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || |
344 | (pid < 0 && errno == EINTR)) | 352 | (pid < 0 && errno == EINTR)) |
345 | ; | 353 | ; |
346 | |||
347 | signal(SIGCHLD, main_sigchld_handler); | ||
348 | errno = save_errno; | 354 | errno = save_errno; |
349 | } | 355 | } |
350 | 356 | ||
@@ -457,16 +463,12 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | |||
457 | logit("Client version \"%.100s\" uses unsafe RSA signature " | 463 | logit("Client version \"%.100s\" uses unsafe RSA signature " |
458 | "scheme; disabling use of RSA keys", remote_version); | 464 | "scheme; disabling use of RSA keys", remote_version); |
459 | } | 465 | } |
460 | if ((ssh->compat & SSH_BUG_DERIVEKEY) != 0) { | ||
461 | fatal("Client version \"%.100s\" uses unsafe key agreement; " | ||
462 | "refusing connection", remote_version); | ||
463 | } | ||
464 | 466 | ||
465 | chop(server_version_string); | 467 | chop(server_version_string); |
466 | debug("Local version string %.200s", server_version_string); | 468 | debug("Local version string %.200s", server_version_string); |
467 | 469 | ||
468 | if (remote_major != 2 || | 470 | if (remote_major != 2 && |
469 | (remote_major == 1 && remote_minor != 99)) { | 471 | !(remote_major == 1 && remote_minor == 99)) { |
470 | s = "Protocol major versions differ.\n"; | 472 | s = "Protocol major versions differ.\n"; |
471 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | 473 | (void) atomicio(vwrite, sock_out, s, strlen(s)); |
472 | close(sock_in); | 474 | close(sock_in); |
@@ -483,7 +485,7 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | |||
483 | void | 485 | void |
484 | destroy_sensitive_data(void) | 486 | destroy_sensitive_data(void) |
485 | { | 487 | { |
486 | int i; | 488 | u_int i; |
487 | 489 | ||
488 | for (i = 0; i < options.num_host_key_files; i++) { | 490 | for (i = 0; i < options.num_host_key_files; i++) { |
489 | if (sensitive_data.host_keys[i]) { | 491 | if (sensitive_data.host_keys[i]) { |
@@ -502,7 +504,7 @@ void | |||
502 | demote_sensitive_data(void) | 504 | demote_sensitive_data(void) |
503 | { | 505 | { |
504 | struct sshkey *tmp; | 506 | struct sshkey *tmp; |
505 | int i; | 507 | u_int i; |
506 | 508 | ||
507 | for (i = 0; i < options.num_host_key_files; i++) { | 509 | for (i = 0; i < options.num_host_key_files; i++) { |
508 | if (sensitive_data.host_keys[i]) { | 510 | if (sensitive_data.host_keys[i]) { |
@@ -701,7 +703,7 @@ list_hostkey_types(void) | |||
701 | Buffer b; | 703 | Buffer b; |
702 | const char *p; | 704 | const char *p; |
703 | char *ret; | 705 | char *ret; |
704 | int i; | 706 | u_int i; |
705 | struct sshkey *key; | 707 | struct sshkey *key; |
706 | 708 | ||
707 | buffer_init(&b); | 709 | buffer_init(&b); |
@@ -723,6 +725,7 @@ list_hostkey_types(void) | |||
723 | case KEY_DSA: | 725 | case KEY_DSA: |
724 | case KEY_ECDSA: | 726 | case KEY_ECDSA: |
725 | case KEY_ED25519: | 727 | case KEY_ED25519: |
728 | case KEY_XMSS: | ||
726 | if (buffer_len(&b) > 0) | 729 | if (buffer_len(&b) > 0) |
727 | buffer_append(&b, ",", 1); | 730 | buffer_append(&b, ",", 1); |
728 | p = key_ssh_name(key); | 731 | p = key_ssh_name(key); |
@@ -744,6 +747,7 @@ list_hostkey_types(void) | |||
744 | case KEY_DSA_CERT: | 747 | case KEY_DSA_CERT: |
745 | case KEY_ECDSA_CERT: | 748 | case KEY_ECDSA_CERT: |
746 | case KEY_ED25519_CERT: | 749 | case KEY_ED25519_CERT: |
750 | case KEY_XMSS_CERT: | ||
747 | if (buffer_len(&b) > 0) | 751 | if (buffer_len(&b) > 0) |
748 | buffer_append(&b, ",", 1); | 752 | buffer_append(&b, ",", 1); |
749 | p = key_ssh_name(key); | 753 | p = key_ssh_name(key); |
@@ -761,7 +765,7 @@ list_hostkey_types(void) | |||
761 | static struct sshkey * | 765 | static struct sshkey * |
762 | get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) | 766 | get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) |
763 | { | 767 | { |
764 | int i; | 768 | u_int i; |
765 | struct sshkey *key; | 769 | struct sshkey *key; |
766 | 770 | ||
767 | for (i = 0; i < options.num_host_key_files; i++) { | 771 | for (i = 0; i < options.num_host_key_files; i++) { |
@@ -770,6 +774,7 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) | |||
770 | case KEY_DSA_CERT: | 774 | case KEY_DSA_CERT: |
771 | case KEY_ECDSA_CERT: | 775 | case KEY_ECDSA_CERT: |
772 | case KEY_ED25519_CERT: | 776 | case KEY_ED25519_CERT: |
777 | case KEY_XMSS_CERT: | ||
773 | key = sensitive_data.host_certificates[i]; | 778 | key = sensitive_data.host_certificates[i]; |
774 | break; | 779 | break; |
775 | default: | 780 | default: |
@@ -801,7 +806,7 @@ get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) | |||
801 | struct sshkey * | 806 | struct sshkey * |
802 | get_hostkey_by_index(int ind) | 807 | get_hostkey_by_index(int ind) |
803 | { | 808 | { |
804 | if (ind < 0 || ind >= options.num_host_key_files) | 809 | if (ind < 0 || (u_int)ind >= options.num_host_key_files) |
805 | return (NULL); | 810 | return (NULL); |
806 | return (sensitive_data.host_keys[ind]); | 811 | return (sensitive_data.host_keys[ind]); |
807 | } | 812 | } |
@@ -809,7 +814,7 @@ get_hostkey_by_index(int ind) | |||
809 | struct sshkey * | 814 | struct sshkey * |
810 | get_hostkey_public_by_index(int ind, struct ssh *ssh) | 815 | get_hostkey_public_by_index(int ind, struct ssh *ssh) |
811 | { | 816 | { |
812 | if (ind < 0 || ind >= options.num_host_key_files) | 817 | if (ind < 0 || (u_int)ind >= options.num_host_key_files) |
813 | return (NULL); | 818 | return (NULL); |
814 | return (sensitive_data.host_pubkeys[ind]); | 819 | return (sensitive_data.host_pubkeys[ind]); |
815 | } | 820 | } |
@@ -817,7 +822,7 @@ get_hostkey_public_by_index(int ind, struct ssh *ssh) | |||
817 | int | 822 | int |
818 | get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) | 823 | get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) |
819 | { | 824 | { |
820 | int i; | 825 | u_int i; |
821 | 826 | ||
822 | for (i = 0; i < options.num_host_key_files; i++) { | 827 | for (i = 0; i < options.num_host_key_files; i++) { |
823 | if (key_is_cert(key)) { | 828 | if (key_is_cert(key)) { |
@@ -846,7 +851,8 @@ notify_hostkeys(struct ssh *ssh) | |||
846 | { | 851 | { |
847 | struct sshbuf *buf; | 852 | struct sshbuf *buf; |
848 | struct sshkey *key; | 853 | struct sshkey *key; |
849 | int i, nkeys, r; | 854 | u_int i, nkeys; |
855 | int r; | ||
850 | char *fp; | 856 | char *fp; |
851 | 857 | ||
852 | /* Some clients cannot cope with the hostkeys message, skip those. */ | 858 | /* Some clients cannot cope with the hostkeys message, skip those. */ |
@@ -877,7 +883,7 @@ notify_hostkeys(struct ssh *ssh) | |||
877 | packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); | 883 | packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); |
878 | nkeys++; | 884 | nkeys++; |
879 | } | 885 | } |
880 | debug3("%s: sent %d hostkeys", __func__, nkeys); | 886 | debug3("%s: sent %u hostkeys", __func__, nkeys); |
881 | if (nkeys == 0) | 887 | if (nkeys == 0) |
882 | fatal("%s: no hostkeys", __func__); | 888 | fatal("%s: no hostkeys", __func__); |
883 | packet_send(); | 889 | packet_send(); |
@@ -1030,13 +1036,13 @@ server_accept_inetd(int *sock_in, int *sock_out) | |||
1030 | * Listen for TCP connections | 1036 | * Listen for TCP connections |
1031 | */ | 1037 | */ |
1032 | static void | 1038 | static void |
1033 | server_listen(void) | 1039 | listen_on_addrs(struct listenaddr *la) |
1034 | { | 1040 | { |
1035 | int ret, listen_sock, on = 1; | 1041 | int ret, listen_sock; |
1036 | struct addrinfo *ai; | 1042 | struct addrinfo *ai; |
1037 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 1043 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
1038 | 1044 | ||
1039 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { | 1045 | for (ai = la->addrs; ai; ai = ai->ai_next) { |
1040 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | 1046 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) |
1041 | continue; | 1047 | continue; |
1042 | if (num_listen_socks >= MAX_LISTEN_SOCKS) | 1048 | if (num_listen_socks >= MAX_LISTEN_SOCKS) |
@@ -1066,13 +1072,13 @@ server_listen(void) | |||
1066 | close(listen_sock); | 1072 | close(listen_sock); |
1067 | continue; | 1073 | continue; |
1068 | } | 1074 | } |
1069 | /* | 1075 | /* Socket options */ |
1070 | * Set socket options. | 1076 | set_reuseaddr(listen_sock); |
1071 | * Allow local port reuse in TIME_WAIT. | 1077 | if (la->rdomain != NULL && |
1072 | */ | 1078 | set_rdomain(listen_sock, la->rdomain) == -1) { |
1073 | if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, | 1079 | close(listen_sock); |
1074 | &on, sizeof(on)) == -1) | 1080 | continue; |
1075 | error("setsockopt SO_REUSEADDR: %s", strerror(errno)); | 1081 | } |
1076 | 1082 | ||
1077 | /* Only communicate in IPv6 over AF_INET6 sockets. */ | 1083 | /* Only communicate in IPv6 over AF_INET6 sockets. */ |
1078 | if (ai->ai_family == AF_INET6) | 1084 | if (ai->ai_family == AF_INET6) |
@@ -1094,9 +1100,28 @@ server_listen(void) | |||
1094 | if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) | 1100 | if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) |
1095 | fatal("listen on [%s]:%s: %.100s", | 1101 | fatal("listen on [%s]:%s: %.100s", |
1096 | ntop, strport, strerror(errno)); | 1102 | ntop, strport, strerror(errno)); |
1097 | logit("Server listening on %s port %s.", ntop, strport); | 1103 | logit("Server listening on %s port %s%s%s.", |
1104 | ntop, strport, | ||
1105 | la->rdomain == NULL ? "" : " rdomain ", | ||
1106 | la->rdomain == NULL ? "" : la->rdomain); | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | static void | ||
1111 | server_listen(void) | ||
1112 | { | ||
1113 | u_int i; | ||
1114 | |||
1115 | for (i = 0; i < options.num_listen_addrs; i++) { | ||
1116 | listen_on_addrs(&options.listen_addrs[i]); | ||
1117 | freeaddrinfo(options.listen_addrs[i].addrs); | ||
1118 | free(options.listen_addrs[i].rdomain); | ||
1119 | memset(&options.listen_addrs[i], 0, | ||
1120 | sizeof(options.listen_addrs[i])); | ||
1098 | } | 1121 | } |
1099 | freeaddrinfo(options.listen_addrs); | 1122 | free(options.listen_addrs); |
1123 | options.listen_addrs = NULL; | ||
1124 | options.num_listen_addrs = 0; | ||
1100 | 1125 | ||
1101 | if (!num_listen_socks) | 1126 | if (!num_listen_socks) |
1102 | fatal("Cannot bind any address."); | 1127 | fatal("Cannot bind any address."); |
@@ -1364,6 +1389,46 @@ check_ip_options(struct ssh *ssh) | |||
1364 | #endif /* IP_OPTIONS */ | 1389 | #endif /* IP_OPTIONS */ |
1365 | } | 1390 | } |
1366 | 1391 | ||
1392 | /* Set the routing domain for this process */ | ||
1393 | static void | ||
1394 | set_process_rdomain(struct ssh *ssh, const char *name) | ||
1395 | { | ||
1396 | #if defined(HAVE_SYS_SET_PROCESS_RDOMAIN) | ||
1397 | if (name == NULL) | ||
1398 | return; /* default */ | ||
1399 | |||
1400 | if (strcmp(name, "%D") == 0) { | ||
1401 | /* "expands" to routing domain of connection */ | ||
1402 | if ((name = ssh_packet_rdomain_in(ssh)) == NULL) | ||
1403 | return; | ||
1404 | } | ||
1405 | /* NB. We don't pass 'ssh' to sys_set_process_rdomain() */ | ||
1406 | return sys_set_process_rdomain(name); | ||
1407 | #elif defined(__OpenBSD__) | ||
1408 | int rtable, ortable = getrtable(); | ||
1409 | const char *errstr; | ||
1410 | |||
1411 | if (name == NULL) | ||
1412 | return; /* default */ | ||
1413 | |||
1414 | if (strcmp(name, "%D") == 0) { | ||
1415 | /* "expands" to routing domain of connection */ | ||
1416 | if ((name = ssh_packet_rdomain_in(ssh)) == NULL) | ||
1417 | return; | ||
1418 | } | ||
1419 | |||
1420 | rtable = (int)strtonum(name, 0, 255, &errstr); | ||
1421 | if (errstr != NULL) /* Shouldn't happen */ | ||
1422 | fatal("Invalid routing domain \"%s\": %s", name, errstr); | ||
1423 | if (rtable != ortable && setrtable(rtable) != 0) | ||
1424 | fatal("Unable to set routing domain %d: %s", | ||
1425 | rtable, strerror(errno)); | ||
1426 | debug("%s: set routing domain %d (was %d)", __func__, rtable, ortable); | ||
1427 | #else /* defined(__OpenBSD__) */ | ||
1428 | fatal("Unable to set routing domain: not supported in this platform"); | ||
1429 | #endif | ||
1430 | } | ||
1431 | |||
1367 | /* | 1432 | /* |
1368 | * Main program for the daemon. | 1433 | * Main program for the daemon. |
1369 | */ | 1434 | */ |
@@ -1373,20 +1438,19 @@ main(int ac, char **av) | |||
1373 | struct ssh *ssh = NULL; | 1438 | struct ssh *ssh = NULL; |
1374 | extern char *optarg; | 1439 | extern char *optarg; |
1375 | extern int optind; | 1440 | extern int optind; |
1376 | int r, opt, i, j, on = 1, already_daemon; | 1441 | int r, opt, on = 1, already_daemon, remote_port; |
1377 | int sock_in = -1, sock_out = -1, newsock = -1; | 1442 | int sock_in = -1, sock_out = -1, newsock = -1; |
1378 | const char *remote_ip; | 1443 | const char *remote_ip, *rdomain; |
1379 | int remote_port; | ||
1380 | char *fp, *line, *laddr, *logfile = NULL; | 1444 | char *fp, *line, *laddr, *logfile = NULL; |
1381 | int config_s[2] = { -1 , -1 }; | 1445 | int config_s[2] = { -1 , -1 }; |
1382 | u_int n; | 1446 | u_int i, j; |
1383 | u_int64_t ibytes, obytes; | 1447 | u_int64_t ibytes, obytes; |
1384 | mode_t new_umask; | 1448 | mode_t new_umask; |
1385 | struct sshkey *key; | 1449 | struct sshkey *key; |
1386 | struct sshkey *pubkey; | 1450 | struct sshkey *pubkey; |
1387 | int keytype; | 1451 | int keytype; |
1388 | Authctxt *authctxt; | 1452 | Authctxt *authctxt; |
1389 | struct connection_info *connection_info = get_connection_info(0, 0); | 1453 | struct connection_info *connection_info = NULL; |
1390 | 1454 | ||
1391 | ssh_malloc_init(); /* must be called before any mallocs */ | 1455 | ssh_malloc_init(); /* must be called before any mallocs */ |
1392 | 1456 | ||
@@ -1399,7 +1463,7 @@ main(int ac, char **av) | |||
1399 | saved_argc = ac; | 1463 | saved_argc = ac; |
1400 | rexec_argc = ac; | 1464 | rexec_argc = ac; |
1401 | saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); | 1465 | saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); |
1402 | for (i = 0; i < ac; i++) | 1466 | for (i = 0; (int)i < ac; i++) |
1403 | saved_argv[i] = xstrdup(av[i]); | 1467 | saved_argv[i] = xstrdup(av[i]); |
1404 | saved_argv[i] = NULL; | 1468 | saved_argv[i] = NULL; |
1405 | 1469 | ||
@@ -1432,12 +1496,8 @@ main(int ac, char **av) | |||
1432 | config_file_name = optarg; | 1496 | config_file_name = optarg; |
1433 | break; | 1497 | break; |
1434 | case 'c': | 1498 | case 'c': |
1435 | if (options.num_host_cert_files >= MAX_HOSTCERTS) { | 1499 | servconf_add_hostcert("[command-line]", 0, |
1436 | fprintf(stderr, "too many host certificates.\n"); | 1500 | &options, optarg); |
1437 | exit(1); | ||
1438 | } | ||
1439 | options.host_cert_files[options.num_host_cert_files++] = | ||
1440 | derelativise_path(optarg); | ||
1441 | break; | 1501 | break; |
1442 | case 'd': | 1502 | case 'd': |
1443 | if (debug_flag == 0) { | 1503 | if (debug_flag == 0) { |
@@ -1496,12 +1556,8 @@ main(int ac, char **av) | |||
1496 | /* protocol 1, ignored */ | 1556 | /* protocol 1, ignored */ |
1497 | break; | 1557 | break; |
1498 | case 'h': | 1558 | case 'h': |
1499 | if (options.num_host_key_files >= MAX_HOSTKEYS) { | 1559 | servconf_add_hostkey("[command-line]", 0, |
1500 | fprintf(stderr, "too many host keys.\n"); | 1560 | &options, optarg); |
1501 | exit(1); | ||
1502 | } | ||
1503 | options.host_key_files[options.num_host_key_files++] = | ||
1504 | derelativise_path(optarg); | ||
1505 | break; | 1561 | break; |
1506 | case 't': | 1562 | case 't': |
1507 | test_flag = 1; | 1563 | test_flag = 1; |
@@ -1510,6 +1566,7 @@ main(int ac, char **av) | |||
1510 | test_flag = 2; | 1566 | test_flag = 2; |
1511 | break; | 1567 | break; |
1512 | case 'C': | 1568 | case 'C': |
1569 | connection_info = get_connection_info(0, 0); | ||
1513 | if (parse_server_match_testspec(connection_info, | 1570 | if (parse_server_match_testspec(connection_info, |
1514 | optarg) == -1) | 1571 | optarg) == -1) |
1515 | exit(1); | 1572 | exit(1); |
@@ -1568,24 +1625,13 @@ main(int ac, char **av) | |||
1568 | if (getenv("KRB5CCNAME") != NULL) | 1625 | if (getenv("KRB5CCNAME") != NULL) |
1569 | (void) unsetenv("KRB5CCNAME"); | 1626 | (void) unsetenv("KRB5CCNAME"); |
1570 | 1627 | ||
1571 | #ifdef _UNICOS | ||
1572 | /* Cray can define user privs drop all privs now! | ||
1573 | * Not needed on PRIV_SU systems! | ||
1574 | */ | ||
1575 | drop_cray_privs(); | ||
1576 | #endif | ||
1577 | |||
1578 | sensitive_data.have_ssh2_key = 0; | 1628 | sensitive_data.have_ssh2_key = 0; |
1579 | 1629 | ||
1580 | /* | 1630 | /* |
1581 | * If we're doing an extended config test, make sure we have all of | 1631 | * If we're not doing an extended test do not silently ignore connection |
1582 | * the parameters we need. If we're not doing an extended test, | 1632 | * test params. |
1583 | * do not silently ignore connection test params. | ||
1584 | */ | 1633 | */ |
1585 | if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0) | 1634 | if (test_flag < 2 && connection_info != NULL) |
1586 | fatal("user, host and addr are all required when testing " | ||
1587 | "Match configs"); | ||
1588 | if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0) | ||
1589 | fatal("Config test connection parameter (-C) provided without " | 1635 | fatal("Config test connection parameter (-C) provided without " |
1590 | "test mode (-T)"); | 1636 | "test mode (-T)"); |
1591 | 1637 | ||
@@ -1627,12 +1673,12 @@ main(int ac, char **av) | |||
1627 | * and warns for trivial misconfigurations that could break login. | 1673 | * and warns for trivial misconfigurations that could break login. |
1628 | */ | 1674 | */ |
1629 | if (options.num_auth_methods != 0) { | 1675 | if (options.num_auth_methods != 0) { |
1630 | for (n = 0; n < options.num_auth_methods; n++) { | 1676 | for (i = 0; i < options.num_auth_methods; i++) { |
1631 | if (auth2_methods_valid(options.auth_methods[n], | 1677 | if (auth2_methods_valid(options.auth_methods[i], |
1632 | 1) == 0) | 1678 | 1) == 0) |
1633 | break; | 1679 | break; |
1634 | } | 1680 | } |
1635 | if (n >= options.num_auth_methods) | 1681 | if (i >= options.num_auth_methods) |
1636 | fatal("AuthenticationMethods cannot be satisfied by " | 1682 | fatal("AuthenticationMethods cannot be satisfied by " |
1637 | "enabled authentication methods"); | 1683 | "enabled authentication methods"); |
1638 | } | 1684 | } |
@@ -1658,10 +1704,8 @@ main(int ac, char **av) | |||
1658 | fatal("Privilege separation user %s does not exist", | 1704 | fatal("Privilege separation user %s does not exist", |
1659 | SSH_PRIVSEP_USER); | 1705 | SSH_PRIVSEP_USER); |
1660 | } else { | 1706 | } else { |
1661 | explicit_bzero(privsep_pw->pw_passwd, | ||
1662 | strlen(privsep_pw->pw_passwd)); | ||
1663 | privsep_pw = pwcopy(privsep_pw); | 1707 | privsep_pw = pwcopy(privsep_pw); |
1664 | free(privsep_pw->pw_passwd); | 1708 | freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd)); |
1665 | privsep_pw->pw_passwd = xstrdup("*"); | 1709 | privsep_pw->pw_passwd = xstrdup("*"); |
1666 | } | 1710 | } |
1667 | endpwent(); | 1711 | endpwent(); |
@@ -1713,6 +1757,7 @@ main(int ac, char **av) | |||
1713 | case KEY_DSA: | 1757 | case KEY_DSA: |
1714 | case KEY_ECDSA: | 1758 | case KEY_ECDSA: |
1715 | case KEY_ED25519: | 1759 | case KEY_ED25519: |
1760 | case KEY_XMSS: | ||
1716 | if (have_agent || key != NULL) | 1761 | if (have_agent || key != NULL) |
1717 | sensitive_data.have_ssh2_key = 1; | 1762 | sensitive_data.have_ssh2_key = 1; |
1718 | break; | 1763 | break; |
@@ -1771,7 +1816,7 @@ main(int ac, char **av) | |||
1771 | continue; | 1816 | continue; |
1772 | } | 1817 | } |
1773 | sensitive_data.host_certificates[j] = key; | 1818 | sensitive_data.host_certificates[j] = key; |
1774 | debug("host certificate: #%d type %d %s", j, key->type, | 1819 | debug("host certificate: #%u type %d %s", j, key->type, |
1775 | key_type(key)); | 1820 | key_type(key)); |
1776 | } | 1821 | } |
1777 | 1822 | ||
@@ -1795,8 +1840,13 @@ main(int ac, char **av) | |||
1795 | } | 1840 | } |
1796 | 1841 | ||
1797 | if (test_flag > 1) { | 1842 | if (test_flag > 1) { |
1798 | if (server_match_spec_complete(connection_info) == 1) | 1843 | /* |
1799 | parse_server_match_config(&options, connection_info); | 1844 | * If no connection info was provided by -C then use |
1845 | * use a blank one that will cause no predicate to match. | ||
1846 | */ | ||
1847 | if (connection_info == NULL) | ||
1848 | connection_info = get_connection_info(0, 0); | ||
1849 | parse_server_match_config(&options, connection_info); | ||
1800 | dump_config(&options); | 1850 | dump_config(&options); |
1801 | } | 1851 | } |
1802 | 1852 | ||
@@ -1815,8 +1865,10 @@ main(int ac, char **av) | |||
1815 | debug("setgroups() failed: %.200s", strerror(errno)); | 1865 | debug("setgroups() failed: %.200s", strerror(errno)); |
1816 | 1866 | ||
1817 | if (rexec_flag) { | 1867 | if (rexec_flag) { |
1868 | if (rexec_argc < 0) | ||
1869 | fatal("rexec_argc %d < 0", rexec_argc); | ||
1818 | rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *)); | 1870 | rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *)); |
1819 | for (i = 0; i < rexec_argc; i++) { | 1871 | for (i = 0; i < (u_int)rexec_argc; i++) { |
1820 | debug("rexec_argv[%d]='%s'", i, saved_argv[i]); | 1872 | debug("rexec_argv[%d]='%s'", i, saved_argv[i]); |
1821 | rexec_argv[i] = saved_argv[i]; | 1873 | rexec_argv[i] = saved_argv[i]; |
1822 | } | 1874 | } |
@@ -1994,6 +2046,9 @@ main(int ac, char **av) | |||
1994 | cleanup_exit(255); | 2046 | cleanup_exit(255); |
1995 | } | 2047 | } |
1996 | 2048 | ||
2049 | if (options.routing_domain != NULL) | ||
2050 | set_process_rdomain(ssh, options.routing_domain); | ||
2051 | |||
1997 | /* | 2052 | /* |
1998 | * The rest of the code depends on the fact that | 2053 | * The rest of the code depends on the fact that |
1999 | * ssh_remote_ipaddr() caches the remote ip, even if | 2054 | * ssh_remote_ipaddr() caches the remote ip, even if |
@@ -2023,10 +2078,15 @@ main(int ac, char **av) | |||
2023 | } | 2078 | } |
2024 | #endif /* LIBWRAP */ | 2079 | #endif /* LIBWRAP */ |
2025 | 2080 | ||
2081 | rdomain = ssh_packet_rdomain_in(ssh); | ||
2082 | |||
2026 | /* Log the connection. */ | 2083 | /* Log the connection. */ |
2027 | laddr = get_local_ipaddr(sock_in); | 2084 | laddr = get_local_ipaddr(sock_in); |
2028 | verbose("Connection from %s port %d on %s port %d", | 2085 | verbose("Connection from %s port %d on %s port %d%s%s%s", |
2029 | remote_ip, remote_port, laddr, ssh_local_port(ssh)); | 2086 | remote_ip, remote_port, laddr, ssh_local_port(ssh), |
2087 | rdomain == NULL ? "" : " rdomain \"", | ||
2088 | rdomain == NULL ? "" : rdomain, | ||
2089 | rdomain == NULL ? "" : "\""); | ||
2030 | free(laddr); | 2090 | free(laddr); |
2031 | 2091 | ||
2032 | #ifdef USE_SECURITY_SESSION_API | 2092 | #ifdef USE_SECURITY_SESSION_API |
@@ -2106,6 +2166,10 @@ main(int ac, char **av) | |||
2106 | /* XXX global for cleanup, access from other modules */ | 2166 | /* XXX global for cleanup, access from other modules */ |
2107 | the_authctxt = authctxt; | 2167 | the_authctxt = authctxt; |
2108 | 2168 | ||
2169 | /* Set default key authentication options */ | ||
2170 | if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) | ||
2171 | fatal("allocation failed"); | ||
2172 | |||
2109 | /* prepare buffer to collect messages to display to user after login */ | 2173 | /* prepare buffer to collect messages to display to user after login */ |
2110 | buffer_init(&loginmsg); | 2174 | buffer_init(&loginmsg); |
2111 | auth_debug_reset(); | 2175 | auth_debug_reset(); |
@@ -2162,7 +2226,7 @@ main(int ac, char **av) | |||
2162 | #ifdef USE_PAM | 2226 | #ifdef USE_PAM |
2163 | if (options.use_pam) { | 2227 | if (options.use_pam) { |
2164 | do_pam_setcred(1); | 2228 | do_pam_setcred(1); |
2165 | do_pam_session(); | 2229 | do_pam_session(ssh); |
2166 | } | 2230 | } |
2167 | #endif | 2231 | #endif |
2168 | 2232 | ||