=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/monitor.c,v retrieving revision 1.113 retrieving revision 1.114 diff -u -r1.113 -r1.114 --- src/usr.bin/ssh/monitor.c 2011/05/23 03:30:07 1.113 +++ src/usr.bin/ssh/monitor.c 2011/06/17 21:44:30 1.114 @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.113 2011/05/23 03:30:07 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.114 2011/06/17 21:44:30 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -37,12 +37,13 @@ #include #include #include +#include #include #include #include #include - +#include "atomicio.h" #include "xmalloc.h" #include "ssh.h" #include "key.h" @@ -150,6 +151,8 @@ int mm_answer_gss_checkmic(int, Buffer *); #endif +static int monitor_read_log(struct monitor *); + static Authctxt *authctxt; static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ @@ -275,6 +278,10 @@ debug3("preauth child monitor started"); + close(pmonitor->m_recvfd); + close(pmonitor->m_log_sendfd); + pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; + authctxt = _authctxt; memset(authctxt, 0, sizeof(*authctxt)); @@ -320,6 +327,10 @@ #endif } + /* Drain any buffered messages from the child */ + while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) + ; + if (!authctxt->valid) fatal("%s: authenticated invalid user", __func__); if (strcmp(auth_method, "unknown") == 0) @@ -329,6 +340,10 @@ __func__, authctxt->user); mm_get_keystate(pmonitor); + + close(pmonitor->m_sendfd); + close(pmonitor->m_log_recvfd); + pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; } static void @@ -346,6 +361,9 @@ void monitor_child_postauth(struct monitor *pmonitor) { + close(pmonitor->m_recvfd); + pmonitor->m_recvfd = -1; + monitor_set_child_handler(pmonitor->m_pid); signal(SIGHUP, &monitor_child_handler); signal(SIGTERM, &monitor_child_handler); @@ -369,6 +387,9 @@ for (;;) monitor_read(pmonitor, mon_dispatch, NULL); + + close(pmonitor->m_sendfd); + pmonitor->m_sendfd = -1; } void @@ -380,6 +401,52 @@ } } +static int +monitor_read_log(struct monitor *pmonitor) +{ + Buffer logmsg; + u_int len, level; + char *msg; + + buffer_init(&logmsg); + + /* Read length */ + buffer_append_space(&logmsg, 4); + if (atomicio(read, pmonitor->m_log_recvfd, + buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) { + if (errno == EPIPE) { + debug("%s: child log fd closed", __func__); + close(pmonitor->m_log_recvfd); + pmonitor->m_log_recvfd = -1; + return -1; + } + fatal("%s: log fd read: %s", __func__, strerror(errno)); + } + len = buffer_get_int(&logmsg); + if (len <= 4 || len > 8192) + fatal("%s: invalid log message length %u", __func__, len); + + /* Read severity, message */ + buffer_clear(&logmsg); + buffer_append_space(&logmsg, len); + if (atomicio(read, pmonitor->m_log_recvfd, + buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) + fatal("%s: log fd read: %s", __func__, strerror(errno)); + + /* Log it */ + level = buffer_get_int(&logmsg); + msg = buffer_get_string(&logmsg, NULL); + if (log_level_name(level) == NULL) + fatal("%s: invalid log level %u (corrupted message?)", + __func__, level); + do_log2(level, "%s [preauth]", msg); + + buffer_free(&logmsg); + xfree(msg); + + return 0; +} + int monitor_read(struct monitor *pmonitor, struct mon_table *ent, struct mon_table **pent) @@ -387,7 +454,28 @@ Buffer m; int ret; u_char type; + struct pollfd pfd[2]; + for (;;) { + bzero(&pfd, sizeof(pfd)); + pfd[0].fd = pmonitor->m_sendfd; + pfd[0].events = POLLIN; + pfd[1].fd = pmonitor->m_log_recvfd; + pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; + if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) + fatal("%s: poll: %s", __func__, strerror(errno)); + if (pfd[1].revents) { + /* + * Drain all log messages before processing next + * monitor request. + */ + monitor_read_log(pmonitor); + continue; + } + if (pfd[0].revents) + break; /* Continues below */ + } + buffer_init(&m); mm_request_receive(pmonitor->m_sendfd, &m); @@ -1530,12 +1618,26 @@ } while (0) static void -monitor_socketpair(int *pair) +monitor_openfds(struct monitor *mon, int do_logfds) { + int pair[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) - fatal("%s: socketpair", __func__); + fatal("%s: socketpair: %s", __func__, strerror(errno)); FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]); + mon->m_recvfd = pair[0]; + mon->m_sendfd = pair[1]; + + if (do_logfds) { + if (pipe(pair) == -1) + fatal("%s: pipe: %s", __func__, strerror(errno)); + FD_CLOSEONEXEC(pair[0]); + FD_CLOSEONEXEC(pair[1]); + mon->m_log_recvfd = pair[0]; + mon->m_log_sendfd = pair[1]; + } else + mon->m_log_recvfd = mon->m_log_sendfd = -1; } #define MM_MEMSIZE 65536 @@ -1544,15 +1646,11 @@ monitor_init(void) { struct monitor *mon; - int pair[2]; mon = xcalloc(1, sizeof(*mon)); - monitor_socketpair(pair); + monitor_openfds(mon, 1); - mon->m_recvfd = pair[0]; - mon->m_sendfd = pair[1]; - /* Used to share zlib space across processes */ if (options.compression) { mon->m_zback = mm_create(NULL, MM_MEMSIZE); @@ -1568,12 +1666,7 @@ void monitor_reinit(struct monitor *mon) { - int pair[2]; - - monitor_socketpair(pair); - - mon->m_recvfd = pair[0]; - mon->m_sendfd = pair[1]; + monitor_openfds(mon, 0); } #ifdef GSSAPI