summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2007-06-12 16:16:35 +0000
committerColin Watson <cjwatson@debian.org>2007-06-12 16:16:35 +0000
commitb7e40fa9da0b5491534a429dadb321eab5a77558 (patch)
treebed1da11e9f829925797aa093e379fc0b5868ecd /ssh.c
parent4f84beedf1005e44ff33c854abd6b711ffc0adb7 (diff)
parent086ea76990b1e6287c24b6db74adffd4605eb3b0 (diff)
* New upstream release (closes: #395507, #397961, #420035). Important
changes not previously backported to 4.3p2: - 4.4/4.4p1 (http://www.openssh.org/txt/release-4.4): + On portable OpenSSH, fix a GSSAPI authentication abort that could be used to determine the validity of usernames on some platforms. + Implemented conditional configuration in sshd_config(5) using the "Match" directive. This allows some configuration options to be selectively overridden if specific criteria (based on user, group, hostname and/or address) are met. So far a useful subset of post-authentication options are supported and more are expected to be added in future releases. + Add support for Diffie-Hellman group exchange key agreement with a final hash of SHA256. + Added a "ForceCommand" directive to sshd_config(5). Similar to the command="..." option accepted in ~/.ssh/authorized_keys, this forces the execution of the specified command regardless of what the user requested. This is very useful in conjunction with the new "Match" option. + Add a "PermitOpen" directive to sshd_config(5). This mirrors the permitopen="..." authorized_keys option, allowing fine-grained control over the port-forwardings that a user is allowed to establish. + Add optional logging of transactions to sftp-server(8). + ssh(1) will now record port numbers for hosts stored in ~/.ssh/known_hosts when a non-standard port has been requested (closes: #50612). + Add an "ExitOnForwardFailure" option to cause ssh(1) to exit (with a non-zero exit code) when requested port forwardings could not be established. + Extend sshd_config(5) "SubSystem" declarations to allow the specification of command-line arguments. + Replacement of all integer overflow susceptible invocations of malloc(3) and realloc(3) with overflow-checking equivalents. + Many manpage fixes and improvements. + Add optional support for OpenSSL hardware accelerators (engines), enabled using the --with-ssl-engine configure option. + Tokens in configuration files may be double-quoted in order to contain spaces (closes: #319639). + Move a debug() call out of a SIGCHLD handler, fixing a hang when the session exits very quickly (closes: #307890). + Fix some incorrect buffer allocation calculations (closes: #410599). + ssh-add doesn't ask for a passphrase if key file permissions are too liberal (closes: #103677). + Likewise, ssh doesn't ask either (closes: #99675). - 4.6/4.6p1 (http://www.openssh.org/txt/release-4.6): + sshd now allows the enabling and disabling of authentication methods on a per user, group, host and network basis via the Match directive in sshd_config. + Fixed an inconsistent check for a terminal when displaying scp progress meter (closes: #257524). + Fix "hang on exit" when background processes are running at the time of exit on a ttyful/login session (closes: #88337). * Update to current GSSAPI patch from http://www.sxw.org.uk/computing/patches/openssh-4.6p1-gsskex-20070312.patch; install ChangeLog.gssapi.
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c147
1 files changed, 102 insertions, 45 deletions
diff --git a/ssh.c b/ssh.c
index a86d0e17b..c75decc1b 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.295 2007/01/03 03:01:40 stevesk Exp $ */
1/* 2/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -40,20 +41,46 @@
40 */ 41 */
41 42
42#include "includes.h" 43#include "includes.h"
43RCSID("$OpenBSD: ssh.c,v 1.257 2005/12/20 04:41:07 dtucker Exp $"); 44
45#include <sys/types.h>
46#ifdef HAVE_SYS_STAT_H
47# include <sys/stat.h>
48#endif
49#include <sys/resource.h>
50#include <sys/ioctl.h>
51#include <sys/socket.h>
52#include <sys/un.h>
53
54#include <ctype.h>
55#include <errno.h>
56#include <fcntl.h>
57#include <netdb.h>
58#ifdef HAVE_PATHS_H
59#include <paths.h>
60#endif
61#include <pwd.h>
62#include <signal.h>
63#include <stdarg.h>
64#include <stddef.h>
65#include <stdio.h>
66#include <stdlib.h>
67#include <string.h>
68#include <unistd.h>
69
70#include <netinet/in.h>
71#include <arpa/inet.h>
44 72
45#include <openssl/evp.h> 73#include <openssl/evp.h>
46#include <openssl/err.h> 74#include <openssl/err.h>
47 75
76#include "xmalloc.h"
48#include "ssh.h" 77#include "ssh.h"
49#include "ssh1.h" 78#include "ssh1.h"
50#include "ssh2.h" 79#include "ssh2.h"
51#include "compat.h" 80#include "compat.h"
52#include "cipher.h" 81#include "cipher.h"
53#include "xmalloc.h"
54#include "packet.h" 82#include "packet.h"
55#include "buffer.h" 83#include "buffer.h"
56#include "bufaux.h"
57#include "channels.h" 84#include "channels.h"
58#include "key.h" 85#include "key.h"
59#include "authfd.h" 86#include "authfd.h"
@@ -72,6 +99,7 @@ RCSID("$OpenBSD: ssh.c,v 1.257 2005/12/20 04:41:07 dtucker Exp $");
72#include "msg.h" 99#include "msg.h"
73#include "monitor_fdpass.h" 100#include "monitor_fdpass.h"
74#include "uidswap.h" 101#include "uidswap.h"
102#include "version.h"
75 103
76#ifdef SMARTCARD 104#ifdef SMARTCARD
77#include "scard.h" 105#include "scard.h"
@@ -162,7 +190,7 @@ usage(void)
162" [-i identity_file] [-L [bind_address:]port:host:hostport]\n" 190" [-i identity_file] [-L [bind_address:]port:host:hostport]\n"
163" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" 191" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
164" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" 192" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
165" [-w tunnel:tunnel] [user@]hostname [command]\n" 193" [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
166 ); 194 );
167 exit(255); 195 exit(255);
168} 196}
@@ -242,7 +270,7 @@ main(int ac, char **av)
242 /* Parse command-line arguments. */ 270 /* Parse command-line arguments. */
243 host = NULL; 271 host = NULL;
244 272
245again: 273 again:
246 while ((opt = getopt(ac, av, 274 while ((opt = getopt(ac, av,
247 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) { 275 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) {
248 switch (opt) { 276 switch (opt) {
@@ -594,7 +622,7 @@ again:
594 if (!read_config_file(config, host, &options, 0)) 622 if (!read_config_file(config, host, &options, 0))
595 fatal("Can't open user config file %.100s: " 623 fatal("Can't open user config file %.100s: "
596 "%.100s", config, strerror(errno)); 624 "%.100s", config, strerror(errno));
597 } else { 625 } else {
598 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, 626 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
599 _PATH_SSH_USER_CONFFILE); 627 _PATH_SSH_USER_CONFFILE);
600 (void)read_config_file(buf, host, &options, 1); 628 (void)read_config_file(buf, host, &options, 1);
@@ -624,7 +652,7 @@ again:
624 if (options.host_key_alias != NULL) { 652 if (options.host_key_alias != NULL) {
625 for (p = options.host_key_alias; *p; p++) 653 for (p = options.host_key_alias; *p; p++)
626 if (isupper(*p)) 654 if (isupper(*p))
627 *p = tolower(*p); 655 *p = (char)tolower(*p);
628 } 656 }
629 657
630 /* Get default port if port has not been set. */ 658 /* Get default port if port has not been set. */
@@ -641,11 +669,15 @@ again:
641 options.control_path = NULL; 669 options.control_path = NULL;
642 670
643 if (options.control_path != NULL) { 671 if (options.control_path != NULL) {
672 char thishost[NI_MAXHOST];
673
674 if (gethostname(thishost, sizeof(thishost)) == -1)
675 fatal("gethostname: %s", strerror(errno));
644 snprintf(buf, sizeof(buf), "%d", options.port); 676 snprintf(buf, sizeof(buf), "%d", options.port);
645 cp = tilde_expand_filename(options.control_path, 677 cp = tilde_expand_filename(options.control_path,
646 original_real_uid); 678 original_real_uid);
647 options.control_path = percent_expand(cp, "p", buf, "h", host, 679 options.control_path = percent_expand(cp, "p", buf, "h", host,
648 "r", options.user, (char *)NULL); 680 "r", options.user, "l", thishost, (char *)NULL);
649 xfree(cp); 681 xfree(cp);
650 } 682 }
651 if (mux_command != 0 && options.control_path == NULL) 683 if (mux_command != 0 && options.control_path == NULL)
@@ -678,16 +710,16 @@ again:
678 if (options.rhosts_rsa_authentication || 710 if (options.rhosts_rsa_authentication ||
679 options.hostbased_authentication) { 711 options.hostbased_authentication) {
680 sensitive_data.nkeys = 3; 712 sensitive_data.nkeys = 3;
681 sensitive_data.keys = xmalloc(sensitive_data.nkeys * 713 sensitive_data.keys = xcalloc(sensitive_data.nkeys,
682 sizeof(Key)); 714 sizeof(Key));
683 715
684 PRIV_START; 716 PRIV_START;
685 sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, 717 sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
686 _PATH_HOST_KEY_FILE, "", NULL); 718 _PATH_HOST_KEY_FILE, "", NULL, NULL);
687 sensitive_data.keys[1] = key_load_private_type(KEY_DSA, 719 sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
688 _PATH_HOST_DSA_KEY_FILE, "", NULL); 720 _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
689 sensitive_data.keys[2] = key_load_private_type(KEY_RSA, 721 sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
690 _PATH_HOST_RSA_KEY_FILE, "", NULL); 722 _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
691 PRIV_END; 723 PRIV_END;
692 724
693 if (options.hostbased_authentication == 1 && 725 if (options.hostbased_authentication == 1 &&
@@ -803,6 +835,8 @@ ssh_init_forwarding(void)
803 options.local_forwards[i].connect_port, 835 options.local_forwards[i].connect_port,
804 options.gateway_ports); 836 options.gateway_ports);
805 } 837 }
838 if (i > 0 && success != i && options.exit_on_forward_failure)
839 fatal("Could not request local forwarding.");
806 if (i > 0 && success == 0) 840 if (i > 0 && success == 0)
807 error("Could not request local forwarding."); 841 error("Could not request local forwarding.");
808 842
@@ -815,11 +849,17 @@ ssh_init_forwarding(void)
815 options.remote_forwards[i].listen_port, 849 options.remote_forwards[i].listen_port,
816 options.remote_forwards[i].connect_host, 850 options.remote_forwards[i].connect_host,
817 options.remote_forwards[i].connect_port); 851 options.remote_forwards[i].connect_port);
818 channel_request_remote_forwarding( 852 if (channel_request_remote_forwarding(
819 options.remote_forwards[i].listen_host, 853 options.remote_forwards[i].listen_host,
820 options.remote_forwards[i].listen_port, 854 options.remote_forwards[i].listen_port,
821 options.remote_forwards[i].connect_host, 855 options.remote_forwards[i].connect_host,
822 options.remote_forwards[i].connect_port); 856 options.remote_forwards[i].connect_port) < 0) {
857 if (options.exit_on_forward_failure)
858 fatal("Could not request remote forwarding.");
859 else
860 logit("Warning: Could not request remote "
861 "forwarding.");
862 }
823 } 863 }
824} 864}
825 865
@@ -880,10 +920,10 @@ ssh_session(void)
880 /* Store window size in the packet. */ 920 /* Store window size in the packet. */
881 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) 921 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
882 memset(&ws, 0, sizeof(ws)); 922 memset(&ws, 0, sizeof(ws));
883 packet_put_int(ws.ws_row); 923 packet_put_int((u_int)ws.ws_row);
884 packet_put_int(ws.ws_col); 924 packet_put_int((u_int)ws.ws_col);
885 packet_put_int(ws.ws_xpixel); 925 packet_put_int((u_int)ws.ws_xpixel);
886 packet_put_int(ws.ws_ypixel); 926 packet_put_int((u_int)ws.ws_ypixel);
887 927
888 /* Store tty modes in the packet. */ 928 /* Store tty modes in the packet. */
889 tty_make_modes(fileno(stdin), NULL); 929 tty_make_modes(fileno(stdin), NULL);
@@ -1001,9 +1041,16 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
1001 options.remote_forwards[i].listen_port, 1041 options.remote_forwards[i].listen_port,
1002 options.remote_forwards[i].connect_host, 1042 options.remote_forwards[i].connect_host,
1003 options.remote_forwards[i].connect_port); 1043 options.remote_forwards[i].connect_port);
1004 if (type == SSH2_MSG_REQUEST_FAILURE) 1044 if (type == SSH2_MSG_REQUEST_FAILURE) {
1005 logit("Warning: remote port forwarding failed for listen " 1045 if (options.exit_on_forward_failure)
1006 "port %d", options.remote_forwards[i].listen_port); 1046 fatal("Error: remote port forwarding failed for "
1047 "listen port %d",
1048 options.remote_forwards[i].listen_port);
1049 else
1050 logit("Warning: remote port forwarding failed for "
1051 "listen port %d",
1052 options.remote_forwards[i].listen_port);
1053 }
1007} 1054}
1008 1055
1009static void 1056static void
@@ -1032,7 +1079,7 @@ ssh_control_listener(void)
1032 fatal("%s socket(): %s", __func__, strerror(errno)); 1079 fatal("%s socket(): %s", __func__, strerror(errno));
1033 1080
1034 old_umask = umask(0177); 1081 old_umask = umask(0177);
1035 if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { 1082 if (bind(control_fd, (struct sockaddr *)&addr, addr_len) == -1) {
1036 control_fd = -1; 1083 control_fd = -1;
1037 if (errno == EINVAL || errno == EADDRINUSE) 1084 if (errno == EINVAL || errno == EADDRINUSE)
1038 fatal("ControlSocket %s already exists", 1085 fatal("ControlSocket %s already exists",
@@ -1184,15 +1231,16 @@ ssh_session2(void)
1184static void 1231static void
1185load_public_identity_files(void) 1232load_public_identity_files(void)
1186{ 1233{
1187 char *filename; 1234 char *filename, *cp, thishost[NI_MAXHOST];
1188 int i = 0; 1235 int i = 0;
1189 Key *public; 1236 Key *public;
1237 struct passwd *pw;
1190#ifdef SMARTCARD 1238#ifdef SMARTCARD
1191 Key **keys; 1239 Key **keys;
1192 1240
1193 if (options.smartcard_device != NULL && 1241 if (options.smartcard_device != NULL &&
1194 options.num_identity_files < SSH_MAX_IDENTITY_FILES && 1242 options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1195 (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) { 1243 (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
1196 int count = 0; 1244 int count = 0;
1197 for (i = 0; keys[i] != NULL; i++) { 1245 for (i = 0; keys[i] != NULL; i++) {
1198 count++; 1246 count++;
@@ -1210,9 +1258,18 @@ load_public_identity_files(void)
1210 xfree(keys); 1258 xfree(keys);
1211 } 1259 }
1212#endif /* SMARTCARD */ 1260#endif /* SMARTCARD */
1261 if ((pw = getpwuid(original_real_uid)) == NULL)
1262 fatal("load_public_identity_files: getpwuid failed");
1263 if (gethostname(thishost, sizeof(thishost)) == -1)
1264 fatal("load_public_identity_files: gethostname: %s",
1265 strerror(errno));
1213 for (; i < options.num_identity_files; i++) { 1266 for (; i < options.num_identity_files; i++) {
1214 filename = tilde_expand_filename(options.identity_files[i], 1267 cp = tilde_expand_filename(options.identity_files[i],
1215 original_real_uid); 1268 original_real_uid);
1269 filename = percent_expand(cp, "d", pw->pw_dir,
1270 "u", pw->pw_name, "l", thishost, "h", host,
1271 "r", options.user, (char *)NULL);
1272 xfree(cp);
1216 public = key_load_public(filename, NULL); 1273 public = key_load_public(filename, NULL);
1217 debug("identity file %s type %d", filename, 1274 debug("identity file %s type %d", filename,
1218 public ? public->type : -1); 1275 public ? public->type : -1);
@@ -1238,14 +1295,14 @@ control_client_sigrelay(int signo)
1238static int 1295static int
1239env_permitted(char *env) 1296env_permitted(char *env)
1240{ 1297{
1241 int i; 1298 int i, ret;
1242 char name[1024], *cp; 1299 char name[1024], *cp;
1243 1300
1244 strlcpy(name, env, sizeof(name)); 1301 if ((cp = strchr(env, '=')) == NULL || cp == env)
1245 if ((cp = strchr(name, '=')) == NULL)
1246 return (0); 1302 return (0);
1247 1303 ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
1248 *cp = '\0'; 1304 if (ret <= 0 || (size_t)ret >= sizeof(name))
1305 fatal("env_permitted: name '%.100s...' too long", env);
1249 1306
1250 for (i = 0; i < options.num_send_env; i++) 1307 for (i = 0; i < options.num_send_env; i++)
1251 if (match_pattern(name, options.send_env[i])) 1308 if (match_pattern(name, options.send_env[i]))
@@ -1290,29 +1347,29 @@ control_client(const char *path)
1290 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) 1347 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
1291 fatal("%s socket(): %s", __func__, strerror(errno)); 1348 fatal("%s socket(): %s", __func__, strerror(errno));
1292 1349
1293 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) { 1350 if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
1294 if (mux_command != SSHMUX_COMMAND_OPEN) { 1351 if (mux_command != SSHMUX_COMMAND_OPEN) {
1295 fatal("Control socket connect(%.100s): %s", path, 1352 fatal("Control socket connect(%.100s): %s", path,
1296 strerror(errno)); 1353 strerror(errno));
1297 } 1354 }
1298 if (errno == ENOENT) 1355 if (errno == ENOENT)
1299 debug("Control socket \"%.100s\" does not exist", path); 1356 debug("Control socket \"%.100s\" does not exist", path);
1300 else { 1357 else {
1301 error("Control socket connect(%.100s): %s", path, 1358 error("Control socket connect(%.100s): %s", path,
1302 strerror(errno)); 1359 strerror(errno));
1303 } 1360 }
1304 close(sock); 1361 close(sock);
1305 return; 1362 return;
1306 } 1363 }
1307 1364
1308 if (stdin_null_flag) { 1365 if (stdin_null_flag) {
1309 if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1) 1366 if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
1310 fatal("open(/dev/null): %s", strerror(errno)); 1367 fatal("open(/dev/null): %s", strerror(errno));
1311 if (dup2(fd, STDIN_FILENO) == -1) 1368 if (dup2(fd, STDIN_FILENO) == -1)
1312 fatal("dup2: %s", strerror(errno)); 1369 fatal("dup2: %s", strerror(errno));
1313 if (fd > STDERR_FILENO) 1370 if (fd > STDERR_FILENO)
1314 close(fd); 1371 close(fd);
1315 } 1372 }
1316 1373
1317 term = getenv("TERM"); 1374 term = getenv("TERM");
1318 1375