# HG changeset patch # User Matt Johnston # Date 1251823106 0 # Node ID 0055305605948a474c5074a8ddbd065f578ea504 # Parent 893a9dd0b9dd0a27ceaed28debf38ce6d253d6c6 Rearrange getaddrstring() etc diff -r 893a9dd0b9dd -r 005530560594 cli-kex.c --- a/cli-kex.c Mon Aug 31 15:25:39 2009 +0000 +++ b/cli-kex.c Tue Sep 01 16:38:26 2009 +0000 @@ -304,7 +304,7 @@ fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */ buf_setpos(line, 0); buf_setlen(line, 0); - buf_putbytes(line, ses.remotehost, hostlen); + buf_putbytes(line, cli_opts.remotehost, hostlen); buf_putbyte(line, ' '); buf_putbytes(line, algoname, algolen); buf_putbyte(line, ' '); diff -r 893a9dd0b9dd -r 005530560594 cli-main.c --- a/cli-main.c Mon Aug 31 15:25:39 2009 +0000 +++ b/cli-main.c Tue Sep 01 16:38:26 2009 +0000 @@ -45,8 +45,6 @@ int sock_in, sock_out; char* error = NULL; - char* hostandport; - int len; _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; @@ -78,14 +76,7 @@ dropbear_exit("%s", error); } - /* Set up the host:port log */ - len = strlen(cli_opts.remotehost); - len += 10; /* 16 bit port and leeway*/ - hostandport = (char*)m_malloc(len); - snprintf(hostandport, len, "%s:%s", - cli_opts.remotehost, cli_opts.remoteport); - - cli_session(sock_in, sock_out, hostandport); + cli_session(sock_in, sock_out); /* not reached */ return -1; diff -r 893a9dd0b9dd -r 005530560594 cli-runopts.c --- a/cli-runopts.c Mon Aug 31 15:25:39 2009 +0000 +++ b/cli-runopts.c Tue Sep 01 16:38:26 2009 +0000 @@ -378,15 +378,19 @@ } } if (keepalive_arg) { - if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) { + unsigned int val; + if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) { dropbear_exit("Bad keepalive '%s'", keepalive_arg); } + opts.keepalive_secs = val; } if (idle_timeout_arg) { - if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) { + unsigned int val; + if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) { dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg); } + opts.idle_timeout_secs = val; } #ifdef ENABLE_CLI_NETCAT @@ -454,7 +458,7 @@ sign_key * key = (sign_key*)iter->item; const size_t size = len - total; int written = snprintf(ret+total, size, "-i %s", key->filename); - dropbear_assert(written < size); + dropbear_assert((unsigned int)written < size); total += written; } diff -r 893a9dd0b9dd -r 005530560594 cli-session.c --- a/cli-session.c Mon Aug 31 15:25:39 2009 +0000 +++ b/cli-session.c Tue Sep 01 16:38:26 2009 +0000 @@ -82,13 +82,13 @@ NULL /* Null termination */ }; -void cli_session(int sock_in, int sock_out, char* remotehost) { +void cli_session(int sock_in, int sock_out) { seedrandom(); crypto_init(); - common_session_init(sock_in, sock_out, remotehost); + common_session_init(sock_in, sock_out); chaninitialise(cli_chantypes); diff -r 893a9dd0b9dd -r 005530560594 common-session.c --- a/common-session.c Mon Aug 31 15:25:39 2009 +0000 +++ b/common-session.c Tue Sep 01 16:38:26 2009 +0000 @@ -52,12 +52,10 @@ /* called only at the start of a session, set up initial state */ -void common_session_init(int sock_in, int sock_out, char* remotehost) { +void common_session_init(int sock_in, int sock_out) { TRACE(("enter session_init")) - ses.remotehost = remotehost; - ses.sock_in = sock_in; ses.sock_out = sock_out; ses.maxfd = MAX(sock_in, sock_out); diff -r 893a9dd0b9dd -r 005530560594 dbutil.c --- a/dbutil.c Mon Aug 31 15:25:39 2009 +0000 +++ b/dbutil.c Tue Sep 01 16:38:26 2009 +0000 @@ -539,14 +539,47 @@ execv(usershell, argv); } +void get_socket_address(int fd, char **local_host, char **local_port, + char **remote_host, char **remote_port, int host_lookup) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + + if (local_host || local_port) { + addrlen = sizeof(addr); + if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) { + dropbear_exit("Failed socket address: %s", strerror(errno)); + } + getaddrstring(&addr, local_host, local_port, host_lookup); + } + if (remote_host || remote_port) { + addrlen = sizeof(addr); + if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) { + dropbear_exit("Failed socket address: %s", strerror(errno)); + } + getaddrstring(&addr, remote_host, remote_port, host_lookup); + } +} + /* Return a string representation of the socket address passed. The return * value is allocated with malloc() */ -unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) { +void getaddrstring(struct sockaddr_storage* addr, + char **ret_host, char **ret_port, + int host_lookup) { - char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; - char *retstring = NULL; + char host[NI_MAXHOST+1], serv[NI_MAXSERV+1]; + unsigned int len; int ret; - unsigned int len; + + int flags = NI_NUMERICSERV | NI_NUMERICHOST; + +#ifndef DO_HOST_LOOKUP + host_lookup = 0; +#endif + + if (host_lookup) { + flags = NI_NUMERICSERV; + } len = sizeof(struct sockaddr_storage); /* Some platforms such as Solaris 8 require that len is the length @@ -564,66 +597,28 @@ #endif #endif - ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), - sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST); + ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1, + serv, sizeof(serv)-1, flags); if (ret != 0) { - /* This is a fairly bad failure - it'll fallback to IP if it - * just can't resolve */ - dropbear_exit("failed lookup (%d, %d)", ret, errno); - } - - if (withport) { - len = strlen(hbuf) + 2 + strlen(sbuf); - retstring = (char*)m_malloc(len); - snprintf(retstring, len, "%s:%s", hbuf, sbuf); - } else { - retstring = m_strdup(hbuf); + if (host_lookup) { + /* On some systems (Darwin does it) we get EINTR from getnameinfo + * somehow. Eew. So we'll just return the IP, since that doesn't seem + * to exhibit that behaviour. */ + getaddrstring(addr, ret_host, ret_port, 0); + return; + } else { + /* if we can't do a numeric lookup, something's gone terribly wrong */ + dropbear_exit("Failed lookup: %s", gai_strerror(ret)); + } } - return retstring; -} - -/* Get the hostname corresponding to the address addr. On failure, the IP - * address is returned. The return value is allocated with strdup() */ -char* getaddrhostname(struct sockaddr_storage * addr) { - - char hbuf[NI_MAXHOST]; - char sbuf[NI_MAXSERV]; - int ret; - unsigned int len; -#ifdef DO_HOST_LOOKUP - const int flags = NI_NUMERICSERV; -#else - const int flags = NI_NUMERICHOST | NI_NUMERICSERV; -#endif - - len = sizeof(struct sockaddr_storage); - /* Some platforms such as Solaris 8 require that len is the length - * of the specific structure. */ -#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY - if (addr->ss_family == AF_INET) { - len = sizeof(struct sockaddr_in); + if (ret_host) { + *ret_host = m_strdup(host); } -#ifdef AF_INET6 - if (addr->ss_family == AF_INET6) { - len = sizeof(struct sockaddr_in6); + if (ret_port) { + *ret_port = m_strdup(serv); } -#endif -#endif - - - ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), - sbuf, sizeof(sbuf), flags); - - if (ret != 0) { - /* On some systems (Darwin does it) we get EINTR from getnameinfo - * somehow. Eew. So we'll just return the IP, since that doesn't seem - * to exhibit that behaviour. */ - return getaddrstring(addr, 0); - } - - return m_strdup(hbuf); } #ifdef DEBUG_TRACE diff -r 893a9dd0b9dd -r 005530560594 dbutil.h --- a/dbutil.h Mon Aug 31 15:25:39 2009 +0000 +++ b/dbutil.h Tue Sep 01 16:38:26 2009 +0000 @@ -46,7 +46,10 @@ extern int debug_trace; #endif char * stripcontrol(const char * text); -unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport); +void get_socket_address(int fd, char **local_host, char **local_port, + char **remote_host, char **remote_port, int host_lookup); +void getaddrstring(struct sockaddr_storage* addr, + char **ret_host, char **ret_port, int host_lookup); int dropbear_listen(const char* address, const char* port, int *socks, unsigned int sockcount, char **errstring, int *maxfd); int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, @@ -57,7 +60,6 @@ #endif int connect_remote(const char* remotehost, const char* remoteport, int nonblocking, char ** errstring); -char* getaddrhostname(struct sockaddr_storage * addr); int buf_readfile(buffer* buf, const char* filename); int buf_getline(buffer * line, FILE * authfile); diff -r 893a9dd0b9dd -r 005530560594 debug.h --- a/debug.h Mon Aug 31 15:25:39 2009 +0000 +++ b/debug.h Tue Sep 01 16:38:26 2009 +0000 @@ -39,7 +39,7 @@ * Caution: Don't use this in an unfriendly environment (ie unfirewalled), * since the printing may not sanitise strings etc. This will add a reasonable * amount to your executable size. */ -/*#define DEBUG_TRACE*/ +#define DEBUG_TRACE /* All functions writing to the cleartext payload buffer call * CHECKCLEARTOWRITE() before writing. This is only really useful if you're diff -r 893a9dd0b9dd -r 005530560594 options.h --- a/options.h Mon Aug 31 15:25:39 2009 +0000 +++ b/options.h Tue Sep 01 16:38:26 2009 +0000 @@ -167,9 +167,9 @@ * but there's an interface via a PAM module - don't bother using it otherwise. * You can't enable both PASSWORD and PAM. */ -#define ENABLE_SVR_PASSWORD_AUTH +/*#define ENABLE_SVR_PASSWORD_AUTH*/ /* PAM requires ./configure --enable-pam */ -/*#define ENABLE_SVR_PAM_AUTH*/ +#define ENABLE_SVR_PAM_AUTH #define ENABLE_SVR_PUBKEY_AUTH /* Whether to take public key options in diff -r 893a9dd0b9dd -r 005530560594 packet.c --- a/packet.c Mon Aug 31 15:25:39 2009 +0000 +++ b/packet.c Tue Sep 01 16:38:26 2009 +0000 @@ -157,9 +157,10 @@ static int read_packet_init() { unsigned int maxlen; - int len; - unsigned char blocksize; - unsigned char macsize; + int slen; + unsigned int len; + unsigned int blocksize; + unsigned int macsize; blocksize = ses.keys->recv.algo_crypt->blocksize; @@ -173,12 +174,12 @@ maxlen = blocksize - ses.readbuf->pos; /* read the rest of the packet if possible */ - len = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen), + slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen), maxlen); - if (len == 0) { + if (slen == 0) { ses.remoteclosed(); } - if (len < 0) { + if (slen < 0) { if (errno == EINTR) { TRACE(("leave read_packet_init: EINTR")) return DROPBEAR_FAILURE; @@ -186,9 +187,9 @@ dropbear_exit("error reading: %s", strerror(errno)); } - buf_incrwritepos(ses.readbuf, len); + buf_incrwritepos(ses.readbuf, slen); - if ((unsigned int)len != maxlen) { + if ((unsigned int)slen != maxlen) { /* don't have enough bytes to determine length, get next time */ return DROPBEAR_FAILURE; } diff -r 893a9dd0b9dd -r 005530560594 runopts.h --- a/runopts.h Mon Aug 31 15:25:39 2009 +0000 +++ b/runopts.h Tue Sep 01 16:38:26 2009 +0000 @@ -37,8 +37,8 @@ int listen_fwd_all; #endif unsigned int recv_window; - unsigned int keepalive_secs; - unsigned int idle_timeout_secs; + time_t keepalive_secs; + time_t idle_timeout_secs; } runopts; diff -r 893a9dd0b9dd -r 005530560594 session.h --- a/session.h Mon Aug 31 15:25:39 2009 +0000 +++ b/session.h Tue Sep 01 16:38:26 2009 +0000 @@ -41,7 +41,7 @@ extern int sessinitdone; /* Is set to 0 somewhere */ extern int exitflag; -void common_session_init(int sock_in, int sock_out, char* remotehost); +void common_session_init(int sock_in, int sock_out); void session_loop(void(*loophandler)()); void common_session_cleanup(); void session_identification(); @@ -51,12 +51,12 @@ void fill_passwd(const char* username); /* Server */ -void svr_session(int sock, int childpipe, char *remotehost, char *addrstring); +void svr_session(int sock, int childpipe); void svr_dropbear_exit(int exitcode, const char* format, va_list param); void svr_dropbear_log(int priority, const char* format, va_list param); /* Client */ -void cli_session(int sock_in, int sock_out, char *remotehost); +void cli_session(int sock_in, int sock_out); void cli_session_cleanup(); void cleantext(unsigned char* dirtytext); @@ -110,8 +110,6 @@ int sock_in; int sock_out; - unsigned char *remotehost; /* the peer hostname */ - unsigned char *remoteident; int maxfd; /* the maximum file descriptor to check with select() */ diff -r 893a9dd0b9dd -r 005530560594 svr-chansession.c --- a/svr-chansession.c Mon Aug 31 15:25:39 2009 +0000 +++ b/svr-chansession.c Tue Sep 01 16:38:26 2009 +0000 @@ -250,6 +250,17 @@ } +static struct logininfo* +chansess_login_alloc(struct ChanSess *chansess) { + char *remotehost; + struct logininfo * li; + get_socket_address(ses.sock_in, NULL, NULL, &remotehost, NULL, 1); + li = login_alloc_entry(chansess->pid, ses.authstate.username, + remotehost, chansess->tty); + m_free(remotehost); + return li; +} + /* clean a session channel */ static void closechansess(struct Channel *channel) { @@ -273,8 +284,7 @@ if (chansess->tty) { /* write the utmp/wtmp login record */ - li = login_alloc_entry(chansess->pid, ses.authstate.username, - ses.remotehost, chansess->tty); + li = chansess_login_alloc(chansess); login_logout(li); login_free_entry(li); @@ -578,7 +588,6 @@ int iscmd, int issubsys) { unsigned int cmdlen; - int is_forced; int ret; TRACE(("enter sessioncommand")) @@ -628,6 +637,8 @@ } #endif + // XXX set SSH_CONNECTION string here, since about to close socket... + if (chansess->term == NULL) { /* no pty */ ret = noptycommand(channel, chansess); @@ -737,8 +748,7 @@ /* write the utmp/wtmp login record - must be after changing the * terminal used for stdout with the dup2 above */ - li= login_alloc_entry(getpid(), ses.authstate.username, - ses.remotehost, chansess->tty); + li = chansess_login_alloc(chansess); login_login(li); login_free_entry(li); @@ -886,6 +896,8 @@ addnewvar("SSH_TTY", chansess->tty); } + + #ifdef ENABLE_SVR_PUBKEY_OPTIONS if (ses.authstate.pubkey_options && ses.authstate.pubkey_options->original_command) { diff -r 893a9dd0b9dd -r 005530560594 svr-main.c --- a/svr-main.c Mon Aug 31 15:25:39 2009 +0000 +++ b/svr-main.c Tue Sep 01 16:38:26 2009 +0000 @@ -77,22 +77,16 @@ #ifdef INETD_MODE static void main_inetd() { - - struct sockaddr_storage remoteaddr; - socklen_t remoteaddrlen; - char * addrstring = NULL; + char *host, *port = NULL; /* Set up handlers, syslog, seed random */ commonsetup(); - remoteaddrlen = sizeof(remoteaddr); - if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) { - dropbear_exit("Unable to getpeername: %s", strerror(errno)); - } - /* In case our inetd was lax in logging source addresses */ - addrstring = getaddrstring(&remoteaddr, 1); - dropbear_log(LOG_INFO, "Child connection from %s", addrstring); + get_socket_address(0, NULL, NULL, &host, &port, 0); + dropbear_log(LOG_INFO, "Child connection from %s:%s", host, port); + m_free(host); + m_free(port); /* Don't check the return value - it may just fail since inetd has * already done setsid() after forking (xinetd on Darwin appears to do @@ -102,7 +96,7 @@ /* Start service program * -1 is a dummy childpipe, just something we can close() without * mattering. */ - svr_session(0, -1, getaddrhostname(&remoteaddr), addrstring); + svr_session(0, -1); /* notreached */ } @@ -218,14 +212,13 @@ /* handle each socket which has something to say */ for (i = 0; i < listensockcount; i++) { - - struct sockaddr_storage remoteaddr; - socklen_t remoteaddrlen = 0; size_t num_unauthed_for_addr = 0; size_t num_unauthed_total = 0; - char * remote_addr_str = NULL; + char *remote_host = NULL, *remote_port = NULL; pid_t fork_ret = 0; size_t conn_idx = 0; + struct sockaddr_storage remoteaddr; + socklen_t remoteaddrlen; if (!FD_ISSET(listensocks[i], &fds)) continue; @@ -240,14 +233,14 @@ } /* Limit the number of unauthenticated connections per IP */ - remote_addr_str = getaddrstring(&remoteaddr, 0); + getaddrstring(&remoteaddr, &remote_host, NULL, 0); num_unauthed_for_addr = 0; num_unauthed_total = 0; for (j = 0; j < MAX_UNAUTH_CLIENTS; j++) { if (childpipes[j] >= 0) { num_unauthed_total++; - if (strcmp(remote_addr_str, preauth_addrs[j]) == 0) { + if (strcmp(remote_host, preauth_addrs[j]) == 0) { num_unauthed_for_addr++; } } else { @@ -280,21 +273,21 @@ /* parent */ childpipes[conn_idx] = childpipe[0]; m_close(childpipe[1]); - preauth_addrs[conn_idx] = remote_addr_str; - remote_addr_str = NULL; + preauth_addrs[conn_idx] = remote_host; + remote_host = NULL; } else { /* child */ - char * addrstring = NULL; #ifdef DEBUG_FORKGPROF extern void _start(void), etext(void); monstartup((u_long)&_start, (u_long)&etext); #endif /* DEBUG_FORKGPROF */ - m_free(remote_addr_str); - addrstring = getaddrstring(&remoteaddr, 1); - dropbear_log(LOG_INFO, "Child connection from %s", addrstring); + getaddrstring(&remoteaddr, NULL, &remote_port, 0); + dropbear_log(LOG_INFO, "Child connection from %s:%s", remote_host, remote_port); + m_free(remote_host); + m_free(remote_port); #ifndef DEBUG_NOFORK if (setsid() < 0) { @@ -310,9 +303,7 @@ m_close(childpipe[0]); /* start the session */ - svr_session(childsock, childpipe[1], - getaddrhostname(&remoteaddr), - addrstring); + svr_session(childsock, childpipe[1]); /* don't return */ dropbear_assert(0); } @@ -320,8 +311,8 @@ out: /* This section is important for the parent too */ m_close(childsock); - if (remote_addr_str) { - m_free(remote_addr_str); + if (remote_host) { + m_free(remote_host); } } } /* for(;;) loop */ diff -r 893a9dd0b9dd -r 005530560594 svr-runopts.c --- a/svr-runopts.c Mon Aug 31 15:25:39 2009 +0000 +++ b/svr-runopts.c Tue Sep 01 16:38:26 2009 +0000 @@ -296,15 +296,19 @@ } if (keepalive_arg) { - if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) { + unsigned int val; + if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) { dropbear_exit("Bad keepalive '%s'", keepalive_arg); } + opts.keepalive_secs = val; } if (idle_timeout_arg) { - if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) { + unsigned int val; + if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) { dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg); } + opts.idle_timeout_secs = val; } } diff -r 893a9dd0b9dd -r 005530560594 svr-session.c --- a/svr-session.c Mon Aug 31 15:25:39 2009 +0000 +++ b/svr-session.c Tue Sep 01 16:38:26 2009 +0000 @@ -74,27 +74,33 @@ NULL /* Null termination is mandatory. */ }; -void svr_session(int sock, int childpipe, - char* remotehost, char *addrstring) { - +void svr_session(int sock, int childpipe) { + char *host, *port; + size_t len; reseedrandom(); crypto_init(); - common_session_init(sock, sock, remotehost); + common_session_init(sock, sock); /* Initialise server specific parts of the session */ svr_ses.childpipe = childpipe; - svr_ses.addrstring = addrstring; #ifdef __uClinux__ svr_ses.server_pid = getpid(); #endif - svr_ses.addrstring = addrstring; svr_authinitialise(); chaninitialise(svr_chantypes); svr_chansessinitialise(); ses.connect_time = time(NULL); + /* for logging the remote address */ + get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0); + len = strlen(host) + strlen(port) + 2; + svr_ses.addrstring = m_malloc(len); + snprintf(svr_ses.addrstring, len, "%s:%s", host, port); + m_free(host); + m_free(port); + /* set up messages etc */ ses.remoteclosed = svr_remoteclosed;