diff options
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 185 |
1 files changed, 110 insertions, 75 deletions
diff --git a/sshconnect.c b/sshconnect.c index 0b1c0901f..593eade03 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "includes.h" | 10 | #include "includes.h" |
11 | RCSID("$Id: sshconnect.c,v 1.15 1999/11/25 00:54:59 damien Exp $"); | 11 | RCSID("$Id: sshconnect.c,v 1.16 1999/12/06 00:47:29 damien Exp $"); |
12 | 12 | ||
13 | #ifdef HAVE_OPENSSL | 13 | #ifdef HAVE_OPENSSL |
14 | #include <openssl/bn.h> | 14 | #include <openssl/bn.h> |
@@ -34,11 +34,13 @@ RCSID("$Id: sshconnect.c,v 1.15 1999/11/25 00:54:59 damien Exp $"); | |||
34 | /* Session id for the current session. */ | 34 | /* Session id for the current session. */ |
35 | unsigned char session_id[16]; | 35 | unsigned char session_id[16]; |
36 | 36 | ||
37 | extern Options options; | ||
38 | |||
37 | /* | 39 | /* |
38 | * Connect to the given ssh server using a proxy command. | 40 | * Connect to the given ssh server using a proxy command. |
39 | */ | 41 | */ |
40 | int | 42 | int |
41 | ssh_proxy_connect(const char *host, int port, uid_t original_real_uid, | 43 | ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid, |
42 | const char *proxy_command) | 44 | const char *proxy_command) |
43 | { | 45 | { |
44 | Buffer command; | 46 | Buffer command; |
@@ -49,7 +51,7 @@ ssh_proxy_connect(const char *host, int port, uid_t original_real_uid, | |||
49 | char portstring[100]; | 51 | char portstring[100]; |
50 | 52 | ||
51 | /* Convert the port number into a string. */ | 53 | /* Convert the port number into a string. */ |
52 | snprintf(portstring, sizeof portstring, "%d", port); | 54 | snprintf(portstring, sizeof portstring, "%hu", port); |
53 | 55 | ||
54 | /* Build the final command string in the buffer by making the | 56 | /* Build the final command string in the buffer by making the |
55 | appropriate substitutions to the given proxy command. */ | 57 | appropriate substitutions to the given proxy command. */ |
@@ -177,7 +179,7 @@ ssh_create_socket(uid_t original_real_uid, int privileged) | |||
177 | */ | 179 | */ |
178 | int | 180 | int |
179 | ssh_connect(const char *host, struct sockaddr_in * hostaddr, | 181 | ssh_connect(const char *host, struct sockaddr_in * hostaddr, |
180 | int port, int connection_attempts, | 182 | u_short port, int connection_attempts, |
181 | int anonymous, uid_t original_real_uid, | 183 | int anonymous, uid_t original_real_uid, |
182 | const char *proxy_command) | 184 | const char *proxy_command) |
183 | { | 185 | { |
@@ -476,9 +478,8 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) | |||
476 | * the user using it. | 478 | * the user using it. |
477 | */ | 479 | */ |
478 | int | 480 | int |
479 | try_rsa_authentication(struct passwd * pw, const char *authfile) | 481 | try_rsa_authentication(const char *authfile) |
480 | { | 482 | { |
481 | extern Options options; | ||
482 | BIGNUM *challenge; | 483 | BIGNUM *challenge; |
483 | RSA *private_key; | 484 | RSA *private_key; |
484 | RSA *public_key; | 485 | RSA *public_key; |
@@ -490,7 +491,8 @@ try_rsa_authentication(struct passwd * pw, const char *authfile) | |||
490 | public_key = RSA_new(); | 491 | public_key = RSA_new(); |
491 | if (!load_public_key(authfile, public_key, &comment)) { | 492 | if (!load_public_key(authfile, public_key, &comment)) { |
492 | RSA_free(public_key); | 493 | RSA_free(public_key); |
493 | return 0; /* Could not load it. Fail. */ | 494 | /* Could not load it. Fail. */ |
495 | return 0; | ||
494 | } | 496 | } |
495 | debug("Trying RSA authentication with key '%.100s'", comment); | 497 | debug("Trying RSA authentication with key '%.100s'", comment); |
496 | 498 | ||
@@ -513,8 +515,7 @@ try_rsa_authentication(struct passwd * pw, const char *authfile) | |||
513 | if (type == SSH_SMSG_FAILURE) { | 515 | if (type == SSH_SMSG_FAILURE) { |
514 | debug("Server refused our key."); | 516 | debug("Server refused our key."); |
515 | xfree(comment); | 517 | xfree(comment); |
516 | return 0; /* Server refuses to authenticate with | 518 | return 0; |
517 | this key. */ | ||
518 | } | 519 | } |
519 | /* Otherwise, the server should respond with a challenge. */ | 520 | /* Otherwise, the server should respond with a challenge. */ |
520 | if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) | 521 | if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) |
@@ -885,6 +886,93 @@ send_afs_tokens(void) | |||
885 | #endif /* AFS */ | 886 | #endif /* AFS */ |
886 | 887 | ||
887 | /* | 888 | /* |
889 | * Tries to authenticate with any string-based challenge/response system. | ||
890 | * Note that the client code is not tied to s/key or TIS. | ||
891 | */ | ||
892 | int | ||
893 | try_skey_authentication() | ||
894 | { | ||
895 | int type, i, payload_len; | ||
896 | char *challenge, *response; | ||
897 | |||
898 | debug("Doing skey authentication."); | ||
899 | |||
900 | /* request a challenge */ | ||
901 | packet_start(SSH_CMSG_AUTH_TIS); | ||
902 | packet_send(); | ||
903 | packet_write_wait(); | ||
904 | |||
905 | type = packet_read(&payload_len); | ||
906 | if (type != SSH_SMSG_FAILURE && | ||
907 | type != SSH_SMSG_AUTH_TIS_CHALLENGE) { | ||
908 | packet_disconnect("Protocol error: got %d in response " | ||
909 | "to skey-auth", type); | ||
910 | } | ||
911 | if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { | ||
912 | debug("No challenge for skey authentication."); | ||
913 | return 0; | ||
914 | } | ||
915 | challenge = packet_get_string(&payload_len); | ||
916 | if (options.cipher == SSH_CIPHER_NONE) | ||
917 | log("WARNING: Encryption is disabled! " | ||
918 | "Reponse will be transmitted in clear text."); | ||
919 | fprintf(stderr, "%s\n", challenge); | ||
920 | fflush(stderr); | ||
921 | for (i = 0; i < options.number_of_password_prompts; i++) { | ||
922 | if (i != 0) | ||
923 | error("Permission denied, please try again."); | ||
924 | response = read_passphrase("Response: ", 0); | ||
925 | packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); | ||
926 | packet_put_string(response, strlen(response)); | ||
927 | memset(response, 0, strlen(response)); | ||
928 | xfree(response); | ||
929 | packet_send(); | ||
930 | packet_write_wait(); | ||
931 | type = packet_read(&payload_len); | ||
932 | if (type == SSH_SMSG_SUCCESS) | ||
933 | return 1; | ||
934 | if (type != SSH_SMSG_FAILURE) | ||
935 | packet_disconnect("Protocol error: got %d in response " | ||
936 | "to skey-auth-reponse", type); | ||
937 | } | ||
938 | /* failure */ | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | /* | ||
943 | * Tries to authenticate with plain passwd authentication. | ||
944 | */ | ||
945 | int | ||
946 | try_password_authentication(char *prompt) | ||
947 | { | ||
948 | int type, i, payload_len; | ||
949 | char *password; | ||
950 | |||
951 | debug("Doing password authentication."); | ||
952 | if (options.cipher == SSH_CIPHER_NONE) | ||
953 | log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); | ||
954 | for (i = 0; i < options.number_of_password_prompts; i++) { | ||
955 | if (i != 0) | ||
956 | error("Permission denied, please try again."); | ||
957 | password = read_passphrase(prompt, 0); | ||
958 | packet_start(SSH_CMSG_AUTH_PASSWORD); | ||
959 | packet_put_string(password, strlen(password)); | ||
960 | memset(password, 0, strlen(password)); | ||
961 | xfree(password); | ||
962 | packet_send(); | ||
963 | packet_write_wait(); | ||
964 | |||
965 | type = packet_read(&payload_len); | ||
966 | if (type == SSH_SMSG_SUCCESS) | ||
967 | return 1; | ||
968 | if (type != SSH_SMSG_FAILURE) | ||
969 | packet_disconnect("Protocol error: got %d in response to passwd auth", type); | ||
970 | } | ||
971 | /* failure */ | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | /* | ||
888 | * Waits for the server identification string, and sends our own | 976 | * Waits for the server identification string, and sends our own |
889 | * identification string. | 977 | * identification string. |
890 | */ | 978 | */ |
@@ -895,7 +983,6 @@ ssh_exchange_identification() | |||
895 | int remote_major, remote_minor, i; | 983 | int remote_major, remote_minor, i; |
896 | int connection_in = packet_get_connection_in(); | 984 | int connection_in = packet_get_connection_in(); |
897 | int connection_out = packet_get_connection_out(); | 985 | int connection_out = packet_get_connection_out(); |
898 | extern Options options; | ||
899 | 986 | ||
900 | /* Read other side\'s version identification. */ | 987 | /* Read other side\'s version identification. */ |
901 | for (i = 0; i < sizeof(buf) - 1; i++) { | 988 | for (i = 0; i < sizeof(buf) - 1; i++) { |
@@ -1015,9 +1102,7 @@ ssh_login(int host_key_valid, | |||
1015 | struct sockaddr_in *hostaddr, | 1102 | struct sockaddr_in *hostaddr, |
1016 | uid_t original_real_uid) | 1103 | uid_t original_real_uid) |
1017 | { | 1104 | { |
1018 | extern Options options; | ||
1019 | int i, type; | 1105 | int i, type; |
1020 | char *password; | ||
1021 | struct passwd *pw; | 1106 | struct passwd *pw; |
1022 | BIGNUM *key; | 1107 | BIGNUM *key; |
1023 | RSA *host_key, *file_key; | 1108 | RSA *host_key, *file_key; |
@@ -1036,6 +1121,13 @@ ssh_login(int host_key_valid, | |||
1036 | int payload_len, clen, sum_len = 0; | 1121 | int payload_len, clen, sum_len = 0; |
1037 | u_int32_t rand = 0; | 1122 | u_int32_t rand = 0; |
1038 | 1123 | ||
1124 | /* | ||
1125 | * Turn off check_host_ip for proxy connects, since | ||
1126 | * we don't have the remote ip-address | ||
1127 | */ | ||
1128 | if (options.proxy_command != NULL && options.check_host_ip) | ||
1129 | options.check_host_ip = 0; | ||
1130 | |||
1039 | if (options.check_host_ip) | 1131 | if (options.check_host_ip) |
1040 | ip = xstrdup(inet_ntoa(hostaddr->sin_addr)); | 1132 | ip = xstrdup(inet_ntoa(hostaddr->sin_addr)); |
1041 | 1133 | ||
@@ -1494,80 +1586,23 @@ ssh_login(int host_key_valid, | |||
1494 | 1586 | ||
1495 | /* Try RSA authentication for each identity. */ | 1587 | /* Try RSA authentication for each identity. */ |
1496 | for (i = 0; i < options.num_identity_files; i++) | 1588 | for (i = 0; i < options.num_identity_files; i++) |
1497 | if (try_rsa_authentication(pw, options.identity_files[i])) | 1589 | if (try_rsa_authentication(options.identity_files[i])) |
1498 | return; | 1590 | return; |
1499 | } | 1591 | } |
1500 | /* Try skey authentication if the server supports it. */ | 1592 | /* Try skey authentication if the server supports it. */ |
1501 | if ((supported_authentications & (1 << SSH_AUTH_TIS)) && | 1593 | if ((supported_authentications & (1 << SSH_AUTH_TIS)) && |
1502 | options.skey_authentication && !options.batch_mode) { | 1594 | options.skey_authentication && !options.batch_mode) { |
1503 | debug("Doing skey authentication."); | 1595 | if (try_skey_authentication()) |
1504 | 1596 | return; | |
1505 | /* request a challenge */ | ||
1506 | packet_start(SSH_CMSG_AUTH_TIS); | ||
1507 | packet_send(); | ||
1508 | packet_write_wait(); | ||
1509 | |||
1510 | type = packet_read(&payload_len); | ||
1511 | if (type != SSH_SMSG_FAILURE && | ||
1512 | type != SSH_SMSG_AUTH_TIS_CHALLENGE) { | ||
1513 | packet_disconnect("Protocol error: got %d in response " | ||
1514 | "to skey auth", type); | ||
1515 | } | ||
1516 | if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { | ||
1517 | debug("No challenge for skey authentication."); | ||
1518 | } else { | ||
1519 | char *challenge, *response; | ||
1520 | challenge = packet_get_string(&payload_len); | ||
1521 | if (options.cipher == SSH_CIPHER_NONE) | ||
1522 | log("WARNING: Encryption is disabled! " | ||
1523 | "Reponse will be transmitted in clear text."); | ||
1524 | fprintf(stderr, "%s\n", challenge); | ||
1525 | fflush(stderr); | ||
1526 | for (i = 0; i < options.number_of_password_prompts; i++) { | ||
1527 | if (i != 0) | ||
1528 | error("Permission denied, please try again."); | ||
1529 | response = read_passphrase("Response: ", 0); | ||
1530 | packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); | ||
1531 | packet_put_string(response, strlen(response)); | ||
1532 | memset(response, 0, strlen(response)); | ||
1533 | xfree(response); | ||
1534 | packet_send(); | ||
1535 | packet_write_wait(); | ||
1536 | type = packet_read(&payload_len); | ||
1537 | if (type == SSH_SMSG_SUCCESS) | ||
1538 | return; | ||
1539 | if (type != SSH_SMSG_FAILURE) | ||
1540 | packet_disconnect("Protocol error: got %d in response " | ||
1541 | "to skey auth", type); | ||
1542 | } | ||
1543 | } | ||
1544 | } | 1597 | } |
1545 | /* Try password authentication if the server supports it. */ | 1598 | /* Try password authentication if the server supports it. */ |
1546 | if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && | 1599 | if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && |
1547 | options.password_authentication && !options.batch_mode) { | 1600 | options.password_authentication && !options.batch_mode) { |
1548 | char prompt[80]; | 1601 | char prompt[80]; |
1549 | snprintf(prompt, sizeof(prompt), "%.30s@%.30s's password: ", | 1602 | snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ", |
1550 | server_user, host); | 1603 | server_user, host); |
1551 | debug("Doing password authentication."); | 1604 | if (try_password_authentication(prompt)) |
1552 | if (options.cipher == SSH_CIPHER_NONE) | 1605 | return; |
1553 | log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); | ||
1554 | for (i = 0; i < options.number_of_password_prompts; i++) { | ||
1555 | if (i != 0) | ||
1556 | error("Permission denied, please try again."); | ||
1557 | password = read_passphrase(prompt, 0); | ||
1558 | packet_start(SSH_CMSG_AUTH_PASSWORD); | ||
1559 | packet_put_string(password, strlen(password)); | ||
1560 | memset(password, 0, strlen(password)); | ||
1561 | xfree(password); | ||
1562 | packet_send(); | ||
1563 | packet_write_wait(); | ||
1564 | |||
1565 | type = packet_read(&payload_len); | ||
1566 | if (type == SSH_SMSG_SUCCESS) | ||
1567 | return; | ||
1568 | if (type != SSH_SMSG_FAILURE) | ||
1569 | packet_disconnect("Protocol error: got %d in response to passwd auth", type); | ||
1570 | } | ||
1571 | } | 1606 | } |
1572 | /* All authentication methods have failed. Exit with an error message. */ | 1607 | /* All authentication methods have failed. Exit with an error message. */ |
1573 | fatal("Permission denied."); | 1608 | fatal("Permission denied."); |