diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 116 |
1 files changed, 74 insertions, 42 deletions
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "includes.h" | 13 | #include "includes.h" |
14 | RCSID("$OpenBSD: sshd.c,v 1.80 2000/01/20 15:19:22 markus Exp $"); | 14 | RCSID("$OpenBSD: sshd.c,v 1.90 2000/03/06 20:29:04 markus Exp $"); |
15 | 15 | ||
16 | #include "xmalloc.h" | 16 | #include "xmalloc.h" |
17 | #include "rsa.h" | 17 | #include "rsa.h" |
@@ -148,6 +148,27 @@ void do_child(const char *command, struct passwd * pw, const char *term, | |||
148 | const char *auth_data, const char *ttyname); | 148 | const char *auth_data, const char *ttyname); |
149 | 149 | ||
150 | /* | 150 | /* |
151 | * Remove local Xauthority file. | ||
152 | */ | ||
153 | void | ||
154 | xauthfile_cleanup_proc(void *ignore) | ||
155 | { | ||
156 | debug("xauthfile_cleanup_proc called"); | ||
157 | |||
158 | if (xauthfile != NULL) { | ||
159 | char *p; | ||
160 | unlink(xauthfile); | ||
161 | p = strrchr(xauthfile, '/'); | ||
162 | if (p != NULL) { | ||
163 | *p = '\0'; | ||
164 | rmdir(xauthfile); | ||
165 | } | ||
166 | xfree(xauthfile); | ||
167 | xauthfile = NULL; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /* | ||
151 | * Close all listening sockets | 172 | * Close all listening sockets |
152 | */ | 173 | */ |
153 | void | 174 | void |
@@ -234,6 +255,7 @@ grace_alarm_handler(int sig) | |||
234 | char * | 255 | char * |
235 | get_authname(int type) | 256 | get_authname(int type) |
236 | { | 257 | { |
258 | static char buf[1024]; | ||
237 | switch (type) { | 259 | switch (type) { |
238 | case SSH_CMSG_AUTH_PASSWORD: | 260 | case SSH_CMSG_AUTH_PASSWORD: |
239 | return "password"; | 261 | return "password"; |
@@ -252,8 +274,8 @@ get_authname(int type) | |||
252 | return "s/key"; | 274 | return "s/key"; |
253 | #endif | 275 | #endif |
254 | } | 276 | } |
255 | fatal("get_authname: unknown auth %d: internal error", type); | 277 | snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); |
256 | return NULL; | 278 | return buf; |
257 | } | 279 | } |
258 | 280 | ||
259 | /* | 281 | /* |
@@ -878,7 +900,7 @@ main(int ac, char **av) | |||
878 | 900 | ||
879 | /* Cleanup user's local Xauthority file. */ | 901 | /* Cleanup user's local Xauthority file. */ |
880 | if (xauthfile) | 902 | if (xauthfile) |
881 | unlink(xauthfile); | 903 | xauthfile_cleanup_proc(NULL); |
882 | 904 | ||
883 | /* The connection has been terminated. */ | 905 | /* The connection has been terminated. */ |
884 | verbose("Closing connection to %.100s", remote_ip); | 906 | verbose("Closing connection to %.100s", remote_ip); |
@@ -1089,12 +1111,14 @@ do_ssh_kex() | |||
1089 | * DenyUsers or user's primary group is listed in DenyGroups, false will | 1111 | * DenyUsers or user's primary group is listed in DenyGroups, false will |
1090 | * be returned. If AllowUsers isn't empty and user isn't listed there, or | 1112 | * be returned. If AllowUsers isn't empty and user isn't listed there, or |
1091 | * if AllowGroups isn't empty and user isn't listed there, false will be | 1113 | * if AllowGroups isn't empty and user isn't listed there, false will be |
1092 | * returned. Otherwise true is returned. | 1114 | * returned. |
1093 | * XXX This function should also check if user has a valid shell | 1115 | * If the user's shell is not executable, false will be returned. |
1116 | * Otherwise true is returned. | ||
1094 | */ | 1117 | */ |
1095 | static int | 1118 | static int |
1096 | allowed_user(struct passwd * pw) | 1119 | allowed_user(struct passwd * pw) |
1097 | { | 1120 | { |
1121 | struct stat st; | ||
1098 | struct group *grp; | 1122 | struct group *grp; |
1099 | int i; | 1123 | int i; |
1100 | #ifdef WITH_AIXAUTHENTICATE | 1124 | #ifdef WITH_AIXAUTHENTICATE |
@@ -1105,7 +1129,11 @@ allowed_user(struct passwd * pw) | |||
1105 | if (!pw) | 1129 | if (!pw) |
1106 | return 0; | 1130 | return 0; |
1107 | 1131 | ||
1108 | /* XXX Should check for valid login shell */ | 1132 | /* deny if shell does not exists or is not executable */ |
1133 | if (stat(pw->pw_shell, &st) != 0) | ||
1134 | return 0; | ||
1135 | if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) | ||
1136 | return 0; | ||
1109 | 1137 | ||
1110 | /* Return false if user is listed in DenyUsers */ | 1138 | /* Return false if user is listed in DenyUsers */ |
1111 | if (options.num_deny_users > 0) { | 1139 | if (options.num_deny_users > 0) { |
@@ -1202,6 +1230,7 @@ do_authentication() | |||
1202 | pw = getpwnam(user); | 1230 | pw = getpwnam(user); |
1203 | if (!pw || !allowed_user(pw)) | 1231 | if (!pw || !allowed_user(pw)) |
1204 | do_fake_authloop(user); | 1232 | do_fake_authloop(user); |
1233 | xfree(user); | ||
1205 | 1234 | ||
1206 | /* Take a copy of the returned structure. */ | 1235 | /* Take a copy of the returned structure. */ |
1207 | memset(&pwcopy, 0, sizeof(pwcopy)); | 1236 | memset(&pwcopy, 0, sizeof(pwcopy)); |
@@ -1224,7 +1253,7 @@ do_authentication() | |||
1224 | if (getuid() != 0 && pw->pw_uid != getuid()) | 1253 | if (getuid() != 0 && pw->pw_uid != getuid()) |
1225 | packet_disconnect("Cannot change user when server not running as root."); | 1254 | packet_disconnect("Cannot change user when server not running as root."); |
1226 | 1255 | ||
1227 | debug("Attempting authentication for %.100s.", user); | 1256 | debug("Attempting authentication for %.100s.", pw->pw_name); |
1228 | 1257 | ||
1229 | /* If the user has no password, accept authentication immediately. */ | 1258 | /* If the user has no password, accept authentication immediately. */ |
1230 | if (options.password_authentication && | 1259 | if (options.password_authentication && |
@@ -1510,17 +1539,22 @@ do_authloop(struct passwd * pw) | |||
1510 | get_remote_port(), | 1539 | get_remote_port(), |
1511 | user); | 1540 | user); |
1512 | 1541 | ||
1513 | if (authenticated) { | ||
1514 | #ifdef USE_PAM | 1542 | #ifdef USE_PAM |
1543 | if (authenticated) { | ||
1515 | if (!do_pam_account(pw->pw_name, client_user)) { | 1544 | if (!do_pam_account(pw->pw_name, client_user)) { |
1516 | if (client_user != NULL) | 1545 | if (client_user != NULL) { |
1517 | xfree(client_user); | 1546 | xfree(client_user); |
1518 | 1547 | client_user = NULL; | |
1548 | } | ||
1519 | do_fake_authloop(pw->pw_name); | 1549 | do_fake_authloop(pw->pw_name); |
1520 | } | 1550 | } |
1521 | #endif /* USE_PAM */ | ||
1522 | return; | 1551 | return; |
1523 | } | 1552 | } |
1553 | #else /* USE_PAM */ | ||
1554 | if (authenticated) { | ||
1555 | return; | ||
1556 | } | ||
1557 | #endif /* USE_PAM */ | ||
1524 | 1558 | ||
1525 | if (client_user != NULL) { | 1559 | if (client_user != NULL) { |
1526 | xfree(client_user); | 1560 | xfree(client_user); |
@@ -1572,6 +1606,7 @@ do_fake_authloop(char *user) | |||
1572 | /* Try to send a fake s/key challenge. */ | 1606 | /* Try to send a fake s/key challenge. */ |
1573 | if (options.skey_authentication == 1 && | 1607 | if (options.skey_authentication == 1 && |
1574 | (skeyinfo = skey_fake_keyinfo(user)) != NULL) { | 1608 | (skeyinfo = skey_fake_keyinfo(user)) != NULL) { |
1609 | password = NULL; | ||
1575 | if (type == SSH_CMSG_AUTH_TIS) { | 1610 | if (type == SSH_CMSG_AUTH_TIS) { |
1576 | packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); | 1611 | packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); |
1577 | packet_put_string(skeyinfo, strlen(skeyinfo)); | 1612 | packet_put_string(skeyinfo, strlen(skeyinfo)); |
@@ -1585,6 +1620,8 @@ do_fake_authloop(char *user) | |||
1585 | strncasecmp(password, "s/key", 5) == 0 ) { | 1620 | strncasecmp(password, "s/key", 5) == 0 ) { |
1586 | packet_send_debug(skeyinfo); | 1621 | packet_send_debug(skeyinfo); |
1587 | } | 1622 | } |
1623 | if (password != NULL) | ||
1624 | xfree(password); | ||
1588 | } | 1625 | } |
1589 | #endif | 1626 | #endif |
1590 | if (attempt > AUTH_FAIL_MAX) | 1627 | if (attempt > AUTH_FAIL_MAX) |
@@ -1607,22 +1644,6 @@ do_fake_authloop(char *user) | |||
1607 | abort(); | 1644 | abort(); |
1608 | } | 1645 | } |
1609 | 1646 | ||
1610 | |||
1611 | /* | ||
1612 | * Remove local Xauthority file. | ||
1613 | */ | ||
1614 | static void | ||
1615 | xauthfile_cleanup_proc(void *ignore) | ||
1616 | { | ||
1617 | debug("xauthfile_cleanup_proc called"); | ||
1618 | |||
1619 | if (xauthfile != NULL) { | ||
1620 | unlink(xauthfile); | ||
1621 | xfree(xauthfile); | ||
1622 | xauthfile = NULL; | ||
1623 | } | ||
1624 | } | ||
1625 | |||
1626 | struct pty_cleanup_context { | 1647 | struct pty_cleanup_context { |
1627 | const char *ttyname; | 1648 | const char *ttyname; |
1628 | int pid; | 1649 | int pid; |
@@ -1665,7 +1686,7 @@ do_authenticated(struct passwd * pw) | |||
1665 | { | 1686 | { |
1666 | int type; | 1687 | int type; |
1667 | int compression_level = 0, enable_compression_after_reply = 0; | 1688 | int compression_level = 0, enable_compression_after_reply = 0; |
1668 | int have_pty = 0, ptyfd = -1, ttyfd = -1, xauthfd = -1; | 1689 | int have_pty = 0, ptyfd = -1, ttyfd = -1; |
1669 | int row, col, xpixel, ypixel, screen; | 1690 | int row, col, xpixel, ypixel, screen; |
1670 | char ttyname[64]; | 1691 | char ttyname[64]; |
1671 | char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL; | 1692 | char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL; |
@@ -1684,7 +1705,8 @@ do_authenticated(struct passwd * pw) | |||
1684 | * by the client telling us, so we can equally well trust the client | 1705 | * by the client telling us, so we can equally well trust the client |
1685 | * not to request anything bogus.) | 1706 | * not to request anything bogus.) |
1686 | */ | 1707 | */ |
1687 | channel_permit_all_opens(); | 1708 | if (!no_port_forwarding_flag) |
1709 | channel_permit_all_opens(); | ||
1688 | 1710 | ||
1689 | /* | 1711 | /* |
1690 | * We stay in this loop until the client requests to execute a shell | 1712 | * We stay in this loop until the client requests to execute a shell |
@@ -1785,16 +1807,20 @@ do_authenticated(struct passwd * pw) | |||
1785 | 1807 | ||
1786 | /* Setup to always have a local .Xauthority. */ | 1808 | /* Setup to always have a local .Xauthority. */ |
1787 | xauthfile = xmalloc(MAXPATHLEN); | 1809 | xauthfile = xmalloc(MAXPATHLEN); |
1788 | snprintf(xauthfile, MAXPATHLEN, "/tmp/XauthXXXXXX"); | 1810 | strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); |
1789 | 1811 | temporarily_use_uid(pw->pw_uid); | |
1790 | if ((xauthfd = mkstemp(xauthfile)) != -1) { | 1812 | if (mkdtemp(xauthfile) == NULL) { |
1791 | fchown(xauthfd, pw->pw_uid, pw->pw_gid); | 1813 | restore_uid(); |
1792 | close(xauthfd); | 1814 | error("private X11 dir: mkdtemp %s failed: %s", |
1793 | fatal_add_cleanup(xauthfile_cleanup_proc, NULL); | 1815 | xauthfile, strerror(errno)); |
1794 | } else { | ||
1795 | xfree(xauthfile); | 1816 | xfree(xauthfile); |
1796 | xauthfile = NULL; | 1817 | xauthfile = NULL; |
1818 | goto fail; | ||
1797 | } | 1819 | } |
1820 | strlcat(xauthfile, "/cookies", MAXPATHLEN); | ||
1821 | open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); | ||
1822 | restore_uid(); | ||
1823 | fatal_add_cleanup(xauthfile_cleanup_proc, NULL); | ||
1798 | break; | 1824 | break; |
1799 | #else /* XAUTH_PATH */ | 1825 | #else /* XAUTH_PATH */ |
1800 | packet_send_debug("No xauth program; cannot forward with spoofing."); | 1826 | packet_send_debug("No xauth program; cannot forward with spoofing."); |
@@ -2026,6 +2052,7 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
2026 | const char *auth_data) | 2052 | const char *auth_data) |
2027 | { | 2053 | { |
2028 | int pid, fdout; | 2054 | int pid, fdout; |
2055 | int ptymaster; | ||
2029 | const char *hostname; | 2056 | const char *hostname; |
2030 | time_t last_login_time; | 2057 | time_t last_login_time; |
2031 | char buf[100], *time_string; | 2058 | char buf[100], *time_string; |
@@ -2174,11 +2201,16 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
2174 | */ | 2201 | */ |
2175 | fdout = dup(ptyfd); | 2202 | fdout = dup(ptyfd); |
2176 | if (fdout < 0) | 2203 | if (fdout < 0) |
2177 | packet_disconnect("dup failed: %.100s", strerror(errno)); | 2204 | packet_disconnect("dup #1 failed: %.100s", strerror(errno)); |
2205 | |||
2206 | /* we keep a reference to the pty master */ | ||
2207 | ptymaster = dup(ptyfd); | ||
2208 | if (ptymaster < 0) | ||
2209 | packet_disconnect("dup #2 failed: %.100s", strerror(errno)); | ||
2178 | 2210 | ||
2179 | /* Enter interactive session. */ | 2211 | /* Enter interactive session. */ |
2180 | server_loop(pid, ptyfd, fdout, -1); | 2212 | server_loop(pid, ptyfd, fdout, -1); |
2181 | /* server_loop has not closed ptyfd and fdout. */ | 2213 | /* server_loop _has_ closed ptyfd and fdout. */ |
2182 | 2214 | ||
2183 | /* Cancel the cleanup function. */ | 2215 | /* Cancel the cleanup function. */ |
2184 | fatal_remove_cleanup(pty_cleanup_proc, (void *) &cleanup_context); | 2216 | fatal_remove_cleanup(pty_cleanup_proc, (void *) &cleanup_context); |
@@ -2194,8 +2226,8 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
2194 | * the pty cleanup, so that another process doesn't get this pty | 2226 | * the pty cleanup, so that another process doesn't get this pty |
2195 | * while we're still cleaning up. | 2227 | * while we're still cleaning up. |
2196 | */ | 2228 | */ |
2197 | close(ptyfd); | 2229 | if (close(ptymaster) < 0) |
2198 | close(fdout); | 2230 | error("close(ptymaster): %s", strerror(errno)); |
2199 | } | 2231 | } |
2200 | 2232 | ||
2201 | /* | 2233 | /* |
@@ -2563,7 +2595,7 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
2563 | f = popen(XAUTH_PATH " -q -", "w"); | 2595 | f = popen(XAUTH_PATH " -q -", "w"); |
2564 | if (f) { | 2596 | if (f) { |
2565 | fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data); | 2597 | fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data); |
2566 | fclose(f); | 2598 | pclose(f); |
2567 | } else | 2599 | } else |
2568 | fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH); | 2600 | fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH); |
2569 | } | 2601 | } |