⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monitor.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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.16 2002/06/21 05:50:51 djm Exp $");#include <openssl/dh.h>#ifdef SKEY#include <skey.h>#endif#include "ssh.h"#include "auth.h"#include "kex.h"#include "dh.h"#include "zlib.h"#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"#include "mpaux.h"/* 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;/* 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 montior 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 *);#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 u_char *hostbased_cuser = NULL;static u_char *hostbased_chost = NULL;static char *auth_method = "unknown";static int session_id2_len = 0;static u_char *session_id2 = NULL;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},#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},    {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},    {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 USE_PAM    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},#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#ifdef USE_PAM    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},#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},    {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++;	}}Authctxt *monitor_child_preauth(struct monitor *pmonitor){	struct mon_table *ent;	int authenticated = 0;	debug3("preauth child monitor started");	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);	}	authctxt = authctxt_new();	/* 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			if (!do_pam_account(authctxt->pw->pw_name, NULL))				authenticated = 0;#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);	return (authctxt);}voidmonitor_child_postauth(struct monitor *pmonitor){	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)		xfree(hostbased_chost);	key_blob = NULL;	key_bloblen = 0;	key_blobtype = MM_NOKEY;	hostbased_cuser = NULL;	hostbased_chost = NULL;}intmm_answer_moduli(int socket, Buffer *m){	DH *dh;	int min, want, max;	min = buffer_get_int(m);	want = buffer_get_int(m);	max = buffer_get_int(m);	debug3("%s: got parameters: %d %d %d",	    __func__, min, want, max);	/* We need to check here, too, in case the child got corrupted */	if (max < min || want < min || max < want)		fatal("%s: bad parameters: %d %d %d",		    __func__, min, want, max);	buffer_clear(m);	dh = choose_dh(min, want, max);	if (dh == NULL) {		buffer_put_char(m, 0);		return (0);	} else {		/* Send first bignum */		buffer_put_char(m, 1);		buffer_put_bignum2(m, dh->p);		buffer_put_bignum2(m, dh->g);		DH_free(dh);	}	mm_request_send(socket, MONITOR_ANS_MODULI, m);	return (0);}intmm_answer_sign(int socket, Buffer *m){	Key *key;	u_char *p;	u_char *signature;	u_int siglen, datlen;	int keyid;	debug3("%s", __func__);	keyid = buffer_get_int(m);	p = buffer_get_string(m, &datlen);	if (datlen != 20)		fatal("%s: data length incorrect: %d", __func__, datlen);	/* save session id, it will be passed on the first call */	if (session_id2_len == 0) {		session_id2_len = datlen;		session_id2 = xmalloc(session_id2_len);		memcpy(session_id2, p, session_id2_len);	}	if ((key = get_hostkey_by_index(keyid)) == NULL)		fatal("%s: no hostkey from index %d", __func__, keyid);	if (key_sign(key, &signature, &siglen, p, datlen) < 0)		fatal("%s: key_sign failed", __func__);	debug3("%s: signature %p(%d)", __func__, signature, siglen);	buffer_clear(m);	buffer_put_string(m, signature, siglen);	xfree(p);	xfree(signature);	mm_request_send(socket, MONITOR_ANS_SIGN, m);	/* Turn on permissions for getpwnam */	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);	return (0);}/* Retrieves the password entry and also checks if the user is permitted */intmm_answer_pwnamallow(int socket, Buffer *m){	char *login;	struct passwd *pwent;	int allowed = 0;	debug3("%s", __func__);	if (authctxt->attempt++ != 0)		fatal("%s: multiple attempts for getpwnam", __func__);	login = buffer_get_string(m, NULL);	pwent = getpwnamallow(login);	authctxt->user = xstrdup(login);	setproctitle("%s [priv]", pwent ? login : "unknown");	xfree(login);	buffer_clear(m);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -