=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh.c,v retrieving revision 1.147 retrieving revision 1.147.2.3 diff -u -r1.147 -r1.147.2.3 --- src/usr.bin/ssh/ssh.c 2001/10/08 19:05:05 1.147 +++ src/usr.bin/ssh/ssh.c 2002/05/17 00:03:24 1.147.2.3 @@ -13,6 +13,7 @@ * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 1999 Niels Provos. All rights reserved. + * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Modified to work with SSL by Niels Provos * in Canada (German citizen). @@ -39,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.147 2001/10/08 19:05:05 markus Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.147.2.3 2002/05/17 00:03:24 miod Exp $"); #include #include @@ -70,7 +71,6 @@ #include "sshtty.h" #ifdef SMARTCARD -#include #include "scard.h" #endif @@ -123,14 +123,6 @@ /* socket address the host resolves to */ struct sockaddr_storage hostaddr; -/* - * Flag to indicate that we have received a window change signal which has - * not yet been processed. This will cause a message indicating the new - * window size to be sent to the server a little later. This is volatile - * because this is updated in a signal handler. - */ -volatile int received_window_change_signal = 0; - /* Private host keys. */ struct { Key **keys; @@ -146,6 +138,9 @@ /* Should we execute a command or invoke a subsystem? */ int subsystem_flag = 0; +/* # of replies received for global requests */ +static int client_global_request_id = 0; + /* Prints a help message to the user. This function never returns. */ static void @@ -470,7 +465,7 @@ /* NOTREACHED */ } if ((fwd_port = a2port(sfwd_port)) == 0 || - (fwd_host_port = a2port(sfwd_host_port)) == 0) { + (fwd_host_port = a2port(sfwd_host_port)) == 0) { fprintf(stderr, "Bad forwarding port(s) '%s'\n", optarg); exit(1); @@ -480,7 +475,7 @@ fwd_host_port); else if (opt == 'R') add_remote_forward(&options, fwd_port, buf, - fwd_host_port); + fwd_host_port); break; case 'D': @@ -740,6 +735,8 @@ options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2, original_real_uid); + signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ + /* Log into the remote system. This never returns if the login fails. */ ssh_login(sensitive_data.keys, sensitive_data.nkeys, host, (struct sockaddr *)&hostaddr, pw); @@ -773,19 +770,36 @@ } static void -x11_get_proto(char *proto, int proto_len, char *data, int data_len) +x11_get_proto(char **_proto, char **_data) { char line[512]; + static char proto[512], data[512]; FILE *f; int got_data = 0, i; + char *display; - if (options.xauth_location) { + *_proto = proto; + *_data = data; + proto[0] = data[0] = '\0'; + if (options.xauth_location && (display = getenv("DISPLAY"))) { /* Try to get Xauthority information for the display. */ - snprintf(line, sizeof line, "%.100s list %.200s 2>" _PATH_DEVNULL, - options.xauth_location, getenv("DISPLAY")); + if (strncmp(display, "localhost:", 10) == 0) + /* + * Handle FamilyLocal case where $DISPLAY does + * not match an authorization entry. For this we + * just try "xauth list unix:displaynum.screennum". + * XXX: "localhost" match to determine FamilyLocal + * is not perfect. + */ + snprintf(line, sizeof line, "%.100s list unix:%s 2>" + _PATH_DEVNULL, options.xauth_location, display+10); + else + snprintf(line, sizeof line, "%.100s list %.200s 2>" + _PATH_DEVNULL, options.xauth_location, display); + debug2("x11_get_proto %s", line); f = popen(line, "r"); if (f && fgets(line, sizeof(line), f) && - sscanf(line, "%*s %s %s", proto, data) == 2) + sscanf(line, "%*s %511s %511s", proto, data) == 2) got_data = 1; if (f) pclose(f); @@ -801,11 +815,11 @@ if (!got_data) { u_int32_t rand = 0; - strlcpy(proto, "MIT-MAGIC-COOKIE-1", proto_len); + strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto); for (i = 0; i < 16; i++) { if (i % 4 == 0) rand = arc4random(); - snprintf(data + 2 * i, data_len - 2 * i, "%02x", rand & 0xff); + snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff); rand >>= 8; } } @@ -823,7 +837,7 @@ options.local_forwards[i].port, options.local_forwards[i].host, options.local_forwards[i].host_port); - success += channel_request_local_forwarding( + success += channel_setup_local_fwd_listener( options.local_forwards[i].port, options.local_forwards[i].host, options.local_forwards[i].host_port, @@ -862,7 +876,6 @@ ssh_session(void) { int type; - int plen; int interactive = 0; int have_tty = 0; struct winsize ws; @@ -880,7 +893,7 @@ packet_put_int(options.compression_level); packet_send(); packet_write_wait(); - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) packet_start_compression(options.compression_level); else if (type == SSH_SMSG_FAILURE) @@ -918,7 +931,7 @@ packet_write_wait(); /* Read response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { interactive = 1; have_tty = 1; @@ -929,15 +942,15 @@ } /* Request X11 forwarding if enabled and DISPLAY is set. */ if (options.forward_x11 && getenv("DISPLAY") != NULL) { - char proto[512], data[512]; + char *proto, *data; /* Get reasonable local authentication information. */ - x11_get_proto(proto, sizeof proto, data, sizeof data); + x11_get_proto(&proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); x11_request_forwarding_with_spoofing(0, proto, data); /* Read response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { interactive = 1; } else if (type == SSH_SMSG_FAILURE) { @@ -957,8 +970,8 @@ auth_request_forwarding(); /* Read response from the server. */ - type = packet_read(&plen); - packet_integrity_check(plen, 0, type); + type = packet_read(); + packet_check_eom(); if (type != SSH_SMSG_SUCCESS) log("Warning: Remote host denied authentication agent forwarding."); } @@ -979,7 +992,7 @@ int len = buffer_len(&command); if (len > 900) len = 900; - debug("Sending command: %.*s", len, buffer_ptr(&command)); + debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); packet_start(SSH_CMSG_EXEC_CMD); packet_put_string(buffer_ptr(&command), buffer_len(&command)); packet_send(); @@ -997,7 +1010,7 @@ } static void -client_subsystem_reply(int type, int plen, void *ctxt) +client_subsystem_reply(int type, u_int32_t seq, void *ctxt) { int id, len; @@ -1005,12 +1018,33 @@ len = buffer_len(&command); if (len > 900) len = 900; - packet_done(); + packet_check_eom(); if (type == SSH2_MSG_CHANNEL_FAILURE) fatal("Request for subsystem '%.*s' failed on channel %d", - len, buffer_ptr(&command), id); + len, (u_char *)buffer_ptr(&command), id); } +void +client_global_request_reply(int type, u_int32_t seq, void *ctxt) +{ + int i; + + i = client_global_request_id++; + if (i >= options.num_remote_forwards) { + debug("client_global_request_reply: too many replies %d > %d", + i, options.num_remote_forwards); + return; + } + debug("remote forward %s for: listen %d, connect %s:%d", + type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", + options.remote_forwards[i].port, + options.remote_forwards[i].host, + options.remote_forwards[i].host_port); + if (type == SSH2_MSG_REQUEST_FAILURE) + log("Warning: remote port forwarding failed for listen port %d", + options.remote_forwards[i].port); +} + /* request pty/x11/agent/tcpfwd/shell for channel */ static void ssh_session2_setup(int id, void *arg) @@ -1045,9 +1079,9 @@ } if (options.forward_x11 && getenv("DISPLAY") != NULL) { - char proto[512], data[512]; + char *proto, *data; /* Get reasonable local authentication information. */ - x11_get_proto(proto, sizeof proto, data, sizeof data); + x11_get_proto(&proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); x11_request_forwarding_with_spoofing(id, proto, data); @@ -1067,24 +1101,23 @@ if (len > 900) len = 900; if (subsystem_flag) { - debug("Sending subsystem: %.*s", len, buffer_ptr(&command)); + debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command)); channel_request_start(id, "subsystem", /*want reply*/ 1); /* register callback for reply */ /* XXX we asume that client_loop has already been called */ dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply); dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply); } else { - debug("Sending command: %.*s", len, buffer_ptr(&command)); + debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); channel_request_start(id, "exec", 0); } packet_put_string(buffer_ptr(&command), buffer_len(&command)); packet_send(); } else { - channel_request(id, "shell", 0); + channel_request_start(id, "shell", 0); + packet_send(); } - /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */ - /* register different callback, etc. XXX */ packet_set_interactive(interactive); } @@ -1116,24 +1149,20 @@ window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; - if (!tty_flag) { - window *= 2; - packetmax *=2; + if (tty_flag) { + window >>= 1; + packetmax >>= 1; } c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"), /*nonblock*/0); - if (c == NULL) - fatal("ssh_session2_open: channel_new failed"); debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); if (!no_shell_flag) - channel_register_callback(c->self, - SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, - ssh_session2_setup, (void *)0); + channel_register_confirm(c->self, ssh_session2_setup); return c->self; } @@ -1162,40 +1191,29 @@ load_public_identity_files(void) { char *filename; - Key *public; int i = 0; - + Key *public; #ifdef SMARTCARD - if (options.smartcard_device != NULL && - options.num_identity_files + 1 < SSH_MAX_IDENTITY_FILES && - (public = sc_get_key(options.smartcard_device)) != NULL ) { - Key *new; + Key **keys; - if (options.num_identity_files + 2 > SSH_MAX_IDENTITY_FILES) - options.num_identity_files = SSH_MAX_IDENTITY_FILES - 2; - memmove(&options.identity_files[2], &options.identity_files[0], - sizeof(char *) * options.num_identity_files); - options.num_identity_files += 2; - i = 2; - - /* XXX ssh1 vs ssh2 */ - new = key_new(KEY_RSA); - new->flags = KEY_FLAG_EXT; - BN_copy(new->rsa->n, public->rsa->n); - BN_copy(new->rsa->e, public->rsa->e); - RSA_set_method(new->rsa, sc_get_engine()); - options.identity_keys[0] = new; - options.identity_files[0] = xstrdup("smartcard rsa key");; - - new = key_new(KEY_RSA1); - new->flags = KEY_FLAG_EXT; - BN_copy(new->rsa->n, public->rsa->n); - BN_copy(new->rsa->e, public->rsa->e); - RSA_set_method(new->rsa, sc_get_engine()); - options.identity_keys[1] = new; - options.identity_files[1] = xstrdup("smartcard rsa1 key"); - - key_free(public); + if (options.smartcard_device != NULL && + options.num_identity_files < SSH_MAX_IDENTITY_FILES && + (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) { + int count = 0; + for (i = 0; keys[i] != NULL; i++) { + count++; + memmove(&options.identity_files[1], &options.identity_files[0], + sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); + memmove(&options.identity_keys[1], &options.identity_keys[0], + sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); + options.num_identity_files++; + options.identity_keys[0] = keys[i]; + options.identity_files[0] = xstrdup("smartcard key");; + } + if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) + options.num_identity_files = SSH_MAX_IDENTITY_FILES; + i = count; + xfree(keys); } #endif /* SMARTCARD */ for (; i < options.num_identity_files; i++) {