X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/b8e04133c48243a05f5ced1731deef2ad2d09240..5486a45797557bd2ffca421ca5e7ad2441f4db59:/monitor.c diff --git a/monitor.c b/monitor.c index f306794d..009dcf18 100644 --- a/monitor.c +++ b/monitor.c @@ -25,7 +25,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor.c,v 1.43 2003/06/12 07:57:38 markus Exp $"); +RCSID("$OpenBSD: monitor.c,v 1.55 2004/02/05 05:37:17 dtucker Exp $"); #include @@ -59,6 +59,11 @@ RCSID("$OpenBSD: monitor.c,v 1.43 2003/06/12 07:57:38 markus Exp $"); #include "ssh2.h" #include "mpaux.h" +#ifdef GSSAPI +#include "ssh-gss.h" +static Gssctxt *gsscontext = NULL; +#endif + /* Imports */ extern ServerOptions options; extern u_int utmp_len; @@ -118,17 +123,18 @@ int mm_answer_sessid(int, Buffer *); #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); +int mm_answer_pam_account(int, Buffer *); int mm_answer_pam_init_ctx(int, Buffer *); int mm_answer_pam_query(int, Buffer *); int mm_answer_pam_respond(int, Buffer *); int mm_answer_pam_free_ctx(int, Buffer *); #endif -#ifdef KRB4 -int mm_answer_krb4(int, Buffer *); -#endif -#ifdef KRB5 -int mm_answer_krb5(int, Buffer *); +#ifdef GSSAPI +int mm_answer_gss_setup_ctx(int, Buffer *); +int mm_answer_gss_accept_ctx(int, Buffer *); +int mm_answer_gss_userok(int, Buffer *); +int mm_answer_gss_checkmic(int, Buffer *); #endif static Authctxt *authctxt; @@ -141,7 +147,7 @@ static int key_blobtype = MM_NOKEY; static char *hostbased_cuser = NULL; static char *hostbased_chost = NULL; static char *auth_method = "unknown"; -static int session_id2_len = 0; +static u_int session_id2_len = 0; static u_char *session_id2 = NULL; static pid_t monitor_child_pid; @@ -168,6 +174,7 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, @@ -183,8 +190,11 @@ struct mon_table mon_dispatch_proto20[] = { #endif {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, -#ifdef KRB5 - {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5}, +#ifdef GSSAPI + {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, + {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, #endif {0, 0, NULL} }; @@ -217,16 +227,11 @@ struct mon_table mon_dispatch_proto15[] = { #endif #ifdef USE_PAM {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, -#endif -#ifdef KRB4 - {MONITOR_REQ_KRB4, MON_ONCE|MON_AUTH, mm_answer_krb4}, -#endif -#ifdef KRB5 - {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5}, #endif {0, 0, NULL} }; @@ -269,14 +274,17 @@ monitor_permit_authentications(int permit) } } -Authctxt * -monitor_child_preauth(struct monitor *pmonitor) +void +monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) { struct mon_table *ent; int authenticated = 0; debug3("preauth child monitor started"); + authctxt = _authctxt; + memset(authctxt, 0, sizeof(*authctxt)); + if (compat20) { mon_dispatch = mon_dispatch_proto20; @@ -289,8 +297,6 @@ monitor_child_preauth(struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); } - authctxt = authctxt_new(); - /* The first few requests do not require asynchronous access */ while (!authenticated) { authenticated = monitor_read(pmonitor, mon_dispatch, &ent); @@ -301,6 +307,18 @@ monitor_child_preauth(struct monitor *pmonitor) if (authctxt->pw->pw_uid == 0 && !auth_root_allowed(auth_method)) authenticated = 0; +#ifdef USE_PAM + /* PAM needs to perform account checks after auth */ + if (options.use_pam && authenticated) { + Buffer m; + + buffer_init(&m); + mm_request_receive_expect(pmonitor->m_sendfd, + MONITOR_REQ_PAM_ACCOUNT, &m); + authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m); + buffer_free(&m); + } +#endif } if (ent->flags & MON_AUTHDECIDE) { @@ -318,8 +336,6 @@ monitor_child_preauth(struct monitor *pmonitor) __func__, authctxt->user); mm_get_keystate(pmonitor); - - return (authctxt); } static void @@ -348,7 +364,6 @@ monitor_child_postauth(struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -552,6 +567,7 @@ mm_answer_pwnamallow(int socket, Buffer *m) if (pwent == NULL) { buffer_put_char(m, 0); + authctxt->pw = fakepw(); goto out; } @@ -635,7 +651,7 @@ mm_answer_authpassword(int socket, Buffer *m) passwd = buffer_get_string(m, &plen); /* Only authenticate if the context is valid */ authenticated = options.password_authentication && - auth_password(authctxt, passwd) && authctxt->valid; + auth_password(authctxt, passwd); memset(passwd, 0, strlen(passwd)); xfree(passwd); @@ -767,7 +783,7 @@ int mm_answer_pam_start(int socket, Buffer *m) { char *user; - + if (!options.use_pam) fatal("UsePAM not set, but ended up in %s anyway", __func__); @@ -777,9 +793,28 @@ mm_answer_pam_start(int socket, Buffer *m) xfree(user); + monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); + return (0); } +int +mm_answer_pam_account(int socket, Buffer *m) +{ + u_int ret; + + if (!options.use_pam) + fatal("UsePAM not set, but ended up in %s anyway", __func__); + + ret = do_pam_account(); + + buffer_put_int(m, ret); + + mm_request_send(socket, MONITOR_ANS_PAM_ACCOUNT, m); + + return (ret); +} + static void *sshpam_ctxt, *sshpam_authok; extern KbdintDevice sshpam_device; @@ -914,7 +949,7 @@ mm_answer_keyallowed(int socket, Buffer *m) debug3("%s: key_from_blob: %p", __func__, key); - if (key != NULL && authctxt->pw != NULL) { + if (key != NULL && authctxt->valid) { switch(type) { case MM_USERKEY: allowed = options.pubkey_authentication && @@ -1152,7 +1187,7 @@ mm_record_login(Session *s, struct passwd *pw) if (getpeername(packet_get_connection_in(), (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); - fatal_cleanup(); + cleanup_exit(255); } } /* Record that there was a login on that tty from the remote host. */ @@ -1167,7 +1202,6 @@ 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); - fatal_remove_cleanup(session_pty_cleanup2, (void *)s); session_pty_cleanup2(s); } s->used = 0; @@ -1192,7 +1226,6 @@ mm_answer_pty(int socket, Buffer *m) res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); if (res == 0) goto error; - fatal_add_cleanup(session_pty_cleanup2, (void *)s); pty_setowner(authctxt->pw, s->tty); buffer_put_int(m, 1); @@ -1428,91 +1461,6 @@ mm_answer_rsa_response(int socket, Buffer *m) return (success); } -#ifdef KRB4 -int -mm_answer_krb4(int socket, Buffer *m) -{ - KTEXT_ST auth, reply; - char *client, *p; - int success; - u_int alen; - - reply.length = auth.length = 0; - - p = buffer_get_string(m, &alen); - if (alen >= MAX_KTXT_LEN) - fatal("%s: auth too large", __func__); - memcpy(auth.dat, p, alen); - auth.length = alen; - memset(p, 0, alen); - xfree(p); - - success = options.kerberos_authentication && - authctxt->valid && - auth_krb4(authctxt, &auth, &client, &reply); - - memset(auth.dat, 0, alen); - buffer_clear(m); - buffer_put_int(m, success); - - if (success) { - buffer_put_cstring(m, client); - buffer_put_string(m, reply.dat, reply.length); - if (client) - xfree(client); - if (reply.length) - memset(reply.dat, 0, reply.length); - } - - debug3("%s: sending result %d", __func__, success); - mm_request_send(socket, MONITOR_ANS_KRB4, m); - - auth_method = "kerberos"; - - /* Causes monitor loop to terminate if authenticated */ - return (success); -} -#endif - -#ifdef KRB5 -int -mm_answer_krb5(int socket, Buffer *m) -{ - krb5_data tkt, reply; - char *client_user; - u_int len; - int success; - - /* use temporary var to avoid size issues on 64bit arch */ - tkt.data = buffer_get_string(m, &len); - tkt.length = len; - - success = options.kerberos_authentication && - authctxt->valid && - auth_krb5(authctxt, &tkt, &client_user, &reply); - - if (tkt.length) - xfree(tkt.data); - - buffer_clear(m); - buffer_put_int(m, success); - - if (success) { - buffer_put_cstring(m, client_user); - buffer_put_string(m, reply.data, reply.length); - if (client_user) - xfree(client_user); - if (reply.length) - xfree(reply.data); - } - mm_request_send(socket, MONITOR_ANS_KRB5, m); - - auth_method = "kerberos"; - - return success; -} -#endif - int mm_answer_term(int socket, Buffer *req) { @@ -1760,6 +1708,7 @@ monitor_init(void) mon = xmalloc(sizeof(*mon)); + mon->m_pid = 0; monitor_socketpair(pair); mon->m_recvfd = pair[0]; @@ -1787,3 +1736,107 @@ monitor_reinit(struct monitor *mon) mon->m_recvfd = pair[0]; mon->m_sendfd = pair[1]; } + +#ifdef GSSAPI +int +mm_answer_gss_setup_ctx(int socket, Buffer *m) +{ + gss_OID_desc oid; + OM_uint32 major; + u_int len; + + oid.elements = buffer_get_string(m, &len); + oid.length = len; + + major = ssh_gssapi_server_ctx(&gsscontext, &oid); + + xfree(oid.elements); + + buffer_clear(m); + buffer_put_int(m, major); + + mm_request_send(socket,MONITOR_ANS_GSSSETUP, m); + + /* Now we have a context, enable the step */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); + + return (0); +} + +int +mm_answer_gss_accept_ctx(int socket, Buffer *m) +{ + gss_buffer_desc in; + gss_buffer_desc out = GSS_C_EMPTY_BUFFER; + OM_uint32 major,minor; + OM_uint32 flags = 0; /* GSI needs this */ + u_int len; + + in.value = buffer_get_string(m, &len); + in.length = len; + major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); + xfree(in.value); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_string(m, out.value, out.length); + buffer_put_int(m, flags); + mm_request_send(socket, MONITOR_ANS_GSSSTEP, m); + + gss_release_buffer(&minor, &out); + + 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); + } + return (0); +} + +int +mm_answer_gss_checkmic(int socket, Buffer *m) +{ + gss_buffer_desc gssbuf, mic; + OM_uint32 ret; + u_int len; + + gssbuf.value = buffer_get_string(m, &len); + gssbuf.length = len; + mic.value = buffer_get_string(m, &len); + mic.length = len; + + ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); + + xfree(gssbuf.value); + xfree(mic.value); + + buffer_clear(m); + buffer_put_int(m, ret); + + mm_request_send(socket, MONITOR_ANS_GSSCHECKMIC, m); + + if (!GSS_ERROR(ret)) + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); + + return (0); +} + +int +mm_answer_gss_userok(int socket, Buffer *m) +{ + int authenticated; + + authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); + + buffer_clear(m); + buffer_put_int(m, authenticated); + + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(socket, MONITOR_ANS_GSSUSEROK, m); + + auth_method="gssapi-with-mic"; + + /* Monitor loop will terminate if authenticated */ + return (authenticated); +} +#endif /* GSSAPI */