diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-08 15:30:59 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-08 15:30:59 +1100 |
commit | 356a0b004aad93ec570b134664522a3a925ba556 (patch) | |
tree | 3c7cddb50f71a838947d5fda204b569d879dc757 /sshd.c | |
parent | 0aa8e5395ca08c7fa927bccd8a763edc4ae61f7b (diff) |
Lots of changes:
- Removed lots of unnecessary checks from autoconf
- Added support and autoconf test for openpty() function (Unix98 pty support)
- Fix for scp not finding ssh if not installed as /usr/bin/ssh
- Added TODO file
- Merged parts of Debian patch From Phil Hands <phil@hands.com>:
- Added ssh-askpass program
- Added ssh-askpass support to ssh-add.c
- Create symlinks for slogin on install
- Fix "distclean" target in makefile
- Added example for ssh-agent to manpage
- Added support for PAM_TEXT_INFO messages
- Disable internal /etc/nologin support if PAM enabled
- Merged latest OpenBSD CVS changes:
- [sshd.c] don't send fail-msg but disconnect if too many authentication
failures
- [sshd.c] replace assert() with error, fatal or packet_disconnect
- [sshd.c] remove unused argument. ok dugsong
- [sshd.c] typo
- [rsa.c] clear buffers used for encryption. ok: niels
- [rsa.c] replace assert() with error, fatal or packet_disconnect
- Fixed coredump after merge of OpenBSD rsa.c patch
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 85 |
1 files changed, 64 insertions, 21 deletions
@@ -18,7 +18,7 @@ agent connections. | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "includes.h" | 20 | #include "includes.h" |
21 | RCSID("$Id: sshd.c,v 1.10 1999/11/02 08:05:02 damien Exp $"); | 21 | RCSID("$Id: sshd.c,v 1.11 1999/11/08 04:30:59 damien Exp $"); |
22 | 22 | ||
23 | #include "xmalloc.h" | 23 | #include "xmalloc.h" |
24 | #include "rsa.h" | 24 | #include "rsa.h" |
@@ -142,6 +142,7 @@ static struct pam_conv conv = { | |||
142 | }; | 142 | }; |
143 | struct pam_handle_t *pamh = NULL; | 143 | struct pam_handle_t *pamh = NULL; |
144 | const char *pampasswd = NULL; | 144 | const char *pampasswd = NULL; |
145 | char *pamconv_msg = NULL; | ||
145 | 146 | ||
146 | static int pamconv(int num_msg, const struct pam_message **msg, | 147 | static int pamconv(int num_msg, const struct pam_message **msg, |
147 | struct pam_response **resp, void *appdata_ptr) | 148 | struct pam_response **resp, void *appdata_ptr) |
@@ -171,6 +172,26 @@ static int pamconv(int num_msg, const struct pam_message **msg, | |||
171 | case PAM_TEXT_INFO: | 172 | case PAM_TEXT_INFO: |
172 | reply[count].resp_retcode = PAM_SUCCESS; | 173 | reply[count].resp_retcode = PAM_SUCCESS; |
173 | reply[count].resp = xstrdup(""); | 174 | reply[count].resp = xstrdup(""); |
175 | |||
176 | if (msg[count]->msg == NULL) break; | ||
177 | debug("Adding PAM message: %s", msg[count]->msg); | ||
178 | if (pamconv_msg == NULL) | ||
179 | { | ||
180 | pamconv_msg = malloc(strlen(msg[count]->msg) + 2); | ||
181 | |||
182 | if (pamconv_msg == NULL) | ||
183 | return PAM_CONV_ERR; | ||
184 | |||
185 | strncpy(pamconv_msg, msg[count]->msg, strlen(msg[count]->msg)); | ||
186 | pamconv_msg[strlen(msg[count]->msg)] = '\n'; | ||
187 | pamconv_msg[strlen(msg[count]->msg) + 1] = '\0'; | ||
188 | } else | ||
189 | { | ||
190 | pamconv_msg = realloc(pamconv_msg, strlen(pamconv_msg) + strlen(msg[count]->msg) + 2); | ||
191 | strncat(pamconv_msg, msg[count]->msg, strlen(msg[count]->msg)); | ||
192 | pamconv_msg[strlen(pamconv_msg)] = '\n'; | ||
193 | pamconv_msg[strlen(pamconv_msg) + 1] = '\0'; | ||
194 | } | ||
174 | break; | 195 | break; |
175 | 196 | ||
176 | case PAM_PROMPT_ECHO_ON: | 197 | case PAM_PROMPT_ECHO_ON: |
@@ -964,8 +985,14 @@ void do_connection(int privileged_port) | |||
964 | if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) | 985 | if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) |
965 | { | 986 | { |
966 | /* Private key has bigger modulus. */ | 987 | /* Private key has bigger modulus. */ |
967 | assert(BN_num_bits(sensitive_data.private_key->n) >= | 988 | if (BN_num_bits(sensitive_data.private_key->n) < |
968 | BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED); | 989 | BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) { |
990 | fatal("do_connection: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", | ||
991 | BN_num_bits(sensitive_data.private_key->n), | ||
992 | BN_num_bits(sensitive_data.host_key->n), | ||
993 | SSH_KEY_BITS_RESERVED); | ||
994 | } | ||
995 | |||
969 | rsa_private_decrypt(session_key_int, session_key_int, | 996 | rsa_private_decrypt(session_key_int, session_key_int, |
970 | sensitive_data.private_key); | 997 | sensitive_data.private_key); |
971 | rsa_private_decrypt(session_key_int, session_key_int, | 998 | rsa_private_decrypt(session_key_int, session_key_int, |
@@ -974,9 +1001,13 @@ void do_connection(int privileged_port) | |||
974 | else | 1001 | else |
975 | { | 1002 | { |
976 | /* Host key has bigger modulus (or they are equal). */ | 1003 | /* Host key has bigger modulus (or they are equal). */ |
977 | assert(BN_num_bits(sensitive_data.host_key->n) >= | 1004 | if (BN_num_bits(sensitive_data.host_key->n) < |
978 | BN_num_bits(sensitive_data.private_key->n) + | 1005 | BN_num_bits(sensitive_data.private_key->n) + SSH_KEY_BITS_RESERVED) { |
979 | SSH_KEY_BITS_RESERVED); | 1006 | fatal("do_connection: host_key %d < private_key %d + SSH_KEY_BITS_RESERVED %d", |
1007 | BN_num_bits(sensitive_data.host_key->n), | ||
1008 | BN_num_bits(sensitive_data.private_key->n), | ||
1009 | SSH_KEY_BITS_RESERVED); | ||
1010 | } | ||
980 | rsa_private_decrypt(session_key_int, session_key_int, | 1011 | rsa_private_decrypt(session_key_int, session_key_int, |
981 | sensitive_data.host_key); | 1012 | sensitive_data.host_key); |
982 | rsa_private_decrypt(session_key_int, session_key_int, | 1013 | rsa_private_decrypt(session_key_int, session_key_int, |
@@ -994,7 +1025,10 @@ void do_connection(int privileged_port) | |||
994 | least significant 256 bits of the integer; the first byte of the | 1025 | least significant 256 bits of the integer; the first byte of the |
995 | key is in the highest bits. */ | 1026 | key is in the highest bits. */ |
996 | BN_mask_bits(session_key_int, sizeof(session_key) * 8); | 1027 | BN_mask_bits(session_key_int, sizeof(session_key) * 8); |
997 | assert(BN_num_bytes(session_key_int) == sizeof(session_key)); | 1028 | if (BN_num_bytes(session_key_int) != sizeof(session_key)){ |
1029 | fatal("do_connection: session_key_int %d != sizeof(session_key) %d", | ||
1030 | BN_num_bytes(session_key_int), sizeof(session_key)); | ||
1031 | } | ||
998 | BN_bn2bin(session_key_int, session_key); | 1032 | BN_bn2bin(session_key_int, session_key); |
999 | 1033 | ||
1000 | /* Xor the first 16 bytes of the session key with the session id. */ | 1034 | /* Xor the first 16 bytes of the session key with the session id. */ |
@@ -1243,7 +1277,7 @@ do_authentication(char *user, int privileged_port) | |||
1243 | int dlen; | 1277 | int dlen; |
1244 | char *token_string = packet_get_string(&dlen); | 1278 | char *token_string = packet_get_string(&dlen); |
1245 | packet_integrity_check(plen, 4 + dlen, type); | 1279 | packet_integrity_check(plen, 4 + dlen, type); |
1246 | if (!auth_afs_token(user, pw->pw_uid, token_string)) | 1280 | if (!auth_afs_token(pw, token_string)) |
1247 | debug("AFS token REFUSED for %s", user); | 1281 | debug("AFS token REFUSED for %s", user); |
1248 | xfree(token_string); | 1282 | xfree(token_string); |
1249 | continue; | 1283 | continue; |
@@ -1478,15 +1512,15 @@ do_authentication(char *user, int privileged_port) | |||
1478 | if (authenticated) | 1512 | if (authenticated) |
1479 | break; | 1513 | break; |
1480 | 1514 | ||
1481 | /* Send a message indicating that the authentication attempt failed. */ | ||
1482 | packet_start(SSH_SMSG_FAILURE); | ||
1483 | packet_send(); | ||
1484 | packet_write_wait(); | ||
1485 | |||
1486 | if (++authentication_failures >= MAX_AUTH_FAILURES) { | 1515 | if (++authentication_failures >= MAX_AUTH_FAILURES) { |
1487 | packet_disconnect("Too many authentication failures for %.100s from %.200s", | 1516 | packet_disconnect("Too many authentication failures for %.100s from %.200s", |
1488 | pw->pw_name, get_canonical_hostname()); | 1517 | pw->pw_name, get_canonical_hostname()); |
1489 | } | 1518 | } |
1519 | |||
1520 | /* Send a message indicating that the authentication attempt failed. */ | ||
1521 | packet_start(SSH_SMSG_FAILURE); | ||
1522 | packet_send(); | ||
1523 | packet_write_wait(); | ||
1490 | } | 1524 | } |
1491 | 1525 | ||
1492 | /* Check if the user is logging in as root and root logins are disallowed. */ | 1526 | /* Check if the user is logging in as root and root logins are disallowed. */ |
@@ -1556,16 +1590,16 @@ void eat_packets_and_disconnect(const char *user) | |||
1556 | packet_send_debug(skeyinfo); | 1590 | packet_send_debug(skeyinfo); |
1557 | } | 1591 | } |
1558 | #endif /* SKEY */ | 1592 | #endif /* SKEY */ |
1559 | /* Send failure. This should be indistinguishable from a failed | ||
1560 | authentication. */ | ||
1561 | packet_start(SSH_SMSG_FAILURE); | ||
1562 | packet_send(); | ||
1563 | packet_write_wait(); | ||
1564 | if (++authentication_failures >= MAX_AUTH_FAILURES) | 1593 | if (++authentication_failures >= MAX_AUTH_FAILURES) |
1565 | { | 1594 | { |
1566 | packet_disconnect("Too many authentication failures for %.100s from %.200s", | 1595 | packet_disconnect("Too many authentication failures for %.100s from %.200s", |
1567 | user, get_canonical_hostname()); | 1596 | user, get_canonical_hostname()); |
1568 | } | 1597 | } |
1598 | /* Send failure. This should be indistinguishable from a failed | ||
1599 | authentication. */ | ||
1600 | packet_start(SSH_SMSG_FAILURE); | ||
1601 | packet_send(); | ||
1602 | packet_write_wait(); | ||
1569 | } | 1603 | } |
1570 | /*NOTREACHED*/ | 1604 | /*NOTREACHED*/ |
1571 | abort(); | 1605 | abort(); |
@@ -2049,7 +2083,13 @@ void do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
2049 | /* Check if .hushlogin exists. */ | 2083 | /* Check if .hushlogin exists. */ |
2050 | snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); | 2084 | snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); |
2051 | quiet_login = stat(line, &st) >= 0; | 2085 | quiet_login = stat(line, &st) >= 0; |
2052 | 2086 | ||
2087 | #ifdef HAVE_LIBPAM | ||
2088 | /* output the results of the pamconv() */ | ||
2089 | if (!quiet_login && pamconv_msg != NULL) | ||
2090 | fprintf(stderr, pamconv_msg); | ||
2091 | #endif | ||
2092 | |||
2053 | /* If the user has logged in before, display the time of last login. | 2093 | /* If the user has logged in before, display the time of last login. |
2054 | However, don't display anything extra if a command has been | 2094 | However, don't display anything extra if a command has been |
2055 | specified (so that ssh can be used to execute commands on a remote | 2095 | specified (so that ssh can be used to execute commands on a remote |
@@ -2238,6 +2278,7 @@ void do_child(const char *command, struct passwd *pw, const char *term, | |||
2238 | struct stat st; | 2278 | struct stat st; |
2239 | char *argv[10]; | 2279 | char *argv[10]; |
2240 | 2280 | ||
2281 | #ifndef HAVE_LIBPAM /* pam_nologin handles this */ | ||
2241 | /* Check /etc/nologin. */ | 2282 | /* Check /etc/nologin. */ |
2242 | f = fopen("/etc/nologin", "r"); | 2283 | f = fopen("/etc/nologin", "r"); |
2243 | if (f) | 2284 | if (f) |
@@ -2248,6 +2289,7 @@ void do_child(const char *command, struct passwd *pw, const char *term, | |||
2248 | if (pw->pw_uid != 0) | 2289 | if (pw->pw_uid != 0) |
2249 | exit(254); | 2290 | exit(254); |
2250 | } | 2291 | } |
2292 | #endif | ||
2251 | 2293 | ||
2252 | /* Set uid, gid, and groups. */ | 2294 | /* Set uid, gid, and groups. */ |
2253 | /* Login(1) does this as well, and it needs uid 0 for the "-h" switch, | 2295 | /* Login(1) does this as well, and it needs uid 0 for the "-h" switch, |
@@ -2387,7 +2429,7 @@ void do_child(const char *command, struct passwd *pw, const char *term, | |||
2387 | if (auth_get_socket_name() != NULL) | 2429 | if (auth_get_socket_name() != NULL) |
2388 | child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, | 2430 | child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, |
2389 | auth_get_socket_name()); | 2431 | auth_get_socket_name()); |
2390 | 2432 | ||
2391 | /* Read $HOME/.ssh/environment. */ | 2433 | /* Read $HOME/.ssh/environment. */ |
2392 | if(!options.use_login) { | 2434 | if(!options.use_login) { |
2393 | snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir); | 2435 | snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir); |
@@ -2525,6 +2567,7 @@ void do_child(const char *command, struct passwd *pw, const char *term, | |||
2525 | } | 2567 | } |
2526 | } | 2568 | } |
2527 | } | 2569 | } |
2570 | |||
2528 | /* Start the shell. Set initial character to '-'. */ | 2571 | /* Start the shell. Set initial character to '-'. */ |
2529 | buf[0] = '-'; | 2572 | buf[0] = '-'; |
2530 | strncpy(buf + 1, cp, sizeof(buf) - 1); | 2573 | strncpy(buf + 1, cp, sizeof(buf) - 1); |
@@ -2540,7 +2583,7 @@ void do_child(const char *command, struct passwd *pw, const char *term, | |||
2540 | } else { | 2583 | } else { |
2541 | /* Launch login(1). */ | 2584 | /* Launch login(1). */ |
2542 | 2585 | ||
2543 | execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(), "-p", "-f", "--", pw->pw_name, NULL); | 2586 | execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(), "-p", "-f", "--", pw->pw_name, NULL); |
2544 | 2587 | ||
2545 | /* Login couldn't be executed, die. */ | 2588 | /* Login couldn't be executed, die. */ |
2546 | 2589 | ||