diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | ssh.c | 20 | ||||
-rw-r--r-- | sshconnect.c | 47 | ||||
-rw-r--r-- | sshconnect.h | 20 |
4 files changed, 51 insertions, 44 deletions
@@ -29,6 +29,12 @@ | |||
29 | [channels.c channels.h session.c] | 29 | [channels.c channels.h session.c] |
30 | move creation of agent socket to session.c; no need for uidswapping | 30 | move creation of agent socket to session.c; no need for uidswapping |
31 | in channel.c. | 31 | in channel.c. |
32 | - markus@cvs.openbsd.org 2002/06/11 04:14:26 | ||
33 | [ssh.c sshconnect.c sshconnect.h] | ||
34 | no longer use uidswap.[ch] from the ssh client | ||
35 | run less code with euid==0 if ssh is installed setuid root | ||
36 | just switch the euid, don't switch the complete set of groups | ||
37 | (this is only needed by sshd). ok provos@ | ||
32 | 38 | ||
33 | 20020609 | 39 | 20020609 |
34 | - (bal) OpenBSD CVS Sync | 40 | - (bal) OpenBSD CVS Sync |
@@ -894,4 +900,4 @@ | |||
894 | - (stevesk) entropy.c: typo in debug message | 900 | - (stevesk) entropy.c: typo in debug message |
895 | - (djm) ssh-keygen -i needs seeded RNG; report from markus@ | 901 | - (djm) ssh-keygen -i needs seeded RNG; report from markus@ |
896 | 902 | ||
897 | $Id: ChangeLog,v 1.2207 2002/06/11 15:59:02 mouring Exp $ | 903 | $Id: ChangeLog,v 1.2208 2002/06/11 16:37:51 mouring Exp $ |
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: ssh.c,v 1.176 2002/06/08 05:17:01 markus Exp $"); | 43 | RCSID("$OpenBSD: ssh.c,v 1.177 2002/06/11 04:14:26 markus Exp $"); |
44 | 44 | ||
45 | #include <openssl/evp.h> | 45 | #include <openssl/evp.h> |
46 | #include <openssl/err.h> | 46 | #include <openssl/err.h> |
@@ -53,7 +53,6 @@ RCSID("$OpenBSD: ssh.c,v 1.176 2002/06/08 05:17:01 markus Exp $"); | |||
53 | #include "xmalloc.h" | 53 | #include "xmalloc.h" |
54 | #include "packet.h" | 54 | #include "packet.h" |
55 | #include "buffer.h" | 55 | #include "buffer.h" |
56 | #include "uidswap.h" | ||
57 | #include "channels.h" | 56 | #include "channels.h" |
58 | #include "key.h" | 57 | #include "key.h" |
59 | #include "authfd.h" | 58 | #include "authfd.h" |
@@ -136,6 +135,7 @@ Sensitive sensitive_data; | |||
136 | 135 | ||
137 | /* Original real UID. */ | 136 | /* Original real UID. */ |
138 | uid_t original_real_uid; | 137 | uid_t original_real_uid; |
138 | uid_t original_effective_uid; | ||
139 | 139 | ||
140 | /* command to be executed */ | 140 | /* command to be executed */ |
141 | Buffer command; | 141 | Buffer command; |
@@ -217,7 +217,6 @@ main(int ac, char **av) | |||
217 | struct stat st; | 217 | struct stat st; |
218 | struct passwd *pw; | 218 | struct passwd *pw; |
219 | int dummy; | 219 | int dummy; |
220 | uid_t original_effective_uid; | ||
221 | extern int optind, optreset; | 220 | extern int optind, optreset; |
222 | extern char *optarg; | 221 | extern char *optarg; |
223 | 222 | ||
@@ -256,7 +255,7 @@ main(int ac, char **av) | |||
256 | * them when the port has been created (actually, when the connection | 255 | * them when the port has been created (actually, when the connection |
257 | * has been made, as we may need to create the port several times). | 256 | * has been made, as we may need to create the port several times). |
258 | */ | 257 | */ |
259 | temporarily_use_uid(pw); | 258 | PRIV_END; |
260 | 259 | ||
261 | /* | 260 | /* |
262 | * Set our umask to something reasonable, as some files are created | 261 | * Set our umask to something reasonable, as some files are created |
@@ -612,15 +611,12 @@ again: | |||
612 | "originating port will not be trusted."); | 611 | "originating port will not be trusted."); |
613 | options.rhosts_authentication = 0; | 612 | options.rhosts_authentication = 0; |
614 | } | 613 | } |
615 | /* Restore our superuser privileges. */ | ||
616 | restore_uid(); | ||
617 | |||
618 | /* Open a connection to the remote host. */ | 614 | /* Open a connection to the remote host. */ |
619 | 615 | ||
620 | cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6, | 616 | cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6, |
621 | options.connection_attempts, | 617 | options.connection_attempts, |
622 | original_effective_uid != 0 || !options.use_privileged_port, | 618 | original_effective_uid == 0 && options.use_privileged_port, |
623 | pw, options.proxy_command); | 619 | options.proxy_command); |
624 | 620 | ||
625 | /* | 621 | /* |
626 | * If we successfully made the connection, load the host private key | 622 | * If we successfully made the connection, load the host private key |
@@ -637,12 +633,15 @@ again: | |||
637 | options.hostbased_authentication)) { | 633 | options.hostbased_authentication)) { |
638 | sensitive_data.nkeys = 3; | 634 | sensitive_data.nkeys = 3; |
639 | sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key)); | 635 | sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key)); |
636 | |||
637 | PRIV_START; | ||
640 | sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, | 638 | sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, |
641 | _PATH_HOST_KEY_FILE, "", NULL); | 639 | _PATH_HOST_KEY_FILE, "", NULL); |
642 | sensitive_data.keys[1] = key_load_private_type(KEY_DSA, | 640 | sensitive_data.keys[1] = key_load_private_type(KEY_DSA, |
643 | _PATH_HOST_DSA_KEY_FILE, "", NULL); | 641 | _PATH_HOST_DSA_KEY_FILE, "", NULL); |
644 | sensitive_data.keys[2] = key_load_private_type(KEY_RSA, | 642 | sensitive_data.keys[2] = key_load_private_type(KEY_RSA, |
645 | _PATH_HOST_RSA_KEY_FILE, "", NULL); | 643 | _PATH_HOST_RSA_KEY_FILE, "", NULL); |
644 | PRIV_END; | ||
646 | 645 | ||
647 | if (sensitive_data.keys[0] == NULL && | 646 | if (sensitive_data.keys[0] == NULL && |
648 | sensitive_data.keys[1] == NULL && | 647 | sensitive_data.keys[1] == NULL && |
@@ -661,7 +660,8 @@ again: | |||
661 | * user's home directory if it happens to be on a NFS volume where | 660 | * user's home directory if it happens to be on a NFS volume where |
662 | * root is mapped to nobody. | 661 | * root is mapped to nobody. |
663 | */ | 662 | */ |
664 | permanently_set_uid(pw); | 663 | seteuid(original_real_uid); |
664 | setuid(original_real_uid); | ||
665 | 665 | ||
666 | /* | 666 | /* |
667 | * Now that we are back to our own permissions, create ~/.ssh | 667 | * Now that we are back to our own permissions, create ~/.ssh |
diff --git a/sshconnect.c b/sshconnect.c index 651e3fcf4..3a93a4fbb 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -13,7 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include "includes.h" | 15 | #include "includes.h" |
16 | RCSID("$OpenBSD: sshconnect.c,v 1.123 2002/06/09 22:17:21 itojun Exp $"); | 16 | RCSID("$OpenBSD: sshconnect.c,v 1.124 2002/06/11 04:14:26 markus Exp $"); |
17 | 17 | ||
18 | #include <openssl/bn.h> | 18 | #include <openssl/bn.h> |
19 | 19 | ||
@@ -36,8 +36,11 @@ RCSID("$OpenBSD: sshconnect.c,v 1.123 2002/06/09 22:17:21 itojun Exp $"); | |||
36 | char *client_version_string = NULL; | 36 | char *client_version_string = NULL; |
37 | char *server_version_string = NULL; | 37 | char *server_version_string = NULL; |
38 | 38 | ||
39 | /* import */ | ||
39 | extern Options options; | 40 | extern Options options; |
40 | extern char *__progname; | 41 | extern char *__progname; |
42 | extern uid_t original_real_uid; | ||
43 | extern uid_t original_effective_uid; | ||
41 | 44 | ||
42 | #ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ | 45 | #ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ |
43 | #define INET6_ADDRSTRLEN 46 | 46 | #define INET6_ADDRSTRLEN 46 |
@@ -58,8 +61,7 @@ sockaddr_ntop(struct sockaddr *sa, socklen_t salen) | |||
58 | * Connect to the given ssh server using a proxy command. | 61 | * Connect to the given ssh server using a proxy command. |
59 | */ | 62 | */ |
60 | static int | 63 | static int |
61 | ssh_proxy_connect(const char *host, u_short port, struct passwd *pw, | 64 | ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) |
62 | const char *proxy_command) | ||
63 | { | 65 | { |
64 | Buffer command; | 66 | Buffer command; |
65 | const char *cp; | 67 | const char *cp; |
@@ -109,7 +111,8 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw, | |||
109 | char *argv[10]; | 111 | char *argv[10]; |
110 | 112 | ||
111 | /* Child. Permanently give up superuser privileges. */ | 113 | /* Child. Permanently give up superuser privileges. */ |
112 | permanently_set_uid(pw); | 114 | seteuid(original_real_uid); |
115 | setuid(original_real_uid); | ||
113 | 116 | ||
114 | /* Redirect stdin and stdout. */ | 117 | /* Redirect stdin and stdout. */ |
115 | close(pin[1]); | 118 | close(pin[1]); |
@@ -159,7 +162,7 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw, | |||
159 | * Creates a (possibly privileged) socket for use as the ssh connection. | 162 | * Creates a (possibly privileged) socket for use as the ssh connection. |
160 | */ | 163 | */ |
161 | static int | 164 | static int |
162 | ssh_create_socket(struct passwd *pw, int privileged, int family) | 165 | ssh_create_socket(int privileged, int family) |
163 | { | 166 | { |
164 | int sock, gaierr; | 167 | int sock, gaierr; |
165 | struct addrinfo hints, *res; | 168 | struct addrinfo hints, *res; |
@@ -170,22 +173,18 @@ ssh_create_socket(struct passwd *pw, int privileged, int family) | |||
170 | */ | 173 | */ |
171 | if (privileged) { | 174 | if (privileged) { |
172 | int p = IPPORT_RESERVED - 1; | 175 | int p = IPPORT_RESERVED - 1; |
176 | PRIV_START; | ||
173 | sock = rresvport_af(&p, family); | 177 | sock = rresvport_af(&p, family); |
178 | PRIV_END; | ||
174 | if (sock < 0) | 179 | if (sock < 0) |
175 | error("rresvport: af=%d %.100s", family, strerror(errno)); | 180 | error("rresvport: af=%d %.100s", family, strerror(errno)); |
176 | else | 181 | else |
177 | debug("Allocated local port %d.", p); | 182 | debug("Allocated local port %d.", p); |
178 | return sock; | 183 | return sock; |
179 | } | 184 | } |
180 | /* | ||
181 | * Just create an ordinary socket on arbitrary port. We use | ||
182 | * the user's uid to create the socket. | ||
183 | */ | ||
184 | temporarily_use_uid(pw); | ||
185 | sock = socket(family, SOCK_STREAM, 0); | 185 | sock = socket(family, SOCK_STREAM, 0); |
186 | if (sock < 0) | 186 | if (sock < 0) |
187 | error("socket: %.100s", strerror(errno)); | 187 | error("socket: %.100s", strerror(errno)); |
188 | restore_uid(); | ||
189 | 188 | ||
190 | /* Bind the socket to an alternative local IP address */ | 189 | /* Bind the socket to an alternative local IP address */ |
191 | if (options.bind_address == NULL) | 190 | if (options.bind_address == NULL) |
@@ -215,9 +214,9 @@ ssh_create_socket(struct passwd *pw, int privileged, int family) | |||
215 | /* | 214 | /* |
216 | * Opens a TCP/IP connection to the remote server on the given host. | 215 | * Opens a TCP/IP connection to the remote server on the given host. |
217 | * The address of the remote host will be returned in hostaddr. | 216 | * The address of the remote host will be returned in hostaddr. |
218 | * If port is 0, the default port will be used. If anonymous is zero, | 217 | * If port is 0, the default port will be used. If needpriv is true, |
219 | * a privileged port will be allocated to make the connection. | 218 | * a privileged port will be allocated to make the connection. |
220 | * This requires super-user privileges if anonymous is false. | 219 | * This requires super-user privileges if needpriv is true. |
221 | * Connection_attempts specifies the maximum number of tries (one per | 220 | * Connection_attempts specifies the maximum number of tries (one per |
222 | * second). If proxy_command is non-NULL, it specifies the command (with %h | 221 | * second). If proxy_command is non-NULL, it specifies the command (with %h |
223 | * and %p substituted for host and port, respectively) to use to contact | 222 | * and %p substituted for host and port, respectively) to use to contact |
@@ -232,7 +231,7 @@ ssh_create_socket(struct passwd *pw, int privileged, int family) | |||
232 | int | 231 | int |
233 | ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | 232 | ssh_connect(const char *host, struct sockaddr_storage * hostaddr, |
234 | u_short port, int family, int connection_attempts, | 233 | u_short port, int family, int connection_attempts, |
235 | int anonymous, struct passwd *pw, const char *proxy_command) | 234 | int needpriv, const char *proxy_command) |
236 | { | 235 | { |
237 | int gaierr; | 236 | int gaierr; |
238 | int on = 1; | 237 | int on = 1; |
@@ -248,8 +247,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
248 | */ | 247 | */ |
249 | int full_failure = 1; | 248 | int full_failure = 1; |
250 | 249 | ||
251 | debug("ssh_connect: getuid %u geteuid %u anon %d", | 250 | debug("ssh_connect: needpriv %d", needpriv); |
252 | (u_int) getuid(), (u_int) geteuid(), anonymous); | ||
253 | 251 | ||
254 | /* Get default port if port has not been set. */ | 252 | /* Get default port if port has not been set. */ |
255 | if (port == 0) { | 253 | if (port == 0) { |
@@ -261,7 +259,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
261 | } | 259 | } |
262 | /* If a proxy command is given, connect using it. */ | 260 | /* If a proxy command is given, connect using it. */ |
263 | if (proxy_command != NULL) | 261 | if (proxy_command != NULL) |
264 | return ssh_proxy_connect(host, port, pw, proxy_command); | 262 | return ssh_proxy_connect(host, port, proxy_command); |
265 | 263 | ||
266 | /* No proxy command. */ | 264 | /* No proxy command. */ |
267 | 265 | ||
@@ -297,26 +295,14 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
297 | host, ntop, strport); | 295 | host, ntop, strport); |
298 | 296 | ||
299 | /* Create a socket for connecting. */ | 297 | /* Create a socket for connecting. */ |
300 | sock = ssh_create_socket(pw, | 298 | sock = ssh_create_socket(needpriv, ai->ai_family); |
301 | #ifdef HAVE_CYGWIN | ||
302 | !anonymous, | ||
303 | #else | ||
304 | !anonymous && geteuid() == 0, | ||
305 | #endif | ||
306 | ai->ai_family); | ||
307 | if (sock < 0) | 299 | if (sock < 0) |
308 | /* Any error is already output */ | 300 | /* Any error is already output */ |
309 | continue; | 301 | continue; |
310 | 302 | ||
311 | /* Connect to the host. We use the user's uid in the | ||
312 | * hope that it will help with tcp_wrappers showing | ||
313 | * the remote uid as root. | ||
314 | */ | ||
315 | temporarily_use_uid(pw); | ||
316 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { | 303 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { |
317 | /* Successful connection. */ | 304 | /* Successful connection. */ |
318 | memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); | 305 | memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); |
319 | restore_uid(); | ||
320 | break; | 306 | break; |
321 | } else { | 307 | } else { |
322 | if (errno == ECONNREFUSED) | 308 | if (errno == ECONNREFUSED) |
@@ -324,7 +310,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
324 | log("ssh: connect to address %s port %s: %s", | 310 | log("ssh: connect to address %s port %s: %s", |
325 | sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), | 311 | sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), |
326 | strport, strerror(errno)); | 312 | strport, strerror(errno)); |
327 | restore_uid(); | ||
328 | /* | 313 | /* |
329 | * Close the failed socket; there appear to | 314 | * Close the failed socket; there appear to |
330 | * be some problems when reusing a socket for | 315 | * be some problems when reusing a socket for |
diff --git a/sshconnect.h b/sshconnect.h index aeb2e51a5..48148833f 100644 --- a/sshconnect.h +++ b/sshconnect.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.h,v 1.15 2002/06/09 13:32:01 markus Exp $ */ | 1 | /* $OpenBSD: sshconnect.h,v 1.16 2002/06/11 04:14:26 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -35,7 +35,7 @@ struct Sensitive { | |||
35 | 35 | ||
36 | int | 36 | int |
37 | ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int, | 37 | ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int, |
38 | int, struct passwd *, const char *); | 38 | int, const char *); |
39 | 39 | ||
40 | void | 40 | void |
41 | ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *); | 41 | ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *); |
@@ -50,4 +50,20 @@ void ssh_userauth2(const char *, const char *, char *, Sensitive *); | |||
50 | 50 | ||
51 | void ssh_put_password(char *); | 51 | void ssh_put_password(char *); |
52 | 52 | ||
53 | |||
54 | /* | ||
55 | * Macros to raise/lower permissions. | ||
56 | */ | ||
57 | #define PRIV_START do { \ | ||
58 | int save_errno = errno; \ | ||
59 | (void)seteuid(original_effective_uid); \ | ||
60 | errno = save_errno; \ | ||
61 | } while (0) | ||
62 | |||
63 | #define PRIV_END do { \ | ||
64 | int save_errno = errno; \ | ||
65 | (void)seteuid(original_real_uid); \ | ||
66 | errno = save_errno; \ | ||
67 | } while (0) | ||
68 | |||
53 | #endif | 69 | #endif |