📄 monitor.c
字号:
/* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "includes.h"RCSID("$OpenBSD: monitor.c,v 1.62 2005/01/30 11:18:08 dtucker Exp $");#include <openssl/dh.h>#ifdef SKEY#include <skey.h>#endif#include "ssh.h"#include "auth.h"#include "kex.h"#include "dh.h"#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */#undef TARGET_OS_MAC#include "zlib.h"#define TARGET_OS_MAC 1#else#include "zlib.h"#endif#include "packet.h"#include "auth-options.h"#include "sshpty.h"#include "channels.h"#include "session.h"#include "sshlogin.h"#include "canohost.h"#include "log.h"#include "servconf.h"#include "monitor.h"#include "monitor_mm.h"#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/* Imports */extern ServerOptions options;extern u_int utmp_len;extern Newkeys *current_keys[];extern z_stream incoming_stream;extern z_stream outgoing_stream;extern u_char session_id[];extern Buffer input, output;extern Buffer auth_debug;extern int auth_debug_init;extern Buffer loginmsg;/* State exported from the child */struct { z_stream incoming; z_stream outgoing; u_char *keyin; u_int keyinlen; u_char *keyout; u_int keyoutlen; u_char *ivin; u_int ivinlen; u_char *ivout; u_int ivoutlen; u_char *ssh1key; u_int ssh1keylen; int ssh1cipher; int ssh1protoflags; u_char *input; u_int ilen; u_char *output; u_int olen;} child_state;/* Functions on the monitor that answer unprivileged requests */int mm_answer_moduli(int, Buffer *);int mm_answer_sign(int, Buffer *);int mm_answer_pwnamallow(int, Buffer *);int mm_answer_auth2_read_banner(int, Buffer *);int mm_answer_authserv(int, Buffer *);int mm_answer_authpassword(int, Buffer *);int mm_answer_bsdauthquery(int, Buffer *);int mm_answer_bsdauthrespond(int, Buffer *);int mm_answer_skeyquery(int, Buffer *);int mm_answer_skeyrespond(int, Buffer *);int mm_answer_keyallowed(int, Buffer *);int mm_answer_keyverify(int, Buffer *);int mm_answer_pty(int, Buffer *);int mm_answer_pty_cleanup(int, Buffer *);int mm_answer_term(int, Buffer *);int mm_answer_rsa_keyallowed(int, Buffer *);int mm_answer_rsa_challenge(int, Buffer *);int mm_answer_rsa_response(int, Buffer *);int mm_answer_sesskey(int, Buffer *);int mm_answer_sessid(int, Buffer *);#ifdef USE_PAMint 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 GSSAPIint 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#ifdef SSH_AUDIT_EVENTSint mm_answer_audit_event(int, Buffer *);int mm_answer_audit_command(int, Buffer *);#endifstatic Authctxt *authctxt;static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth *//* local state for key verify */static u_char *key_blob = NULL;static u_int key_bloblen = 0;static int key_blobtype = MM_NOKEY;static char *hostbased_cuser = NULL;static char *hostbased_chost = NULL;static char *auth_method = "unknown";static u_int session_id2_len = 0;static u_char *session_id2 = NULL;static pid_t monitor_child_pid;struct mon_table { enum monitor_reqtype type; int flags; int (*f)(int, Buffer *);};#define MON_ISAUTH 0x0004 /* Required for Authentication */#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */#define MON_ONCE 0x0010 /* Disable after calling */#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE)#define MON_PERMIT 0x1000 /* Request is permitted */struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {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}, {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},#endif#ifdef SSH_AUDIT_EVENTS {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},#endif#ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},#endif {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},#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}};struct mon_table mon_dispatch_postauth20[] = { {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_SIGN, 0, mm_answer_sign}, {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, {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, mm_answer_audit_command},#endif {0, 0, NULL}};struct mon_table mon_dispatch_proto15[] = { {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {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_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},#endif#ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},#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 SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},#endif {0, 0, NULL}};struct mon_table mon_dispatch_postauth15[] = { {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, {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_ONCE, mm_answer_audit_command},#endif {0, 0, NULL}};struct mon_table *mon_dispatch;/* Specifies if a certain message is allowed at the moment */static voidmonitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit){ while (ent->f != NULL) { if (ent->type == type) { ent->flags &= ~MON_PERMIT; ent->flags |= permit ? MON_PERMIT : 0; return; } ent++; }}static voidmonitor_permit_authentications(int permit){ struct mon_table *ent = mon_dispatch; while (ent->f != NULL) { if (ent->flags & MON_AUTH) { ent->flags &= ~MON_PERMIT; ent->flags |= permit ? MON_PERMIT : 0; } ent++; }}voidmonitor_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; /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); } else { mon_dispatch = mon_dispatch_proto15; monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); } /* The first few requests do not require asynchronous access */ while (!authenticated) { authenticated = monitor_read(pmonitor, mon_dispatch, &ent); if (authenticated) { if (!(ent->flags & MON_AUTHDECIDE)) fatal("%s: unexpected authentication from %d", __func__, ent->type); 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) { auth_log(authctxt, authenticated, auth_method, compat20 ? " ssh2" : ""); if (!authenticated) authctxt->failures++; } } if (!authctxt->valid) fatal("%s: authenticated invalid user", __func__); debug("%s: %s has been authenticated by privileged process", __func__, authctxt->user); mm_get_keystate(pmonitor);}static voidmonitor_set_child_handler(pid_t pid){ monitor_child_pid = pid;}static voidmonitor_child_handler(int sig){ kill(monitor_child_pid, sig);}voidmonitor_child_postauth(struct monitor *pmonitor){ monitor_set_child_handler(pmonitor->m_pid); signal(SIGHUP, &monitor_child_handler); signal(SIGTERM, &monitor_child_handler); if (compat20) { mon_dispatch = mon_dispatch_postauth20; /* Permit requests for moduli and signatures */ 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); } if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); } for (;;) monitor_read(pmonitor, mon_dispatch, NULL);}voidmonitor_sync(struct monitor *pmonitor){ if (options.compression) { /* The member allocation is not visible, so sync it */ mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); }}intmonitor_read(struct monitor *pmonitor, struct mon_table *ent, struct mon_table **pent){ Buffer m; int ret; u_char type; buffer_init(&m); mm_request_receive(pmonitor->m_sendfd, &m); type = buffer_get_char(&m); debug3("%s: checking request %d", __func__, type); while (ent->f != NULL) { if (ent->type == type) break; ent++; } if (ent->f != NULL) { if (!(ent->flags & MON_PERMIT)) fatal("%s: unpermitted request %d", __func__, type); ret = (*ent->f)(pmonitor->m_sendfd, &m); buffer_free(&m); /* The child may use this request only once, disable it */ if (ent->flags & MON_ONCE) { debug2("%s: %d used once, disabling now", __func__, type); ent->flags &= ~MON_PERMIT; } if (pent != NULL) *pent = ent; return ret; } fatal("%s: unsupported request: %d", __func__, type); /* NOTREACHED */ return (-1);}/* allowed key state */static intmonitor_allowed_key(u_char *blob, u_int bloblen){ /* make sure key is allowed */ if (key_blob == NULL || key_bloblen != bloblen || memcmp(key_blob, blob, key_bloblen)) return (0); return (1);}static voidmonitor_reset_key_state(void){ /* reset state */ if (key_blob != NULL) xfree(key_blob); if (hostbased_cuser != NULL) xfree(hostbased_cuser); if (hostbased_chost != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -