diff options
-rw-r--r-- | cli-kex.c | 2 | ||||
-rw-r--r-- | cli-main.c | 11 | ||||
-rw-r--r-- | cli-runopts.c | 10 | ||||
-rw-r--r-- | cli-session.c | 4 | ||||
-rw-r--r-- | common-session.c | 4 | ||||
-rw-r--r-- | dbutil.c | 111 | ||||
-rw-r--r-- | dbutil.h | 6 | ||||
-rw-r--r-- | debug.h | 2 | ||||
-rw-r--r-- | options.h | 4 | ||||
-rw-r--r-- | packet.c | 17 | ||||
-rw-r--r-- | runopts.h | 4 | ||||
-rw-r--r-- | session.h | 8 | ||||
-rw-r--r-- | svr-chansession.c | 22 | ||||
-rw-r--r-- | svr-main.c | 49 | ||||
-rw-r--r-- | svr-runopts.c | 8 | ||||
-rw-r--r-- | svr-session.c | 18 |
16 files changed, 141 insertions, 139 deletions
@@ -304,7 +304,7 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) { 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, ' '); @@ -45,8 +45,6 @@ int main(int argc, char ** argv) { 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 @@ int main(int argc, char ** argv) { 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 --git a/cli-runopts.c b/cli-runopts.c index eab33b7..e32d2fb 100644 --- a/cli-runopts.c +++ b/cli-runopts.c @@ -378,15 +378,19 @@ void cli_getopts(int argc, char ** argv) { } } 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 @@ multihop_passthrough_args() { 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 --git a/cli-session.c b/cli-session.c index ed58a11..96a0929 100644 --- a/cli-session.c +++ b/cli-session.c @@ -82,13 +82,13 @@ static const struct ChanType *cli_chantypes[] = { 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 --git a/common-session.c b/common-session.c index 1348da2..f2ad436 100644 --- a/common-session.c +++ b/common-session.c @@ -52,12 +52,10 @@ int exitflag = 0; /* GLOBAL */ /* 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); @@ -539,14 +539,47 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) { 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; - int ret; + char host[NI_MAXHOST+1], serv[NI_MAXSERV+1]; unsigned int len; + int ret; + + 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 @@ unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) { #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 (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)); + } } - 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 (ret_host) { + *ret_host = m_strdup(host); } - - 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_port) { + *ret_port = m_strdup(serv); } -#ifdef AF_INET6 - if (addr->ss_family == AF_INET6) { - len = sizeof(struct sockaddr_in6); - } -#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 @@ -46,7 +46,10 @@ void printhex(const char * label, const unsigned char * buf, int len); 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 @@ int connect_unix(const char* addr); #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); @@ -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 @@ -167,9 +167,9 @@ much traffic. */ * 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 @@ -157,9 +157,10 @@ void read_packet() { 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 @@ static int read_packet_init() { 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 @@ static int read_packet_init() { 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; } @@ -37,8 +37,8 @@ typedef struct runopts { 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; @@ -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 @@ const char* get_user_shell(); 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 @@ struct sshsession { 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 --git a/svr-chansession.c b/svr-chansession.c index 2664382..503e789 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -250,6 +250,17 @@ static int newchansess(struct Channel *channel) { } +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 @@ static void closechansess(struct Channel *channel) { 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 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, int iscmd, int issubsys) { unsigned int cmdlen; - int is_forced; int ret; TRACE(("enter sessioncommand")) @@ -628,6 +637,8 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, } #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 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) { /* 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 @@ static void execchild(void *user_data) { addnewvar("SSH_TTY", chansess->tty); } + + #ifdef ENABLE_SVR_PUBKEY_OPTIONS if (ses.authstate.pubkey_options && ses.authstate.pubkey_options->original_command) { @@ -77,22 +77,16 @@ int main(int argc, char ** argv) #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 @@ static void main_inetd() { /* 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 @@ void main_noinetd() { /* 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 @@ void main_noinetd() { } /* 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 @@ void main_noinetd() { /* 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 @@ void main_noinetd() { 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 @@ void main_noinetd() { 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 --git a/svr-runopts.c b/svr-runopts.c index 4f1355a..4e59b75 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -296,15 +296,19 @@ void svr_getopts(int argc, char ** argv) { } 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 --git a/svr-session.c b/svr-session.c index 89b16cb..a509906 100644 --- a/svr-session.c +++ b/svr-session.c @@ -74,27 +74,33 @@ static const struct ChanType *svr_chantypes[] = { 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; |