X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/6039eeef82bbc5468a6b755e8ab4028ce9f692cd..ba52fb567358257efd557b4524d9584f9051214f:/monitor.c diff --git a/monitor.c b/monitor.c index d6df656b..83b3765a 100644 --- a/monitor.c +++ b/monitor.c @@ -1,3 +1,4 @@ +/* $OpenBSD: monitor.c,v 1.88 2006/08/12 20:46:46 miod Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -25,16 +26,36 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor.c,v 1.61 2004/07/17 05:31:41 dtucker Exp $"); -#include +#include +#include +#include +#include "openbsd-compat/sys-tree.h" +#include + +#include +#include +#ifdef HAVE_PATHS_H +#include +#endif +#include +#include +#include +#include #ifdef SKEY #include #endif +#include + +#include "xmalloc.h" #include "ssh.h" +#include "key.h" +#include "buffer.h" +#include "hostfile.h" #include "auth.h" +#include "cipher.h" #include "kex.h" #include "dh.h" #ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */ @@ -55,17 +76,16 @@ RCSID("$OpenBSD: monitor.c,v 1.61 2004/07/17 05:31:41 dtucker Exp $"); #include "servconf.h" #include "monitor.h" #include "monitor_mm.h" +#ifdef GSSAPI +#include "ssh-gss.h" +#endif #include "monitor_wrap.h" #include "monitor_fdpass.h" -#include "xmalloc.h" #include "misc.h" -#include "buffer.h" -#include "bufaux.h" #include "compat.h" #include "ssh2.h" #ifdef GSSAPI -#include "ssh-gss.h" static Gssctxt *gsscontext = NULL; #endif @@ -171,6 +191,7 @@ struct mon_table { #define MON_ISAUTH 0x0004 /* Required for Authentication */ #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ #define MON_ONCE 0x0010 /* Disable after calling */ +#define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) @@ -192,11 +213,11 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, #endif #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, 0, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, - {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, + {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, #endif #ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, @@ -231,13 +252,13 @@ struct mon_table mon_dispatch_proto15[] = { {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, - {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed}, - {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, + {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed}, + {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, - {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, + {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, #endif #ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, @@ -252,7 +273,7 @@ struct mon_table mon_dispatch_proto15[] = { {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, #endif #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, 0, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, #endif {0, 0, NULL} }; @@ -263,7 +284,7 @@ struct mon_table mon_dispatch_postauth15[] = { {MONITOR_REQ_TERM, 0, mm_answer_term}, #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, + {MONITOR_REQ_AUDIT_COMMAND, MON_ONCE, mm_answer_audit_command}, #endif {0, 0, NULL} }; @@ -310,6 +331,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) authctxt = _authctxt; memset(authctxt, 0, sizeof(*authctxt)); + authctxt->loginmsg = &loginmsg; + if (compat20) { mon_dispatch = mon_dispatch_proto20; @@ -324,6 +347,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) /* The first few requests do not require asynchronous access */ while (!authenticated) { + auth_method = "unknown"; authenticated = monitor_read(pmonitor, mon_dispatch, &ent); if (authenticated) { if (!(ent->flags & MON_AUTHDECIDE)) @@ -346,7 +370,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) #endif } - if (ent->flags & MON_AUTHDECIDE) { + if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(authctxt, authenticated, auth_method, compat20 ? " ssh2" : ""); if (!authenticated) @@ -356,6 +380,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) if (!authctxt->valid) fatal("%s: authenticated invalid user", __func__); + if (strcmp(auth_method, "unknown") == 0) + fatal("%s: authentication method name unknown", __func__); debug("%s: %s has been authenticated by privileged process", __func__, authctxt->user); @@ -535,7 +561,11 @@ mm_answer_sign(int sock, Buffer *m) keyid = buffer_get_int(m); p = buffer_get_string(m, &datlen); - if (datlen != 20) + /* + * Supported KEX types will only return SHA1 (20 byte) or + * SHA256 (32 byte) hashes + */ + if (datlen != 20 && datlen != 32) fatal("%s: data length incorrect: %u", __func__, datlen); /* save session id, it will be passed on the first call */ @@ -629,7 +659,7 @@ mm_answer_pwnamallow(int sock, Buffer *m) monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); #endif #ifdef SSH_AUDIT_EVENTS - monitor_permit(mon_dispatch, MONITOR_REQ_AUDIT_EVENT, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_AUDIT_COMMAND, 1); #endif return (0); @@ -832,9 +862,7 @@ mm_answer_pam_account(int sock, Buffer *m) ret = do_pam_account(); buffer_put_int(m, ret); - buffer_append(&loginmsg, "\0", 1); - buffer_put_cstring(m, buffer_ptr(&loginmsg)); - buffer_clear(&loginmsg); + buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); @@ -867,8 +895,8 @@ int mm_answer_pam_query(int sock, Buffer *m) { char *name, *info, **prompts; - u_int num, *echo_on; - int i, ret; + u_int i, num, *echo_on; + int ret; debug3("%s", __func__); sshpam_authok = NULL; @@ -893,6 +921,7 @@ mm_answer_pam_query(int sock, Buffer *m) xfree(prompts); if (echo_on != NULL) xfree(echo_on); + auth_method = "keyboard-interactive/pam"; mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); return (0); } @@ -901,14 +930,14 @@ int mm_answer_pam_respond(int sock, Buffer *m) { char **resp; - u_int num; - int i, ret; + u_int i, num; + int ret; debug3("%s", __func__); sshpam_authok = NULL; num = buffer_get_int(m); if (num > 0) { - resp = xmalloc(num * sizeof(char *)); + resp = xcalloc(num, sizeof(char *)); for (i = 0; i < num; ++i) resp[i] = buffer_get_string(m, NULL); ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); @@ -935,6 +964,7 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) (sshpam_device.free_ctx)(sshpam_ctxt); buffer_clear(m); mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); + auth_method = "keyboard-interactive/pam"; return (sshpam_authok == sshpam_ctxt); } #endif @@ -976,21 +1006,24 @@ mm_answer_keyallowed(int sock, Buffer *m) debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->valid) { - switch(type) { + switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); + auth_method = "publickey"; break; case MM_HOSTKEY: allowed = options.hostbased_authentication && hostbased_key_allowed(authctxt->pw, cuser, chost, key); + auth_method = "hostbased"; break; case MM_RSAHOSTKEY: key->type = KEY_RSA1; /* XXX */ allowed = options.rhosts_rsa_authentication && auth_rhosts_rsa_key_allowed(authctxt->pw, cuser, chost, key); + auth_method = "rsa"; break; default: fatal("%s: unknown key type %d", __func__, type); @@ -1010,6 +1043,12 @@ mm_answer_keyallowed(int sock, Buffer *m) key_blobtype = type; hostbased_cuser = cuser; hostbased_chost = chost; + } else { + /* Log failed attempt */ + auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : ""); + xfree(blob); + xfree(cuser); + xfree(chost); } debug3("%s: key %p is %s", @@ -1211,7 +1250,7 @@ mm_record_login(Session *s, struct passwd *pw) fromlen = sizeof(from); if (packet_connection_is_on_socket()) { if (getpeername(packet_get_connection_in(), - (struct sockaddr *) & from, &fromlen) < 0) { + (struct sockaddr *)&from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); cleanup_exit(255); } @@ -1227,7 +1266,7 @@ mm_session_close(Session *s) { debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); if (s->ttyfd != -1) { - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); + debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); session_pty_cleanup2(s); } s->used = 0; @@ -1287,7 +1326,7 @@ mm_answer_pty(int sock, Buffer *m) /* no need to dup() because nobody closes ptyfd */ s->ptymaster = s->ptyfd; - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); + debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); return (0); @@ -1322,7 +1361,7 @@ mm_answer_sesskey(int sock, Buffer *m) int rsafail; /* Turn off permissions */ - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0); if ((p = BN_new()) == NULL) fatal("%s: BN_new", __func__); @@ -1374,6 +1413,7 @@ mm_answer_rsa_keyallowed(int sock, Buffer *m) debug3("%s entering", __func__); + auth_method = "rsa"; if (options.rsa_authentication && authctxt->valid) { if ((client_n = BN_new()) == NULL) fatal("%s: BN_new", __func__); @@ -1523,7 +1563,6 @@ mm_answer_audit_event(int socket, Buffer *m) debug3("%s entering", __func__); event = buffer_get_int(m); - buffer_free(m); switch(event) { case SSH_AUTH_FAIL_PUBKEY: case SSH_AUTH_FAIL_HOSTBASED: @@ -1552,7 +1591,6 @@ mm_answer_audit_command(int socket, Buffer *m) /* sanity check command, if so how? */ audit_run_command(cmd); xfree(cmd); - buffer_free(m); return (0); } #endif /* SSH_AUDIT_EVENTS */ @@ -1612,8 +1650,7 @@ mm_get_kex(Buffer *m) void *blob; u_int bloblen; - kex = xmalloc(sizeof(*kex)); - memset(kex, 0, sizeof(*kex)); + kex = xcalloc(1, sizeof(*kex)); kex->session_id = buffer_get_string(m, &kex->session_id_len); if ((session_id2 == NULL) || (kex->session_id_len != session_id2_len) || @@ -1623,6 +1660,7 @@ mm_get_kex(Buffer *m) kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; kex->server = 1; kex->hostkey_type = buffer_get_int(m); kex->kex_type = buffer_get_int(m); @@ -1782,9 +1820,8 @@ monitor_init(void) struct monitor *mon; int pair[2]; - mon = xmalloc(sizeof(*mon)); + mon = xcalloc(1, sizeof(*mon)); - mon->m_pid = 0; monitor_socketpair(pair); mon->m_recvfd = pair[0]; @@ -1831,7 +1868,7 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m) buffer_clear(m); buffer_put_int(m, major); - mm_request_send(sock,MONITOR_ANS_GSSSETUP, m); + mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); /* Now we have a context, enable the step */ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); @@ -1844,7 +1881,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) { gss_buffer_desc in; gss_buffer_desc out = GSS_C_EMPTY_BUFFER; - OM_uint32 major,minor; + OM_uint32 major, minor; OM_uint32 flags = 0; /* GSI needs this */ u_int len; @@ -1861,7 +1898,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) gss_release_buffer(&minor, &out); - if (major==GSS_S_COMPLETE) { + if (major == GSS_S_COMPLETE) { monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -1910,7 +1947,7 @@ mm_answer_gss_userok(int sock, Buffer *m) debug3("%s: sending result %d", __func__, authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); - auth_method="gssapi-with-mic"; + auth_method = "gssapi-with-mic"; /* Monitor loop will terminate if authenticated */ return (authenticated);