From: damien Date: Mon, 6 Dec 1999 00:47:28 +0000 (+0000) Subject: - Merged OpenBSD CVS changes: X-Git-Tag: V_1_2_PRE16~18 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/57112b5a9a930e993041c62b62c25b54ac4b03f4 - Merged OpenBSD CVS changes: - [auth-krb4.c auth-passwd.c auth-skey.c ssh. move skey-auth from auth-passwd.c to auth-s - [auth-rsa.c] warn only about mismatch if key is _used_ warn about keysize-mismatch with log() not channels.c readconf.c readconf.h ssh.c ssh. ports are u_short - [hostfile.c] indent, shorter warning - [nchan.c] use error() for internal errors - [packet.c] set loglevel for SSH_MSG_DISCONNECT to log( serverloop.c indent - [ssh-add.1 ssh-add.c ssh.h] document , reasonable default - [ssh.1] CheckHostIP is not available for connects v - [sshconnect.c] typo easier to read client code for passwd and s turn of checkhostip for proxy connects, sin --- diff --git a/ChangeLog b/ChangeLog index 69b5688d..dc16db03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,29 @@ 19991204 - Small cleanup of PAM code in sshd.c + - Merged OpenBSD CVS changes: + - [auth-krb4.c auth-passwd.c auth-skey.c ssh.h] + move skey-auth from auth-passwd.c to auth-skey.c, same for krb4 + - [auth-rsa.c] + warn only about mismatch if key is _used_ + warn about keysize-mismatch with log() not error() + channels.c readconf.c readconf.h ssh.c ssh.h sshconnect.c + ports are u_short + - [hostfile.c] + indent, shorter warning + - [nchan.c] + use error() for internal errors + - [packet.c] + set loglevel for SSH_MSG_DISCONNECT to log(), not fatal() + serverloop.c + indent + - [ssh-add.1 ssh-add.c ssh.h] + document $SSH_ASKPASS, reasonable default + - [ssh.1] + CheckHostIP is not available for connects via proxy command + - [sshconnect.c] + typo + easier to read client code for passwd and skey auth + turn of checkhostip for proxy connects, since we don't know the remote ip 19991126 - Add definition for __P() diff --git a/auth-krb4.c b/auth-krb4.c index 9f99533b..fb0e20ce 100644 --- a/auth-krb4.c +++ b/auth-krb4.c @@ -7,10 +7,123 @@ #include "packet.h" #include "xmalloc.h" #include "ssh.h" +#include "servconf.h" #ifdef KRB4 char *ticket = NULL; +extern ServerOptions options; + +/* + * try krb4 authentication, + * return 1 on success, 0 on failure, -1 if krb4 is not available + */ + +int +auth_krb4_password(struct passwd * pw, const char *password) +{ + AUTH_DAT adata; + KTEXT_ST tkt; + struct hostent *hp; + unsigned long faddr; + char localhost[MAXHOSTNAMELEN]; + char phost[INST_SZ]; + char realm[REALM_SZ]; + int r; + + /* + * Try Kerberos password authentication only for non-root + * users and only if Kerberos is installed. + */ + if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) { + + /* Set up our ticket file. */ + if (!krb4_init(pw->pw_uid)) { + log("Couldn't initialize Kerberos ticket file for %s!", + pw->pw_name); + goto kerberos_auth_failure; + } + /* Try to get TGT using our password. */ + r = krb_get_pw_in_tkt((char *) pw->pw_name, "", + realm, "krbtgt", realm, + DEFAULT_TKT_LIFE, (char *) password); + if (r != INTK_OK) { + packet_send_debug("Kerberos V4 password " + "authentication for %s failed: %s", + pw->pw_name, krb_err_txt[r]); + goto kerberos_auth_failure; + } + /* Successful authentication. */ + chown(tkt_string(), pw->pw_uid, pw->pw_gid); + + /* + * Now that we have a TGT, try to get a local + * "rcmd" ticket to ensure that we are not talking + * to a bogus Kerberos server. + */ + (void) gethostname(localhost, sizeof(localhost)); + (void) strlcpy(phost, (char *) krb_get_phost(localhost), + INST_SZ); + r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33); + + if (r == KSUCCESS) { + if (!(hp = gethostbyname(localhost))) { + log("Couldn't get local host address!"); + goto kerberos_auth_failure; + } + memmove((void *) &faddr, (void *) hp->h_addr, + sizeof(faddr)); + + /* Verify our "rcmd" ticket. */ + r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, + faddr, &adata, ""); + if (r == RD_AP_UNDEC) { + /* + * Probably didn't have a srvtab on + * localhost. Allow login. + */ + log("Kerberos V4 TGT for %s unverifiable, " + "no srvtab installed? krb_rd_req: %s", + pw->pw_name, krb_err_txt[r]); + } else if (r != KSUCCESS) { + log("Kerberos V4 %s ticket unverifiable: %s", + KRB4_SERVICE_NAME, krb_err_txt[r]); + goto kerberos_auth_failure; + } + } else if (r == KDC_PR_UNKNOWN) { + /* + * Allow login if no rcmd service exists, but + * log the error. + */ + log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s " + "not registered, or srvtab is wrong?", pw->pw_name, + krb_err_txt[r], KRB4_SERVICE_NAME, phost); + } else { + /* + * TGT is bad, forget it. Possibly spoofed! + */ + packet_send_debug("WARNING: Kerberos V4 TGT " + "possibly spoofed for %s: %s", + pw->pw_name, krb_err_txt[r]); + goto kerberos_auth_failure; + } + + /* Authentication succeeded. */ + return 1; + +kerberos_auth_failure: + krb4_cleanup_proc(NULL); + + if (!options.kerberos_or_local_passwd) + return 0; + } else { + /* Logging in as root or no local Kerberos realm. */ + packet_send_debug("Unable to authenticate to Kerberos."); + } + /* Fall back to ordinary passwd authentication. */ + return -1; +} + void krb4_cleanup_proc(void *ignore) { diff --git a/auth-passwd.c b/auth-passwd.c index edc9d7bc..e8354f5b 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -49,133 +49,20 @@ auth_password(struct passwd * pw, const char *password) #ifdef SKEY if (options.skey_authentication == 1) { - if (strncasecmp(password, "s/key", 5) == 0) { - char *skeyinfo = skey_keyinfo(pw->pw_name); - if (skeyinfo == NULL) { - debug("generating fake skeyinfo for %.100s.", - pw->pw_name); - skeyinfo = skey_fake_keyinfo(pw->pw_name); - } - if (skeyinfo != NULL) - packet_send_debug(skeyinfo); - /* Try again. */ - return 0; - } else if (skey_haskey(pw->pw_name) == 0 && - skey_passcheck(pw->pw_name, (char *) password) != -1) { - /* Authentication succeeded. */ - return 1; - } + int ret = auth_skey_password(pw, password); + if (ret == 1 || ret == 0) + return ret; /* Fall back to ordinary passwd authentication. */ } #endif - -#if defined(KRB4) - /* - * Support for Kerberos v4 authentication - * - Dug Song - */ - if (options.kerberos_authentication) { - AUTH_DAT adata; - KTEXT_ST tkt; - struct hostent *hp; - unsigned long faddr; - char localhost[MAXHOSTNAMELEN]; - char phost[INST_SZ]; - char realm[REALM_SZ]; - int r; - - /* - * Try Kerberos password authentication only for non-root - * users and only if Kerberos is installed. - */ - if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) { - - /* Set up our ticket file. */ - if (!krb4_init(pw->pw_uid)) { - log("Couldn't initialize Kerberos ticket file for %s!", - pw->pw_name); - goto kerberos_auth_failure; - } - /* Try to get TGT using our password. */ - r = krb_get_pw_in_tkt((char *) pw->pw_name, "", - realm, "krbtgt", realm, - DEFAULT_TKT_LIFE, (char *) password); - if (r != INTK_OK) { - packet_send_debug("Kerberos V4 password " - "authentication for %s failed: %s", - pw->pw_name, krb_err_txt[r]); - goto kerberos_auth_failure; - } - /* Successful authentication. */ - chown(tkt_string(), pw->pw_uid, pw->pw_gid); - - /* - * Now that we have a TGT, try to get a local - * "rcmd" ticket to ensure that we are not talking - * to a bogus Kerberos server. - */ - (void) gethostname(localhost, sizeof(localhost)); - (void) strlcpy(phost, (char *) krb_get_phost(localhost), - INST_SZ); - r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33); - - if (r == KSUCCESS) { - if (!(hp = gethostbyname(localhost))) { - log("Couldn't get local host address!"); - goto kerberos_auth_failure; - } - memmove((void *) &faddr, (void *) hp->h_addr, - sizeof(faddr)); - - /* Verify our "rcmd" ticket. */ - r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, - faddr, &adata, ""); - if (r == RD_AP_UNDEC) { - /* - * Probably didn't have a srvtab on - * localhost. Allow login. - */ - log("Kerberos V4 TGT for %s unverifiable, " - "no srvtab installed? krb_rd_req: %s", - pw->pw_name, krb_err_txt[r]); - } else if (r != KSUCCESS) { - log("Kerberos V4 %s ticket unverifiable: %s", - KRB4_SERVICE_NAME, krb_err_txt[r]); - goto kerberos_auth_failure; - } - } else if (r == KDC_PR_UNKNOWN) { - /* - * Allow login if no rcmd service exists, but - * log the error. - */ - log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s " - "not registered, or srvtab is wrong?", pw->pw_name, - krb_err_txt[r], KRB4_SERVICE_NAME, phost); - } else { - /* - * TGT is bad, forget it. Possibly spoofed! - */ - packet_send_debug("WARNING: Kerberos V4 TGT " - "possibly spoofed for %s: %s", - pw->pw_name, krb_err_txt[r]); - goto kerberos_auth_failure; - } - - /* Authentication succeeded. */ - return 1; - - kerberos_auth_failure: - krb4_cleanup_proc(NULL); - - if (!options.kerberos_or_local_passwd) - return 0; - } else { - /* Logging in as root or no local Kerberos realm. */ - packet_send_debug("Unable to authenticate to Kerberos."); - } +#ifdef KRB4 + if (options.kerberos_authentication == 1) { + int ret = auth_krb4_password(pw, password); + if (ret == 1 || ret == 0) + return ret; /* Fall back to ordinary passwd authentication. */ } -#endif /* KRB4 */ +#endif /* Check for users with no password. */ if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0) diff --git a/auth-rsa.c b/auth-rsa.c index 2afb1ea3..955532ce 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -259,16 +259,16 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) } /* cp now points to the comment part. */ - /* check the real bits */ - if (bits != BN_num_bits(n)) - error("Warning: error in %s, line %ld: keysize mismatch: " - "actual size %d vs. announced %d.", - file, linenum, BN_num_bits(n), bits); - /* Check if the we have found the desired key (identified by its modulus). */ if (BN_cmp(n, client_n) != 0) continue; + /* check the real bits */ + if (bits != BN_num_bits(n)) + log("Warning: %s, line %ld: keysize mismatch: " + "actual %d vs. announced %d.", + file, linenum, BN_num_bits(n), bits); + /* We have found the desired key. */ /* Perform the challenge-response dialog for this key. */ diff --git a/auth-skey.c b/auth-skey.c index 4ff9561f..ebe0483d 100644 --- a/auth-skey.c +++ b/auth-skey.c @@ -4,6 +4,8 @@ RCSID("$Id$"); #include "ssh.h" +#include "packet.h" + #ifdef HAVE_OPENSSL #include #endif @@ -13,6 +15,35 @@ RCSID("$Id$"); /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */ +/* + * try skey authentication, + * return 1 on success, 0 on failure, -1 if skey is not available + */ + +int +auth_skey_password(struct passwd * pw, const char *password) +{ + if (strncasecmp(password, "s/key", 5) == 0) { + char *skeyinfo = skey_keyinfo(pw->pw_name); + if (skeyinfo == NULL) { + debug("generating fake skeyinfo for %.100s.", + pw->pw_name); + skeyinfo = skey_fake_keyinfo(pw->pw_name); + } + if (skeyinfo != NULL) + packet_send_debug(skeyinfo); + /* Try again. */ + return 0; + } else if (skey_haskey(pw->pw_name) == 0 && + skey_passcheck(pw->pw_name, (char *) password) != -1) { + /* Authentication succeeded. */ + return 1; + } + /* Fall back to ordinary passwd authentication. */ + return -1; +} + ++ /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */ #define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \ ((x)[3])) diff --git a/channels.c b/channels.c index 143367bd..8fe9c716 100644 --- a/channels.c +++ b/channels.c @@ -82,7 +82,7 @@ unsigned int x11_fake_data_len; */ typedef struct { char *host; /* Host name. */ - int port; /* Port number. */ + u_short port; /* Port number. */ } ForwardPermission; /* List of all permitted host/port pairs to connect. */ @@ -876,8 +876,8 @@ channel_open_message() */ void -channel_request_local_forwarding(int port, const char *host, - int host_port) +channel_request_local_forwarding(u_short port, const char *host, + u_short host_port) { int ch, sock, on = 1; struct sockaddr_in sin; @@ -932,8 +932,8 @@ channel_request_local_forwarding(int port, const char *host, */ void -channel_request_remote_forwarding(int port, const char *host, - int remote_port) +channel_request_remote_forwarding(u_short port, const char *host, + u_short remote_port) { int payload_len; /* Record locally that connection to this host/port is permitted. */ @@ -968,7 +968,7 @@ channel_request_remote_forwarding(int port, const char *host, void channel_input_port_forward_request(int is_root) { - int port, host_port; + u_short port, host_port; char *hostname; /* Get arguments from the packet. */ @@ -976,10 +976,6 @@ channel_input_port_forward_request(int is_root) hostname = packet_get_string(NULL); host_port = packet_get_int(); - /* Port numbers are 16 bit quantities. */ - if ((port & 0xffff) != port) - packet_disconnect("Requested forwarding of nonexistent port %d.", port); - /* * Check that an unprivileged user is not trying to forward a * privileged port. @@ -1004,7 +1000,8 @@ channel_input_port_forward_request(int is_root) void channel_input_port_open(int payload_len) { - int remote_channel, sock, newch, host_port, i; + int remote_channel, sock, newch, i; + u_short host_port; struct sockaddr_in sin; char *host, *originator_string; struct hostent *hp; @@ -1122,7 +1119,8 @@ char * x11_create_display_inet(int screen_number) { extern ServerOptions options; - int display_number, port, sock; + int display_number, sock; + u_short port; struct sockaddr_in sin; char buf[512]; char hostname[MAXHOSTNAMELEN]; diff --git a/hostfile.c b/hostfile.c index df9692b6..7060a899 100644 --- a/hostfile.c +++ b/hostfile.c @@ -14,7 +14,7 @@ */ #include "includes.h" -RCSID("$Id$"); +RCSID("$OpenBSD: hostfile.c,v 1.10 1999/12/02 20:18:59 markus Exp $"); #include "packet.h" #include "ssh.h" @@ -231,9 +231,9 @@ check_host_in_hostfile(const char *filename, const char *host, continue; if (kbits != BN_num_bits(kn)) { - error("Warning: error in %s, line %d: keysize mismatch for host %s: " - "actual size %d vs. announced %d.", - filename, linenum, host, BN_num_bits(kn), kbits); + error("Warning: %s, line %d: keysize mismatch for host %s: " + "actual %d vs. announced %d.", + filename, linenum, host, BN_num_bits(kn), kbits); error("Warning: replace %d with %d in %s, line %d.", kbits, BN_num_bits(kn), filename, linenum); } diff --git a/nchan.c b/nchan.c index 9bcad647..b89b73e5 100644 --- a/nchan.c +++ b/nchan.c @@ -65,7 +65,7 @@ chan_rcvd_oclose(Channel *c) chan_delele_if_full_closed(c); break; default: - debug("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate); + error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate); break; } } @@ -79,7 +79,7 @@ chan_read_failed(Channel *c) c->istate = CHAN_INPUT_WAIT_DRAIN; break; default: - debug("internal error: we do not read, but chan_read_failed %d for istate %d", + error("internal error: we do not read, but chan_read_failed %d for istate %d", c->self, c->istate); break; } @@ -88,7 +88,7 @@ void chan_ibuf_empty(Channel *c) { if (buffer_len(&c->input)) { - debug("internal error: chan_ibuf_empty %d for non empty buffer", c->self); + error("internal error: chan_ibuf_empty %d for non empty buffer", c->self); return; } switch (c->istate) { @@ -98,7 +98,7 @@ chan_ibuf_empty(Channel *c) c->istate = CHAN_INPUT_WAIT_OCLOSE; break; default: - debug("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate); + error("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate); break; } } @@ -118,7 +118,7 @@ chan_rcvd_ieof(Channel *c) chan_delele_if_full_closed(c); break; default: - debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate); + error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate); break; } } @@ -138,7 +138,7 @@ chan_write_failed(Channel *c) chan_delele_if_full_closed(c); break; default: - debug("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate); + error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate); break; } } @@ -157,7 +157,7 @@ chan_obuf_empty(Channel *c) chan_delele_if_full_closed(c); break; default: - debug("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate); + error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate); break; } } @@ -176,7 +176,7 @@ chan_send_ieof(Channel *c) packet_send(); break; default: - debug("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate); + error("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate); break; } } @@ -193,7 +193,7 @@ chan_send_oclose(Channel *c) packet_send(); break; default: - debug("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate); + error("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate); break; } } diff --git a/packet.c b/packet.c index bc6d97f2..f7b4f2c9 100644 --- a/packet.c +++ b/packet.c @@ -530,8 +530,10 @@ restart: *payload_len_ptr = buffer_len(&incoming_packet); /* Handle disconnect message. */ - if ((unsigned char) buf[0] == SSH_MSG_DISCONNECT) - fatal("Received disconnect: %.900s", packet_get_string(NULL)); + if ((unsigned char) buf[0] == SSH_MSG_DISCONNECT) { + log("Received disconnect: %.900s", packet_get_string(NULL)); + fatal_cleanup(); + } /* Ignore ignore messages. */ if ((unsigned char) buf[0] == SSH_MSG_IGNORE) @@ -662,7 +664,8 @@ packet_disconnect(const char *fmt,...) packet_close(); /* Display the error locally and exit. */ - fatal("Disconnecting: %.100s", buf); + log("Disconnecting: %.100s", buf); + fatal_cleanup(); } /* Checks if there is any buffered output, and tries to write some of the output. */ diff --git a/readconf.c b/readconf.c index 199b7e2a..eca13329 100644 --- a/readconf.c +++ b/readconf.c @@ -164,13 +164,11 @@ static struct { */ void -add_local_forward(Options *options, int port, const char *host, - int host_port) +add_local_forward(Options *options, u_short port, const char *host, + u_short host_port) { Forward *fwd; extern uid_t original_real_uid; - if ((port & 0xffff) != port) - fatal("Requested forwarding of nonexistent port %d.", port); if (port < IPPORT_RESERVED && original_real_uid != 0) fatal("Privileged ports can only be forwarded by root.\n"); if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) @@ -187,8 +185,8 @@ add_local_forward(Options *options, int port, const char *host, */ void -add_remote_forward(Options *options, int port, const char *host, - int host_port) +add_remote_forward(Options *options, u_short port, const char *host, + u_short host_port) { Forward *fwd; if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) @@ -230,7 +228,8 @@ process_config_line(Options *options, const char *host, int *activep) { char buf[256], *cp, *string, **charptr, *cp2; - int opcode, *intptr, value, fwd_port, fwd_host_port; + int opcode, *intptr, value; + u_short fwd_port, fwd_host_port; /* Skip leading whitespace. */ cp = line + strspn(line, WHITESPACE); @@ -467,7 +466,7 @@ parse_int: if (!cp) fatal("%.200s line %d: Missing second argument.", filename, linenum); - if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2) + if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2) fatal("%.200s line %d: Badly formatted host:port.", filename, linenum); if (*activep) @@ -486,7 +485,7 @@ parse_int: if (!cp) fatal("%.200s line %d: Missing second argument.", filename, linenum); - if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2) + if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2) fatal("%.200s line %d: Badly formatted host:port.", filename, linenum); if (*activep) diff --git a/readconf.h b/readconf.h index e21a60b7..29dd4f0f 100644 --- a/readconf.h +++ b/readconf.h @@ -21,9 +21,9 @@ /* Data structure for representing a forwarding request. */ typedef struct { - int port; /* Port to forward. */ - char *host; /* Host to connect. */ - int host_port; /* Port to connect on host. */ + u_short port; /* Port to forward. */ + char *host; /* Host to connect. */ + u_short host_port; /* Port to connect on host. */ } Forward; /* Data structure for representing option data. */ @@ -123,15 +123,15 @@ read_config_file(const char *filename, const char *host, * error. */ void -add_local_forward(Options * options, int port, const char *host, - int host_port); +add_local_forward(Options * options, u_short port, const char *host, + u_short host_port); /* * Adds a remote TCP/IP port forward to options. Never returns if there is * an error. */ void -add_remote_forward(Options * options, int port, const char *host, - int host_port); +add_remote_forward(Options * options, u_short port, const char *host, + u_short host_port); #endif /* READCONF_H */ diff --git a/serverloop.c b/serverloop.c index 683598ef..94c21157 100644 --- a/serverloop.c +++ b/serverloop.c @@ -609,7 +609,7 @@ quit: /* Check if it matches the process we forked. */ if (wait_pid != pid) error("Strange, wait returned pid %d, expected %d", - wait_pid, pid); + wait_pid, pid); } /* We no longer want our SIGCHLD handler to be called. */ diff --git a/ssh-add.1 b/ssh-add.1 index 88c15eab..9a11a037 100644 --- a/ssh-add.1 +++ b/ssh-add.1 @@ -51,7 +51,7 @@ Deletes all identities from the agent. .El .Sh FILES .Bl -tag -width Ds -.Pa $HOME/.ssh/identity +.It Pa $HOME/.ssh/identity Contains the RSA authentication identity of the user. This file should not be readable by anyone but the user. Note that @@ -64,6 +64,9 @@ default file added by .Nm when no other files have been specified. .Pp +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev "DISPLAY" and "SSH_ASKPASS" If .Nm needs a passphrase, it will read the passphrase from the current diff --git a/ssh-add.c b/ssh-add.c index 2ade9c23..d81510e1 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -106,8 +106,12 @@ add_file(AuthenticationConnection *ac, const char *filename) } RSA_free(public_key); - if (!interactive && getenv("DISPLAY")) - askpass = getenv("SSH_ASKPASS"); + if (!interactive && getenv("DISPLAY")) { + if (getenv(SSH_ASKPASS_ENV)) + askpass = getenv(SSH_ASKPASS_ENV); + else + askpass = SSH_ASKPASS_DEFAULT; + } /* At first, try empty passphrase */ success = load_private_key(filename, "", key, &comment); diff --git a/ssh.1 b/ssh.1 index 54d797ca..2b89fbb6 100644 --- a/ssh.1 +++ b/ssh.1 @@ -627,6 +627,9 @@ server running on some machine, or execute somewhere. Host key management will be done using the HostName of the host being connected (defaulting to the name typed by the user). +Note that +.Cm CheckHostIP +is not available for connects with a proxy command. .Pp .It Cm RemoteForward Specifies that a TCP/IP port on the remote machine be forwarded over diff --git a/ssh.c b/ssh.c index b208f831..51d5117a 100644 --- a/ssh.c +++ b/ssh.c @@ -162,8 +162,8 @@ rsh_connect(char *host, char *user, Buffer * command) int main(int ac, char **av) { - int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port, - authfd; + int i, opt, optind, type, exit_status, ok, authfd; + u_short fwd_port, fwd_host_port; char *optarg, *cp, buf[256]; Buffer command; struct winsize ws; @@ -340,10 +340,6 @@ main(int ac, char **av) case 'p': options.port = atoi(optarg); - if (options.port < 1 || options.port > 65535) { - fprintf(stderr, "Bad port %s.\n", optarg); - exit(1); - } break; case 'l': @@ -351,7 +347,7 @@ main(int ac, char **av) break; case 'R': - if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf, + if (sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, &fwd_host_port) != 3) { fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); usage(); @@ -361,7 +357,7 @@ main(int ac, char **av) break; case 'L': - if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf, + if (sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, &fwd_host_port) != 3) { fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); usage(); @@ -561,7 +557,7 @@ main(int ac, char **av) /* Check if the connection failed, and try "rsh" if appropriate. */ if (!ok) { if (options.port != 0) - log("Secure connection to %.100s on port %d refused%.100s.", + log("Secure connection to %.100s on port %hu refused%.100s.", host, options.port, options.fallback_to_rsh ? "; reverting to insecure method" : ""); else diff --git a/ssh.h b/ssh.h index bfa8ea12..2de5ad25 100644 --- a/ssh.h +++ b/ssh.h @@ -169,6 +169,13 @@ */ #define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID" +/* + * Default path to ssh-askpass used by ssh-add, + * environment variable for overwriting the default location + */ +#define SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass" +#define SSH_ASKPASS_ENV "SSH_ASKPASS" + /* * Force host key length and server key length to differ by at least this * many bits. This is to make double encryption with rsaref work. @@ -294,7 +301,7 @@ void record_logout(int pid, const char *ttyname); */ int ssh_connect(const char *host, struct sockaddr_in * hostaddr, - int port, int connection_attempts, + u_short port, int connection_attempts, int anonymous, uid_t original_real_uid, const char *proxy_command); @@ -579,8 +586,8 @@ char *channel_open_message(void); * error. */ void -channel_request_local_forwarding(int port, const char *host, - int remote_port); +channel_request_local_forwarding(u_short port, const char *host, + u_short remote_port); /* * Initiate forwarding of connections to port "port" on remote host through @@ -589,8 +596,8 @@ channel_request_local_forwarding(int port, const char *host, * permitted. */ void -channel_request_remote_forwarding(int port, const char *host, - int remote_port); +channel_request_remote_forwarding(u_short port, const char *host, + u_short remote_port); /* * Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually @@ -704,6 +711,7 @@ struct envstring { int auth_krb4(const char *server_user, KTEXT auth, char **client); int krb4_init(uid_t uid); void krb4_cleanup_proc(void *ignore); +int auth_krb4_password(struct passwd * pw, const char *password); #ifdef AFS #include @@ -721,6 +729,7 @@ int radix_to_creds(const char *buf, CREDENTIALS * creds); #ifdef SKEY #include char *skey_fake_keyinfo(char *username); +int auth_skey_password(struct passwd * pw, const char *password); #endif /* SKEY */ #endif /* SSH_H */ diff --git a/sshconnect.c b/sshconnect.c index 9cd33c1c..d64eafd9 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -34,11 +34,13 @@ RCSID("$Id$"); /* Session id for the current session. */ unsigned char session_id[16]; +extern Options options; + /* * Connect to the given ssh server using a proxy command. */ int -ssh_proxy_connect(const char *host, int port, uid_t original_real_uid, +ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid, const char *proxy_command) { Buffer command; @@ -49,7 +51,7 @@ ssh_proxy_connect(const char *host, int port, uid_t original_real_uid, char portstring[100]; /* Convert the port number into a string. */ - snprintf(portstring, sizeof portstring, "%d", port); + snprintf(portstring, sizeof portstring, "%hu", port); /* Build the final command string in the buffer by making the appropriate substitutions to the given proxy command. */ @@ -177,7 +179,7 @@ ssh_create_socket(uid_t original_real_uid, int privileged) */ int ssh_connect(const char *host, struct sockaddr_in * hostaddr, - int port, int connection_attempts, + u_short port, int connection_attempts, int anonymous, uid_t original_real_uid, const char *proxy_command) { @@ -476,9 +478,8 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) * the user using it. */ int -try_rsa_authentication(struct passwd * pw, const char *authfile) +try_rsa_authentication(const char *authfile) { - extern Options options; BIGNUM *challenge; RSA *private_key; RSA *public_key; @@ -490,7 +491,8 @@ try_rsa_authentication(struct passwd * pw, const char *authfile) public_key = RSA_new(); if (!load_public_key(authfile, public_key, &comment)) { RSA_free(public_key); - return 0; /* Could not load it. Fail. */ + /* Could not load it. Fail. */ + return 0; } debug("Trying RSA authentication with key '%.100s'", comment); @@ -513,8 +515,7 @@ try_rsa_authentication(struct passwd * pw, const char *authfile) if (type == SSH_SMSG_FAILURE) { debug("Server refused our key."); xfree(comment); - return 0; /* Server refuses to authenticate with - this key. */ + return 0; } /* Otherwise, the server should respond with a challenge. */ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) @@ -884,6 +885,93 @@ send_afs_tokens(void) #endif /* AFS */ +/* + * Tries to authenticate with any string-based challenge/response system. + * Note that the client code is not tied to s/key or TIS. + */ +int +try_skey_authentication() +{ + int type, i, payload_len; + char *challenge, *response; + + debug("Doing skey authentication."); + + /* request a challenge */ + packet_start(SSH_CMSG_AUTH_TIS); + packet_send(); + packet_write_wait(); + + type = packet_read(&payload_len); + if (type != SSH_SMSG_FAILURE && + type != SSH_SMSG_AUTH_TIS_CHALLENGE) { + packet_disconnect("Protocol error: got %d in response " + "to skey-auth", type); + } + if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { + debug("No challenge for skey authentication."); + return 0; + } + challenge = packet_get_string(&payload_len); + if (options.cipher == SSH_CIPHER_NONE) + log("WARNING: Encryption is disabled! " + "Reponse will be transmitted in clear text."); + fprintf(stderr, "%s\n", challenge); + fflush(stderr); + for (i = 0; i < options.number_of_password_prompts; i++) { + if (i != 0) + error("Permission denied, please try again."); + response = read_passphrase("Response: ", 0); + packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); + packet_put_string(response, strlen(response)); + memset(response, 0, strlen(response)); + xfree(response); + packet_send(); + packet_write_wait(); + type = packet_read(&payload_len); + if (type == SSH_SMSG_SUCCESS) + return 1; + if (type != SSH_SMSG_FAILURE) + packet_disconnect("Protocol error: got %d in response " + "to skey-auth-reponse", type); + } + /* failure */ + return 0; +} + +/* + * Tries to authenticate with plain passwd authentication. + */ +int +try_password_authentication(char *prompt) +{ + int type, i, payload_len; + char *password; + + debug("Doing password authentication."); + if (options.cipher == SSH_CIPHER_NONE) + log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); + for (i = 0; i < options.number_of_password_prompts; i++) { + if (i != 0) + error("Permission denied, please try again."); + password = read_passphrase(prompt, 0); + packet_start(SSH_CMSG_AUTH_PASSWORD); + packet_put_string(password, strlen(password)); + memset(password, 0, strlen(password)); + xfree(password); + packet_send(); + packet_write_wait(); + + type = packet_read(&payload_len); + if (type == SSH_SMSG_SUCCESS) + return 1; + if (type != SSH_SMSG_FAILURE) + packet_disconnect("Protocol error: got %d in response to passwd auth", type); + } + /* failure */ + return 0; +} + /* * Waits for the server identification string, and sends our own * identification string. @@ -895,7 +983,6 @@ ssh_exchange_identification() int remote_major, remote_minor, i; int connection_in = packet_get_connection_in(); int connection_out = packet_get_connection_out(); - extern Options options; /* Read other side\'s version identification. */ for (i = 0; i < sizeof(buf) - 1; i++) { @@ -1015,9 +1102,7 @@ ssh_login(int host_key_valid, struct sockaddr_in *hostaddr, uid_t original_real_uid) { - extern Options options; int i, type; - char *password; struct passwd *pw; BIGNUM *key; RSA *host_key, *file_key; @@ -1036,6 +1121,13 @@ ssh_login(int host_key_valid, int payload_len, clen, sum_len = 0; u_int32_t rand = 0; + /* + * Turn off check_host_ip for proxy connects, since + * we don't have the remote ip-address + */ + if (options.proxy_command != NULL && options.check_host_ip) + options.check_host_ip = 0; + if (options.check_host_ip) ip = xstrdup(inet_ntoa(hostaddr->sin_addr)); @@ -1494,80 +1586,23 @@ ssh_login(int host_key_valid, /* Try RSA authentication for each identity. */ for (i = 0; i < options.num_identity_files; i++) - if (try_rsa_authentication(pw, options.identity_files[i])) + if (try_rsa_authentication(options.identity_files[i])) return; } /* Try skey authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_TIS)) && options.skey_authentication && !options.batch_mode) { - debug("Doing skey authentication."); - - /* request a challenge */ - packet_start(SSH_CMSG_AUTH_TIS); - packet_send(); - packet_write_wait(); - - type = packet_read(&payload_len); - if (type != SSH_SMSG_FAILURE && - type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - packet_disconnect("Protocol error: got %d in response " - "to skey auth", type); - } - if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - debug("No challenge for skey authentication."); - } else { - char *challenge, *response; - challenge = packet_get_string(&payload_len); - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! " - "Reponse will be transmitted in clear text."); - fprintf(stderr, "%s\n", challenge); - fflush(stderr); - for (i = 0; i < options.number_of_password_prompts; i++) { - if (i != 0) - error("Permission denied, please try again."); - response = read_passphrase("Response: ", 0); - packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); - packet_put_string(response, strlen(response)); - memset(response, 0, strlen(response)); - xfree(response); - packet_send(); - packet_write_wait(); - type = packet_read(&payload_len); - if (type == SSH_SMSG_SUCCESS) - return; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response " - "to skey auth", type); - } - } + if (try_skey_authentication()) + return; } /* Try password authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && options.password_authentication && !options.batch_mode) { char prompt[80]; - snprintf(prompt, sizeof(prompt), "%.30s@%.30s's password: ", + snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ", server_user, host); - debug("Doing password authentication."); - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); - for (i = 0; i < options.number_of_password_prompts; i++) { - if (i != 0) - error("Permission denied, please try again."); - password = read_passphrase(prompt, 0); - packet_start(SSH_CMSG_AUTH_PASSWORD); - packet_put_string(password, strlen(password)); - memset(password, 0, strlen(password)); - xfree(password); - packet_send(); - packet_write_wait(); - - type = packet_read(&payload_len); - if (type == SSH_SMSG_SUCCESS) - return; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to passwd auth", type); - } + if (try_password_authentication(prompt)) + return; } /* All authentication methods have failed. Exit with an error message. */ fatal("Permission denied.");