diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 671 |
1 files changed, 307 insertions, 364 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.17 1999/11/12 04:19:27 damien Exp $"); | 21 | RCSID("$Id: sshd.c,v 1.18 1999/11/15 04:25:10 damien Exp $"); |
22 | 22 | ||
23 | #include "xmalloc.h" | 23 | #include "xmalloc.h" |
24 | #include "rsa.h" | 24 | #include "rsa.h" |
@@ -114,9 +114,10 @@ int received_sighup = 0; | |||
114 | RSA *public_key; | 114 | RSA *public_key; |
115 | 115 | ||
116 | /* Prototypes for various functions defined later in this file. */ | 116 | /* Prototypes for various functions defined later in this file. */ |
117 | void do_connection(int privileged_port); | 117 | void do_connection(); |
118 | void do_authentication(char *user, int privileged_port); | 118 | void do_authentication(char *user); |
119 | void eat_packets_and_disconnect(const char *user); | 119 | void do_authloop(struct passwd *pw); |
120 | void do_fake_authloop(char *user); | ||
120 | void do_authenticated(struct passwd *pw); | 121 | void do_authenticated(struct passwd *pw); |
121 | void do_exec_pty(const char *command, int ptyfd, int ttyfd, | 122 | void do_exec_pty(const char *command, int ptyfd, int ttyfd, |
122 | const char *ttyname, struct passwd *pw, const char *term, | 123 | const char *ttyname, struct passwd *pw, const char *term, |
@@ -128,11 +129,12 @@ void do_exec_no_pty(const char *command, struct passwd *pw, | |||
128 | void do_child(const char *command, struct passwd *pw, const char *term, | 129 | void do_child(const char *command, struct passwd *pw, const char *term, |
129 | const char *display, const char *auth_proto, | 130 | const char *display, const char *auth_proto, |
130 | const char *auth_data, const char *ttyname); | 131 | const char *auth_data, const char *ttyname); |
132 | |||
131 | #ifdef HAVE_LIBPAM | 133 | #ifdef HAVE_LIBPAM |
132 | static int pamconv(int num_msg, const struct pam_message **msg, | 134 | static int pamconv(int num_msg, const struct pam_message **msg, |
133 | struct pam_response **resp, void *appdata_ptr); | 135 | struct pam_response **resp, void *appdata_ptr); |
134 | void do_pam_account_and_session(const char *username, const char *password, | 136 | void do_pam_account_and_session(const char *username, |
135 | const char *remote_user, const char *remote_host); | 137 | const char *remote_user, const char *remote_host); |
136 | void pam_cleanup_proc(void *context); | 138 | void pam_cleanup_proc(void *context); |
137 | 139 | ||
138 | static struct pam_conv conv = { | 140 | static struct pam_conv conv = { |
@@ -228,7 +230,7 @@ void pam_cleanup_proc(void *context) | |||
228 | } | 230 | } |
229 | } | 231 | } |
230 | 232 | ||
231 | void do_pam_account_and_session(const char *username, const char *password, const char *remote_user, const char *remote_host) | 233 | void do_pam_account_and_session(const char *username, const char *remote_user, const char *remote_host) |
232 | { | 234 | { |
233 | int pam_retval; | 235 | int pam_retval; |
234 | 236 | ||
@@ -239,7 +241,7 @@ void do_pam_account_and_session(const char *username, const char *password, cons | |||
239 | if (pam_retval != PAM_SUCCESS) | 241 | if (pam_retval != PAM_SUCCESS) |
240 | { | 242 | { |
241 | log("PAM set rhost failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); | 243 | log("PAM set rhost failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); |
242 | eat_packets_and_disconnect(username); | 244 | do_fake_authloop(username); |
243 | } | 245 | } |
244 | } | 246 | } |
245 | 247 | ||
@@ -250,7 +252,7 @@ void do_pam_account_and_session(const char *username, const char *password, cons | |||
250 | if (pam_retval != PAM_SUCCESS) | 252 | if (pam_retval != PAM_SUCCESS) |
251 | { | 253 | { |
252 | log("PAM set ruser failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); | 254 | log("PAM set ruser failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); |
253 | eat_packets_and_disconnect(username); | 255 | do_fake_authloop(username); |
254 | } | 256 | } |
255 | } | 257 | } |
256 | 258 | ||
@@ -258,14 +260,14 @@ void do_pam_account_and_session(const char *username, const char *password, cons | |||
258 | if (pam_retval != PAM_SUCCESS) | 260 | if (pam_retval != PAM_SUCCESS) |
259 | { | 261 | { |
260 | log("PAM rejected by account configuration: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); | 262 | log("PAM rejected by account configuration: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); |
261 | eat_packets_and_disconnect(username); | 263 | do_fake_authloop(username); |
262 | } | 264 | } |
263 | 265 | ||
264 | pam_retval = pam_open_session((pam_handle_t *)pamh, 0); | 266 | pam_retval = pam_open_session((pam_handle_t *)pamh, 0); |
265 | if (pam_retval != PAM_SUCCESS) | 267 | if (pam_retval != PAM_SUCCESS) |
266 | { | 268 | { |
267 | log("PAM session setup failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); | 269 | log("PAM session setup failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); |
268 | eat_packets_and_disconnect(username); | 270 | do_fake_authloop(username); |
269 | } | 271 | } |
270 | } | 272 | } |
271 | #endif /* HAVE_LIBPAM */ | 273 | #endif /* HAVE_LIBPAM */ |
@@ -375,6 +377,7 @@ main(int ac, char **av) | |||
375 | struct sockaddr_in sin; | 377 | struct sockaddr_in sin; |
376 | char buf[100]; /* Must not be larger than remote_version. */ | 378 | char buf[100]; /* Must not be larger than remote_version. */ |
377 | char remote_version[100]; /* Must be at least as big as buf. */ | 379 | char remote_version[100]; /* Must be at least as big as buf. */ |
380 | int remote_port; | ||
378 | char *comment; | 381 | char *comment; |
379 | FILE *f; | 382 | FILE *f; |
380 | struct linger linger; | 383 | struct linger linger; |
@@ -742,6 +745,8 @@ main(int ac, char **av) | |||
742 | have a key. */ | 745 | have a key. */ |
743 | packet_set_connection(sock_in, sock_out); | 746 | packet_set_connection(sock_in, sock_out); |
744 | 747 | ||
748 | remote_port = get_remote_port(); | ||
749 | |||
745 | /* Check whether logins are denied from this host. */ | 750 | /* Check whether logins are denied from this host. */ |
746 | #ifdef LIBWRAP | 751 | #ifdef LIBWRAP |
747 | { | 752 | { |
@@ -755,13 +760,11 @@ main(int ac, char **av) | |||
755 | close(sock_out); | 760 | close(sock_out); |
756 | refuse(&req); | 761 | refuse(&req); |
757 | } | 762 | } |
758 | log("Connection from %.500s port %d", | 763 | log("Connection from %.500s port %d", eval_client(&req), remote_port); |
759 | eval_client(&req), get_remote_port()); | ||
760 | } | 764 | } |
761 | #else | 765 | #else |
762 | /* Log the connection. */ | 766 | /* Log the connection. */ |
763 | log("Connection from %.100s port %d", | 767 | log("Connection from %.100s port %d", get_remote_ipaddr(), remote_port); |
764 | get_remote_ipaddr(), get_remote_port()); | ||
765 | #endif /* LIBWRAP */ | 768 | #endif /* LIBWRAP */ |
766 | 769 | ||
767 | /* We don\'t want to listen forever unless the other side successfully | 770 | /* We don\'t want to listen forever unless the other side successfully |
@@ -834,11 +837,23 @@ main(int ac, char **av) | |||
834 | } | 837 | } |
835 | } | 838 | } |
836 | 839 | ||
840 | /* Check that the connection comes from a privileged port. | ||
841 | Rhosts- and Rhosts-RSA-Authentication only make sense | ||
842 | from priviledged programs. | ||
843 | Of course, if the intruder has root access on his local machine, | ||
844 | he can connect from any port. So do not use these authentication | ||
845 | methods from machines that you do not trust. */ | ||
846 | if (remote_port >= IPPORT_RESERVED || | ||
847 | remote_port < IPPORT_RESERVED / 2) | ||
848 | { | ||
849 | options.rhosts_authentication = 0; | ||
850 | options.rhosts_rsa_authentication = 0; | ||
851 | } | ||
852 | |||
837 | packet_set_nonblocking(); | 853 | packet_set_nonblocking(); |
838 | 854 | ||
839 | /* Handle the connection. We pass as argument whether the connection | 855 | /* Handle the connection. */ |
840 | came from a privileged port. */ | 856 | do_connection(); |
841 | do_connection(get_remote_port() < IPPORT_RESERVED); | ||
842 | 857 | ||
843 | #ifdef KRB4 | 858 | #ifdef KRB4 |
844 | /* Cleanup user's ticket cache file. */ | 859 | /* Cleanup user's ticket cache file. */ |
@@ -879,7 +894,8 @@ main(int ac, char **av) | |||
879 | been exchanged. This sends server key and performs the key exchange. | 894 | been exchanged. This sends server key and performs the key exchange. |
880 | Server and host keys will no longer be needed after this functions. */ | 895 | Server and host keys will no longer be needed after this functions. */ |
881 | 896 | ||
882 | void do_connection(int privileged_port) | 897 | void |
898 | do_connection() | ||
883 | { | 899 | { |
884 | int i, len; | 900 | int i, len; |
885 | BIGNUM *session_key_int; | 901 | BIGNUM *session_key_int; |
@@ -1071,7 +1087,7 @@ void do_connection(int privileged_port) | |||
1071 | 1087 | ||
1072 | setproctitle("%s", user); | 1088 | setproctitle("%s", user); |
1073 | /* Do the authentication. */ | 1089 | /* Do the authentication. */ |
1074 | do_authentication(user, privileged_port); | 1090 | do_authentication(user); |
1075 | } | 1091 | } |
1076 | 1092 | ||
1077 | /* Check if the user is allowed to log in via ssh. If user is listed in | 1093 | /* Check if the user is allowed to log in via ssh. If user is listed in |
@@ -1154,26 +1170,13 @@ allowed_user(struct passwd *pw) | |||
1154 | 1170 | ||
1155 | /* Performs authentication of an incoming connection. Session key has already | 1171 | /* Performs authentication of an incoming connection. Session key has already |
1156 | been exchanged and encryption is enabled. User is the user name to log | 1172 | been exchanged and encryption is enabled. User is the user name to log |
1157 | in as (received from the clinet). Privileged_port is true if the | 1173 | in as (received from the client). */ |
1158 | connection comes from a privileged port (used for .rhosts authentication).*/ | ||
1159 | |||
1160 | #define MAX_AUTH_FAILURES 5 | ||
1161 | 1174 | ||
1162 | void | 1175 | void |
1163 | do_authentication(char *user, int privileged_port) | 1176 | do_authentication(char *user) |
1164 | { | 1177 | { |
1165 | int type; | ||
1166 | int authenticated = 0; | ||
1167 | int authentication_failures = 0; | ||
1168 | char *password = NULL; | ||
1169 | struct passwd *pw, pwcopy; | 1178 | struct passwd *pw, pwcopy; |
1170 | char *client_user = NULL; | 1179 | |
1171 | unsigned int client_host_key_bits; | ||
1172 | BIGNUM *client_host_key_e, *client_host_key_n; | ||
1173 | #ifdef HAVE_LIBPAM | ||
1174 | int pam_retval; | ||
1175 | #endif /* HAVE_LIBPAM */ | ||
1176 | |||
1177 | #ifdef AFS | 1180 | #ifdef AFS |
1178 | /* If machine has AFS, set process authentication group. */ | 1181 | /* If machine has AFS, set process authentication group. */ |
1179 | if (k_hasafs()) { | 1182 | if (k_hasafs()) { |
@@ -1185,8 +1188,8 @@ do_authentication(char *user, int privileged_port) | |||
1185 | /* Verify that the user is a valid user. */ | 1188 | /* Verify that the user is a valid user. */ |
1186 | pw = getpwnam(user); | 1189 | pw = getpwnam(user); |
1187 | if (!pw || !allowed_user(pw)) | 1190 | if (!pw || !allowed_user(pw)) |
1188 | eat_packets_and_disconnect(user); | 1191 | do_fake_authloop(user); |
1189 | 1192 | ||
1190 | /* Take a copy of the returned structure. */ | 1193 | /* Take a copy of the returned structure. */ |
1191 | memset(&pwcopy, 0, sizeof(pwcopy)); | 1194 | memset(&pwcopy, 0, sizeof(pwcopy)); |
1192 | pwcopy.pw_name = xstrdup(pw->pw_name); | 1195 | pwcopy.pw_name = xstrdup(pw->pw_name); |
@@ -1199,13 +1202,11 @@ do_authentication(char *user, int privileged_port) | |||
1199 | 1202 | ||
1200 | #ifdef HAVE_LIBPAM | 1203 | #ifdef HAVE_LIBPAM |
1201 | debug("Starting up PAM with username \"%.200s\"", pw->pw_name); | 1204 | debug("Starting up PAM with username \"%.200s\"", pw->pw_name); |
1202 | pam_retval = pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh); | 1205 | |
1203 | if (pam_retval != PAM_SUCCESS) | 1206 | if (pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh) != PAM_SUCCESS) |
1204 | { | 1207 | fatal("PAM initialisation failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); |
1205 | log("PAM initialisation failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval)); | 1208 | |
1206 | eat_packets_and_disconnect(user); | 1209 | fatal_add_cleanup(&pam_cleanup_proc, NULL); |
1207 | } | ||
1208 | fatal_add_cleanup(&pam_cleanup_proc, NULL); | ||
1209 | #endif | 1210 | #endif |
1210 | 1211 | ||
1211 | /* If we are not running as root, the user must have the same uid as the | 1212 | /* If we are not running as root, the user must have the same uid as the |
@@ -1224,313 +1225,263 @@ do_authentication(char *user, int privileged_port) | |||
1224 | { | 1225 | { |
1225 | /* Authentication with empty password succeeded. */ | 1226 | /* Authentication with empty password succeeded. */ |
1226 | debug("Login for user %.100s accepted without authentication.", user); | 1227 | debug("Login for user %.100s accepted without authentication.", user); |
1227 | /* authentication_type = SSH_AUTH_PASSWORD; */ | 1228 | } else { |
1228 | authenticated = 1; | 1229 | /* Loop until the user has been authenticated or the connection is closed, |
1229 | /* Success packet will be sent after loop below. */ | 1230 | do_authloop() returns only if authentication is successfull */ |
1231 | do_authloop(pw); | ||
1230 | } | 1232 | } |
1231 | else | 1233 | |
1234 | /* XXX log unified auth message */ | ||
1235 | |||
1236 | /* Check if the user is logging in as root and root logins are disallowed. */ | ||
1237 | if (pw->pw_uid == 0 && !options.permit_root_login) | ||
1232 | { | 1238 | { |
1233 | /* Indicate that authentication is needed. */ | 1239 | if (forced_command) |
1234 | packet_start(SSH_SMSG_FAILURE); | 1240 | log("Root login accepted for forced command."); |
1235 | packet_send(); | 1241 | else |
1236 | packet_write_wait(); | 1242 | packet_disconnect("ROOT LOGIN REFUSED FROM %.200s", |
1243 | get_canonical_hostname()); | ||
1237 | } | 1244 | } |
1238 | 1245 | ||
1239 | /* Loop until the user has been authenticated or the connection is closed. */ | 1246 | /* The user has been authenticated and accepted. */ |
1240 | while (!authenticated) | 1247 | packet_start(SSH_SMSG_SUCCESS); |
1241 | { | 1248 | packet_send(); |
1242 | int plen; | 1249 | packet_write_wait(); |
1243 | /* Get a packet from the client. */ | ||
1244 | type = packet_read(&plen); | ||
1245 | |||
1246 | /* Process the packet. */ | ||
1247 | switch (type) | ||
1248 | { | ||
1249 | 1250 | ||
1250 | #ifdef AFS | 1251 | /* Perform session preparation. */ |
1251 | case SSH_CMSG_HAVE_KERBEROS_TGT: | 1252 | do_authenticated(pw); |
1252 | if (!options.kerberos_tgt_passing) | 1253 | } |
1253 | { | 1254 | |
1254 | /* packet_get_all(); */ | 1255 | #define MAX_AUTH_FAILURES 5 |
1255 | log("Kerberos tgt passing disabled."); | 1256 | |
1256 | break; | 1257 | /* read packets and try to authenticate local user *pw. |
1257 | } | 1258 | return if authentication is successfull */ |
1258 | else { | 1259 | void |
1259 | /* Accept Kerberos tgt. */ | 1260 | do_authloop(struct passwd *pw) |
1260 | int dlen; | 1261 | { |
1261 | char *tgt = packet_get_string(&dlen); | 1262 | int authentication_failures = 0; |
1262 | packet_integrity_check(plen, 4 + dlen, type); | 1263 | unsigned int client_host_key_bits; |
1263 | if (!auth_kerberos_tgt(pw, tgt)) | 1264 | BIGNUM *client_host_key_e, *client_host_key_n; |
1264 | debug("Kerberos tgt REFUSED for %s", user); | 1265 | BIGNUM *n; |
1265 | xfree(tgt); | 1266 | char *client_user, *password; |
1266 | } | 1267 | int plen, dlen, nlen, ulen, elen; |
1267 | continue; | 1268 | |
1269 | /* Indicate that authentication is needed. */ | ||
1270 | packet_start(SSH_SMSG_FAILURE); | ||
1271 | packet_send(); | ||
1272 | packet_write_wait(); | ||
1273 | |||
1274 | for (;;) { | ||
1275 | int authenticated = 0; | ||
1268 | 1276 | ||
1269 | case SSH_CMSG_HAVE_AFS_TOKEN: | 1277 | /* Get a packet from the client. */ |
1270 | if (!options.afs_token_passing || !k_hasafs()) { | 1278 | int type = packet_read(&plen); |
1279 | |||
1280 | /* Process the packet. */ | ||
1281 | switch (type) | ||
1282 | { | ||
1283 | #ifdef AFS | ||
1284 | case SSH_CMSG_HAVE_KERBEROS_TGT: | ||
1285 | if (!options.kerberos_tgt_passing) | ||
1286 | { | ||
1271 | /* packet_get_all(); */ | 1287 | /* packet_get_all(); */ |
1272 | log("AFS token passing disabled."); | 1288 | log("Kerberos tgt passing disabled."); |
1273 | break; | 1289 | break; |
1274 | } | 1290 | } |
1275 | else { | 1291 | else { |
1276 | /* Accept AFS token. */ | 1292 | /* Accept Kerberos tgt. */ |
1277 | int dlen; | 1293 | char *tgt = packet_get_string(&dlen); |
1278 | char *token_string = packet_get_string(&dlen); | 1294 | packet_integrity_check(plen, 4 + dlen, type); |
1279 | packet_integrity_check(plen, 4 + dlen, type); | 1295 | if (!auth_kerberos_tgt(pw, tgt)) |
1280 | if (!auth_afs_token(pw, token_string)) | 1296 | debug("Kerberos tgt REFUSED for %s", pw->pw_name); |
1281 | debug("AFS token REFUSED for %s", user); | 1297 | xfree(tgt); |
1282 | xfree(token_string); | 1298 | } |
1283 | continue; | 1299 | continue; |
1284 | } | 1300 | |
1301 | case SSH_CMSG_HAVE_AFS_TOKEN: | ||
1302 | if (!options.afs_token_passing || !k_hasafs()) { | ||
1303 | /* packet_get_all(); */ | ||
1304 | log("AFS token passing disabled."); | ||
1305 | break; | ||
1306 | } | ||
1307 | else { | ||
1308 | /* Accept AFS token. */ | ||
1309 | char *token_string = packet_get_string(&dlen); | ||
1310 | packet_integrity_check(plen, 4 + dlen, type); | ||
1311 | if (!auth_afs_token(pw, token_string)) | ||
1312 | debug("AFS token REFUSED for %s", pw->pw_name); | ||
1313 | xfree(token_string); | ||
1314 | } | ||
1315 | continue; | ||
1285 | #endif /* AFS */ | 1316 | #endif /* AFS */ |
1286 | |||
1287 | #ifdef KRB4 | ||
1288 | case SSH_CMSG_AUTH_KERBEROS: | ||
1289 | if (!options.kerberos_authentication) | ||
1290 | { | ||
1291 | /* packet_get_all(); */ | ||
1292 | log("Kerberos authentication disabled."); | ||
1293 | break; | ||
1294 | } | ||
1295 | else { | ||
1296 | /* Try Kerberos v4 authentication. */ | ||
1297 | KTEXT_ST auth; | ||
1298 | char *tkt_user = NULL; | ||
1299 | char *kdata = packet_get_string((unsigned int *)&auth.length); | ||
1300 | packet_integrity_check(plen, 4 + auth.length, type); | ||
1301 | |||
1302 | if (auth.length < MAX_KTXT_LEN) | ||
1303 | memcpy(auth.dat, kdata, auth.length); | ||
1304 | xfree(kdata); | ||
1305 | 1317 | ||
1306 | if (auth_krb4(user, &auth, &tkt_user)) { | 1318 | #ifdef KRB4 |
1307 | /* Client has successfully authenticated to us. */ | 1319 | case SSH_CMSG_AUTH_KERBEROS: |
1308 | log("Kerberos authentication accepted %s for account " | 1320 | if (!options.kerberos_authentication) |
1309 | "%s from %s", tkt_user, user, get_canonical_hostname()); | 1321 | { |
1310 | /* authentication_type = SSH_AUTH_KERBEROS; */ | 1322 | /* packet_get_all(); */ |
1311 | authenticated = 1; | 1323 | log("Kerberos authentication disabled."); |
1312 | xfree(tkt_user); | 1324 | break; |
1313 | } | ||
1314 | else { | ||
1315 | log("Kerberos authentication failed for account " | ||
1316 | "%s from %s", user, get_canonical_hostname()); | ||
1317 | } | ||
1318 | } | 1325 | } |
1319 | break; | 1326 | else { |
1320 | #endif /* KRB4 */ | 1327 | /* Try Kerberos v4 authentication. */ |
1328 | KTEXT_ST auth; | ||
1329 | char *tkt_user = NULL; | ||
1330 | char *kdata = packet_get_string((unsigned int *)&auth.length); | ||
1331 | packet_integrity_check(plen, 4 + auth.length, type); | ||
1332 | |||
1333 | if (auth.length < MAX_KTXT_LEN) | ||
1334 | memcpy(auth.dat, kdata, auth.length); | ||
1335 | xfree(kdata); | ||
1321 | 1336 | ||
1322 | case SSH_CMSG_AUTH_RHOSTS: | 1337 | authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user); |
1323 | if (!options.rhosts_authentication) | 1338 | |
1324 | { | 1339 | log("Kerberos authentication %s%s for account %s from %s", |
1325 | log("Rhosts authentication disabled."); | 1340 | authenticated ? "accepted " : "failed", |
1326 | break; | 1341 | tkt_user != NULL ? tkt_user : "", |
1327 | } | 1342 | pw->pw_name, get_canonical_hostname()); |
1328 | 1343 | if (authenticated) | |
1329 | /* Rhosts authentication (also uses /etc/hosts.equiv). */ | 1344 | xfree(tkt_user); |
1330 | if (!privileged_port) | 1345 | } |
1331 | { | 1346 | break; |
1332 | log("Rhosts authentication not available for connections from unprivileged port."); | 1347 | #endif /* KRB4 */ |
1333 | break; | 1348 | |
1334 | } | 1349 | case SSH_CMSG_AUTH_RHOSTS: |
1335 | 1350 | if (!options.rhosts_authentication) | |
1336 | /* Get client user name. Note that we just have to trust the client; | ||
1337 | this is one reason why rhosts authentication is insecure. | ||
1338 | (Another is IP-spoofing on a local network.) */ | ||
1339 | { | 1351 | { |
1340 | int dlen; | 1352 | log("Rhosts authentication disabled."); |
1341 | client_user = packet_get_string(&dlen); | 1353 | break; |
1342 | packet_integrity_check(plen, 4 + dlen, type); | ||
1343 | } | 1354 | } |
1355 | |||
1356 | /* Get client user name. Note that we just have to trust the client; | ||
1357 | this is one reason why rhosts authentication is insecure. | ||
1358 | (Another is IP-spoofing on a local network.) */ | ||
1359 | client_user = packet_get_string(&dlen); | ||
1360 | packet_integrity_check(plen, 4 + dlen, type); | ||
1361 | |||
1362 | /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ | ||
1363 | authenticated = auth_rhosts(pw, client_user); | ||
1344 | 1364 | ||
1345 | /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ | 1365 | log("Rhosts authentication %s for %.100s, remote %.100s on %.700s.", |
1346 | if (auth_rhosts(pw, client_user)) | 1366 | authenticated ? "accepted" : "failed", |
1347 | { | 1367 | pw->pw_name, client_user, get_canonical_hostname()); |
1348 | /* Authentication accepted. */ | ||
1349 | log("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.", | ||
1350 | user, client_user, get_canonical_hostname()); | ||
1351 | authenticated = 1; | ||
1352 | #ifndef HAVE_LIBPAM | 1368 | #ifndef HAVE_LIBPAM |
1353 | xfree(client_user); | 1369 | xfree(client_user); |
1354 | #endif /* HAVE_LIBPAM */ | 1370 | #endif /* HAVE_LIBPAM */ |
1355 | break; | 1371 | break; |
1356 | } | 1372 | |
1357 | log("Rhosts authentication failed for %.100s, remote %.100s.", | 1373 | case SSH_CMSG_AUTH_RHOSTS_RSA: |
1358 | user, client_user); | 1374 | if (!options.rhosts_rsa_authentication) |
1359 | #ifndef HAVE_LIBPAM | ||
1360 | xfree(client_user); | ||
1361 | #endif /* HAVE_LIBPAM */ | ||
1362 | break; | ||
1363 | |||
1364 | case SSH_CMSG_AUTH_RHOSTS_RSA: | ||
1365 | if (!options.rhosts_rsa_authentication) | ||
1366 | { | ||
1367 | log("Rhosts with RSA authentication disabled."); | ||
1368 | break; | ||
1369 | } | ||
1370 | |||
1371 | /* Rhosts authentication (also uses /etc/hosts.equiv) with RSA | ||
1372 | host authentication. */ | ||
1373 | if (!privileged_port) | ||
1374 | { | ||
1375 | log("Rhosts authentication not available for connections from unprivileged port."); | ||
1376 | break; | ||
1377 | } | ||
1378 | |||
1379 | { | 1375 | { |
1380 | int ulen, elen, nlen; | 1376 | log("Rhosts with RSA authentication disabled."); |
1381 | /* Get client user name. Note that we just have to trust | 1377 | break; |
1382 | the client; root on the client machine can claim to be | ||
1383 | any user. */ | ||
1384 | client_user = packet_get_string(&ulen); | ||
1385 | |||
1386 | /* Get the client host key. */ | ||
1387 | client_host_key_e = BN_new(); | ||
1388 | client_host_key_n = BN_new(); | ||
1389 | client_host_key_bits = packet_get_int(); | ||
1390 | packet_get_bignum(client_host_key_e, &elen); | ||
1391 | packet_get_bignum(client_host_key_n, &nlen); | ||
1392 | |||
1393 | packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type); | ||
1394 | } | 1378 | } |
1395 | 1379 | ||
1396 | if (auth_rhosts_rsa(pw, client_user, | 1380 | /* Get client user name. Note that we just have to trust |
1397 | client_host_key_bits, client_host_key_e, client_host_key_n)) | 1381 | the client; root on the client machine can claim to be |
1398 | { | 1382 | any user. */ |
1399 | /* Authentication accepted. */ | 1383 | client_user = packet_get_string(&ulen); |
1400 | authenticated = 1; | 1384 | |
1401 | #ifndef HAVE_LIBPAM | 1385 | /* Get the client host key. */ |
1402 | xfree(client_user); | 1386 | client_host_key_e = BN_new(); |
1403 | #endif /* HAVE_LIBPAM */ | 1387 | client_host_key_n = BN_new(); |
1404 | BN_clear_free(client_host_key_e); | 1388 | client_host_key_bits = packet_get_int(); |
1405 | BN_clear_free(client_host_key_n); | 1389 | packet_get_bignum(client_host_key_e, &elen); |
1406 | break; | 1390 | packet_get_bignum(client_host_key_n, &nlen); |
1407 | } | 1391 | |
1408 | log("Rhosts authentication failed for %.100s, remote %.100s.", | 1392 | packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type); |
1409 | user, client_user); | 1393 | |
1394 | authenticated = auth_rhosts_rsa(pw, client_user, client_host_key_bits, | ||
1395 | client_host_key_e, client_host_key_n); | ||
1396 | log("Rhosts authentication %s for %.100s, remote %.100s.", | ||
1397 | authenticated ? "accepted" : "failed", | ||
1398 | pw->pw_name, client_user); | ||
1410 | #ifndef HAVE_LIBPAM | 1399 | #ifndef HAVE_LIBPAM |
1411 | xfree(client_user); | 1400 | xfree(client_user); |
1412 | #endif /* HAVE_LIBPAM */ | 1401 | #endif /* HAVE_LIBPAM */ |
1413 | BN_clear_free(client_host_key_e); | 1402 | BN_clear_free(client_host_key_e); |
1414 | BN_clear_free(client_host_key_n); | 1403 | BN_clear_free(client_host_key_n); |
1415 | break; | 1404 | break; |
1416 | 1405 | ||
1417 | case SSH_CMSG_AUTH_RSA: | 1406 | case SSH_CMSG_AUTH_RSA: |
1418 | if (!options.rsa_authentication) | 1407 | if (!options.rsa_authentication) |
1419 | { | ||
1420 | log("RSA authentication disabled."); | ||
1421 | break; | ||
1422 | } | ||
1423 | |||
1424 | /* RSA authentication requested. */ | ||
1425 | { | 1408 | { |
1426 | int nlen; | 1409 | log("RSA authentication disabled."); |
1427 | BIGNUM *n; | 1410 | break; |
1428 | n = BN_new(); | ||
1429 | packet_get_bignum(n, &nlen); | ||
1430 | |||
1431 | packet_integrity_check(plen, nlen, type); | ||
1432 | |||
1433 | if (auth_rsa(pw, n)) | ||
1434 | { | ||
1435 | /* Successful authentication. */ | ||
1436 | BN_clear_free(n); | ||
1437 | log("RSA authentication for %.100s accepted.", user); | ||
1438 | authenticated = 1; | ||
1439 | break; | ||
1440 | } | ||
1441 | BN_clear_free(n); | ||
1442 | log("RSA authentication for %.100s failed.", user); | ||
1443 | } | 1411 | } |
1444 | break; | 1412 | |
1445 | 1413 | /* RSA authentication requested. */ | |
1446 | case SSH_CMSG_AUTH_PASSWORD: | 1414 | n = BN_new(); |
1447 | if (!options.password_authentication) | 1415 | packet_get_bignum(n, &nlen); |
1448 | { | 1416 | packet_integrity_check(plen, nlen, type); |
1449 | log("Password authentication disabled."); | 1417 | authenticated = auth_rsa(pw, n); |
1450 | break; | 1418 | BN_clear_free(n); |
1451 | } | 1419 | log("RSA authentication %s for %.100s.", |
1452 | 1420 | authenticated ? "accepted" : "failed", | |
1453 | /* Password authentication requested. */ | 1421 | pw->pw_name); |
1454 | /* Read user password. It is in plain text, but was transmitted | 1422 | break; |
1455 | over the encrypted channel so it is not visible to an outside | 1423 | |
1456 | observer. */ | 1424 | case SSH_CMSG_AUTH_PASSWORD: |
1425 | if (!options.password_authentication) | ||
1457 | { | 1426 | { |
1458 | int passw_len; | 1427 | log("Password authentication disabled."); |
1459 | password = packet_get_string(&passw_len); | 1428 | break; |
1460 | packet_integrity_check(plen, 4 + passw_len, type); | ||
1461 | } | 1429 | } |
1462 | 1430 | ||
1431 | /* Read user password. It is in plain text, but was transmitted | ||
1432 | over the encrypted channel so it is not visible to an outside | ||
1433 | observer. */ | ||
1434 | password = packet_get_string(&dlen); | ||
1435 | packet_integrity_check(plen, 4 + dlen, type); | ||
1436 | |||
1463 | #ifdef HAVE_LIBPAM | 1437 | #ifdef HAVE_LIBPAM |
1464 | pampasswd = password; | 1438 | /* Do PAM auth with password */ |
1465 | 1439 | pampasswd = password; | |
1466 | pam_retval = pam_authenticate((pam_handle_t *)pamh, 0); | 1440 | pam_retval = pam_authenticate((pam_handle_t *)pamh, 0); |
1467 | if (pam_retval == PAM_SUCCESS) | 1441 | if (pam_retval == PAM_SUCCESS) |
1468 | { | 1442 | { |
1469 | log("PAM Password authentication accepted for \"%.100s\"", user); | 1443 | log("PAM Password authentication accepted for user \"%.100s\"", user); |
1470 | authenticated = 1; | 1444 | authenticated = 1; |
1471 | break; | 1445 | break; |
1472 | } else | 1446 | } |
1473 | { | 1447 | |
1474 | log("PAM Password authentication for \"%.100s\" failed: %s", | 1448 | log("PAM Password authentication for \"%.100s\" failed: %s", |
1475 | user, pam_strerror((pam_handle_t *)pamh, pam_retval)); | 1449 | user, pam_strerror((pam_handle_t *)pamh, pam_retval)); |
1476 | break; | 1450 | break; |
1477 | } | ||
1478 | #else /* HAVE_LIBPAM */ | 1451 | #else /* HAVE_LIBPAM */ |
1479 | /* Try authentication with the password. */ | 1452 | /* Try authentication with the password. */ |
1480 | if (auth_password(pw, password)) | 1453 | authenticated = auth_password(pw, password); |
1481 | { | ||
1482 | /* Successful authentication. */ | ||
1483 | /* Clear the password from memory. */ | ||
1484 | memset(password, 0, strlen(password)); | ||
1485 | xfree(password); | ||
1486 | log("Password authentication for %.100s accepted.", user); | ||
1487 | authenticated = 1; | ||
1488 | break; | ||
1489 | } | ||
1490 | log("Password authentication for %.100s failed.", user); | ||
1491 | memset(password, 0, strlen(password)); | ||
1492 | xfree(password); | ||
1493 | break; | ||
1494 | #endif /* HAVE_LIBPAM */ | ||
1495 | |||
1496 | case SSH_CMSG_AUTH_TIS: | ||
1497 | /* TIS Authentication is unsupported */ | ||
1498 | log("TIS authentication disabled."); | ||
1499 | break; | ||
1500 | 1454 | ||
1501 | default: | 1455 | memset(password, 0, strlen(password)); |
1502 | /* Any unknown messages will be ignored (and failure returned) | 1456 | xfree(password); |
1503 | during authentication. */ | ||
1504 | log("Unknown message during authentication: type %d", type); | ||
1505 | break; /* Respond with a failure message. */ | ||
1506 | } | ||
1507 | /* If successfully authenticated, break out of loop. */ | ||
1508 | if (authenticated) | ||
1509 | break; | 1457 | break; |
1510 | 1458 | #endif /* HAVE_LIBPAM */ | |
1511 | if (++authentication_failures >= MAX_AUTH_FAILURES) { | 1459 | |
1512 | packet_disconnect("Too many authentication failures for %.100s from %.200s", | 1460 | case SSH_CMSG_AUTH_TIS: |
1513 | pw->pw_name, get_canonical_hostname()); | 1461 | /* TIS Authentication is unsupported */ |
1462 | log("TIS authentication disabled."); | ||
1463 | break; | ||
1464 | |||
1465 | default: | ||
1466 | /* Any unknown messages will be ignored (and failure returned) | ||
1467 | during authentication. */ | ||
1468 | log("Unknown message during authentication: type %d", type); | ||
1469 | break; /* Respond with a failure message. */ | ||
1514 | } | 1470 | } |
1515 | /* Send a message indicating that the authentication attempt failed. */ | ||
1516 | packet_start(SSH_SMSG_FAILURE); | ||
1517 | packet_send(); | ||
1518 | packet_write_wait(); | ||
1519 | 1471 | ||
1520 | } | 1472 | if (authenticated) |
1521 | 1473 | break; | |
1522 | /* Check if the user is logging in as root and root logins are disallowed. */ | 1474 | if (++authentication_failures >= MAX_AUTH_FAILURES) |
1523 | if (pw->pw_uid == 0 && !options.permit_root_login) | 1475 | packet_disconnect("Too many authentication failures for %.100s from %.200s", |
1524 | { | 1476 | pw->pw_name, get_canonical_hostname()); |
1525 | if (forced_command) | 1477 | /* Send a message indicating that the authentication attempt failed. */ |
1526 | log("Root login accepted for forced command."); | 1478 | packet_start(SSH_SMSG_FAILURE); |
1527 | else | 1479 | packet_send(); |
1528 | packet_disconnect("ROOT LOGIN REFUSED FROM %.200s", | 1480 | packet_write_wait(); |
1529 | get_canonical_hostname()); | 1481 | } |
1530 | } | ||
1531 | 1482 | ||
1532 | #ifdef HAVE_LIBPAM | 1483 | #ifdef HAVE_LIBPAM |
1533 | do_pam_account_and_session(pw->pw_name, password, client_user, get_canonical_hostname()); | 1484 | do_pam_account_and_session(pw->pw_name, client_user, get_canonical_hostname()); |
1534 | 1485 | ||
1535 | /* Clean up */ | 1486 | /* Clean up */ |
1536 | if (client_user != NULL) | 1487 | if (client_user != NULL) |
@@ -1542,65 +1493,55 @@ do_authentication(char *user, int privileged_port) | |||
1542 | xfree(password); | 1493 | xfree(password); |
1543 | } | 1494 | } |
1544 | #endif /* HAVE_LIBPAM */ | 1495 | #endif /* HAVE_LIBPAM */ |
1545 | |||
1546 | /* The user has been authenticated and accepted. */ | ||
1547 | packet_start(SSH_SMSG_SUCCESS); | ||
1548 | packet_send(); | ||
1549 | packet_write_wait(); | ||
1550 | |||
1551 | /* Perform session preparation. */ | ||
1552 | do_authenticated(pw); | ||
1553 | } | 1496 | } |
1554 | 1497 | ||
1555 | /* Read authentication messages, but return only failures until */ | 1498 | /* The user does not exist or access is denied, |
1556 | /* max auth attempts exceeded, then disconnect */ | 1499 | but fake indication that authentication is needed. */ |
1557 | void eat_packets_and_disconnect(const char *user) | 1500 | void |
1501 | do_fake_authloop(char *user) | ||
1558 | { | 1502 | { |
1559 | int authentication_failures = 0; | 1503 | int authentication_failures = 0; |
1560 | 1504 | ||
1505 | /* Indicate that authentication is needed. */ | ||
1561 | packet_start(SSH_SMSG_FAILURE); | 1506 | packet_start(SSH_SMSG_FAILURE); |
1562 | packet_send(); | 1507 | packet_send(); |
1563 | packet_write_wait(); | 1508 | packet_write_wait(); |
1564 | 1509 | ||
1565 | /* Keep reading packets, and always respond with a failure. This is to | 1510 | /* Keep reading packets, and always respond with a failure. This is to |
1566 | avoid disclosing whether such a user really exists. */ | 1511 | avoid disclosing whether such a user really exists. */ |
1567 | while(1) | 1512 | for (;;) |
1568 | { | ||
1569 | /* Read a packet. This will not return if the client disconnects. */ | ||
1570 | int plen; | ||
1571 | #ifndef SKEY | ||
1572 | (void) packet_read(&plen); | ||
1573 | #else /* SKEY */ | ||
1574 | int type = packet_read(&plen); | ||
1575 | int passw_len; | ||
1576 | char *password, *skeyinfo; | ||
1577 | if (options.password_authentication && | ||
1578 | options.skey_authentication == 1 && | ||
1579 | type == SSH_CMSG_AUTH_PASSWORD && | ||
1580 | (password = packet_get_string(&passw_len)) != NULL && | ||
1581 | passw_len == 5 && | ||
1582 | strncasecmp(password, "s/key", 5) == 0 && | ||
1583 | (skeyinfo = skey_fake_keyinfo(user)) != NULL ) | ||
1584 | { | 1513 | { |
1585 | /* Send a fake s/key challenge. */ | 1514 | /* Read a packet. This will not return if the client disconnects. */ |
1586 | packet_send_debug(skeyinfo); | 1515 | int plen; |
1587 | } | 1516 | int type = packet_read(&plen); |
1588 | #endif /* SKEY */ | 1517 | #ifdef SKEY |
1589 | if (++authentication_failures >= MAX_AUTH_FAILURES) | 1518 | int passw_len; |
1590 | { | 1519 | char *password, *skeyinfo; |
1591 | packet_disconnect("Too many authentication failures for %.100s from %.200s", | 1520 | if (options.password_authentication && |
1592 | user, get_canonical_hostname()); | 1521 | options.skey_authentication == 1 && |
1522 | type == SSH_CMSG_AUTH_PASSWORD && | ||
1523 | (password = packet_get_string(&passw_len)) != NULL && | ||
1524 | passw_len == 5 && | ||
1525 | strncasecmp(password, "s/key", 5) == 0 && | ||
1526 | (skeyinfo = skey_fake_keyinfo(user)) != NULL ){ | ||
1527 | /* Send a fake s/key challenge. */ | ||
1528 | packet_send_debug(skeyinfo); | ||
1529 | } | ||
1530 | #endif | ||
1531 | if (++authentication_failures >= MAX_AUTH_FAILURES) | ||
1532 | packet_disconnect("Too many authentication failures for %.100s from %.200s", | ||
1533 | user, get_canonical_hostname()); | ||
1534 | /* Send failure. This should be indistinguishable from a failed | ||
1535 | authentication. */ | ||
1536 | packet_start(SSH_SMSG_FAILURE); | ||
1537 | packet_send(); | ||
1538 | packet_write_wait(); | ||
1593 | } | 1539 | } |
1594 | /* Send failure. This should be indistinguishable from a failed | ||
1595 | authentication. */ | ||
1596 | packet_start(SSH_SMSG_FAILURE); | ||
1597 | packet_send(); | ||
1598 | packet_write_wait(); | ||
1599 | } | ||
1600 | /*NOTREACHED*/ | 1540 | /*NOTREACHED*/ |
1601 | abort(); | 1541 | abort(); |
1602 | } | 1542 | } |
1603 | 1543 | ||
1544 | |||
1604 | /* Remove local Xauthority file. */ | 1545 | /* Remove local Xauthority file. */ |
1605 | static void | 1546 | static void |
1606 | xauthfile_cleanup_proc(void *ignore) | 1547 | xauthfile_cleanup_proc(void *ignore) |
@@ -2075,8 +2016,10 @@ void do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
2075 | { | 2016 | { |
2076 | fromlen = sizeof(from); | 2017 | fromlen = sizeof(from); |
2077 | if (getpeername(packet_get_connection_in(), | 2018 | if (getpeername(packet_get_connection_in(), |
2078 | (struct sockaddr *)&from, &fromlen) < 0) | 2019 | (struct sockaddr *)&from, &fromlen) < 0) { |
2079 | fatal("getpeername: %.100s", strerror(errno)); | 2020 | debug("getpeername: %.100s", strerror(errno)); |
2021 | fatal_cleanup(); | ||
2022 | } | ||
2080 | } | 2023 | } |
2081 | 2024 | ||
2082 | /* Record that there was a login on that terminal. */ | 2025 | /* Record that there was a login on that terminal. */ |