dcesrv_auth.c

来自「samba最新软件」· C语言 代码 · 共 533 行 · 第 1/2 页

C
533
字号
/*    Unix SMB/CIFS implementation.   server side dcerpc authentication code   Copyright (C) Andrew Tridgell 2003   Copyright (C) Stefan (metze) Metzmacher 2004   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "rpc_server/dcerpc_server.h"#include "rpc_server/dcerpc_server_proto.h"#include "librpc/rpc/dcerpc_proto.h"#include "librpc/gen_ndr/ndr_dcerpc.h"#include "auth/credentials/credentials.h"#include "auth/gensec/gensec.h"#include "param/param.h"/*  parse any auth information from a dcerpc bind request  return false if we can't handle the auth request for some   reason (in which case we send a bind_nak)*/bool dcesrv_auth_bind(struct dcesrv_call_state *call){	struct cli_credentials *server_credentials;	struct ncacn_packet *pkt = &call->pkt;	struct dcesrv_connection *dce_conn = call->conn;	struct dcesrv_auth *auth = &dce_conn->auth_state;	NTSTATUS status;	enum ndr_err_code ndr_err;	if (pkt->u.bind.auth_info.length == 0) {		dce_conn->auth_state.auth_info = NULL;		return true;	}	dce_conn->auth_state.auth_info = talloc(dce_conn, struct dcerpc_auth);	if (!dce_conn->auth_state.auth_info) {		return false;	}	ndr_err = ndr_pull_struct_blob(&pkt->u.bind.auth_info,				       call, NULL,				       dce_conn->auth_state.auth_info,				       (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return false;	}	status = gensec_server_start(dce_conn, call->event_ctx, call->conn->dce_ctx->lp_ctx, call->msg_ctx, &auth->gensec_security);	if (!NT_STATUS_IS_OK(status)) {		DEBUG(1, ("Failed to start GENSEC for DCERPC server: %s\n", nt_errstr(status)));		return false;	}	server_credentials 		= cli_credentials_init(call);	if (!server_credentials) {		DEBUG(1, ("Failed to init server credentials\n"));		return false;	}		cli_credentials_set_conf(server_credentials, call->conn->dce_ctx->lp_ctx);	status = cli_credentials_set_machine_account(server_credentials, call->conn->dce_ctx->lp_ctx);	if (!NT_STATUS_IS_OK(status)) {		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));		talloc_free(server_credentials);		server_credentials = NULL;	}	gensec_set_credentials(auth->gensec_security, server_credentials);	status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_info->auth_type, 					       auth->auth_info->auth_level);	if (!NT_STATUS_IS_OK(status)) {		DEBUG(1, ("Failed to start GENSEC mechanism for DCERPC server: auth_type=%d, auth_level=%d: %s\n", 			  (int)auth->auth_info->auth_type,			  (int)auth->auth_info->auth_level,			  nt_errstr(status)));		return false;	}	return true;}/*  add any auth information needed in a bind ack, and process the authentication  information found in the bind.*/NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt){	struct dcesrv_connection *dce_conn = call->conn;	NTSTATUS status;	if (!call->conn->auth_state.gensec_security) {		return NT_STATUS_OK;	}	status = gensec_update(dce_conn->auth_state.gensec_security,			       call,			       dce_conn->auth_state.auth_info->credentials, 			       &dce_conn->auth_state.auth_info->credentials);		if (NT_STATUS_IS_OK(status)) {		status = gensec_session_info(dce_conn->auth_state.gensec_security,					     &dce_conn->auth_state.session_info);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));			return status;		}		/* Now that we are authenticated, go back to the generic session key... */		dce_conn->auth_state.session_key = dcesrv_generic_session_key;		return NT_STATUS_OK;	} else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {		dce_conn->auth_state.auth_info->auth_pad_length = 0;		dce_conn->auth_state.auth_info->auth_reserved = 0;		return NT_STATUS_OK;	} else {		DEBUG(2, ("Failed to start dcesrv auth negotiate: %s\n", nt_errstr(status)));		return status;	}}/*  process the final stage of a auth request*/bool dcesrv_auth_auth3(struct dcesrv_call_state *call){	struct ncacn_packet *pkt = &call->pkt;	struct dcesrv_connection *dce_conn = call->conn;	NTSTATUS status;	enum ndr_err_code ndr_err;	/* We can't work without an existing gensec state, and an new blob to feed it */	if (!dce_conn->auth_state.auth_info ||	    !dce_conn->auth_state.gensec_security ||	    pkt->u.auth3.auth_info.length == 0) {		return false;	}	ndr_err = ndr_pull_struct_blob(&pkt->u.auth3.auth_info,				       call, NULL,				       dce_conn->auth_state.auth_info,				       (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return false;	}	/* Pass the extra data we got from the client down to gensec for processing */	status = gensec_update(dce_conn->auth_state.gensec_security,			       call,			       dce_conn->auth_state.auth_info->credentials, 			       &dce_conn->auth_state.auth_info->credentials);	if (NT_STATUS_IS_OK(status)) {		status = gensec_session_info(dce_conn->auth_state.gensec_security,					     &dce_conn->auth_state.session_info);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));			return false;		}		/* Now that we are authenticated, go back to the generic session key... */		dce_conn->auth_state.session_key = dcesrv_generic_session_key;		return true;	} else {		DEBUG(4, ("dcesrv_auth_auth3: failed to authenticate: %s\n", 			  nt_errstr(status)));		return false;	}	return true;}/*  parse any auth information from a dcerpc alter request  return false if we can't handle the auth request for some   reason (in which case we send a bind_nak (is this true for here?))*/bool dcesrv_auth_alter(struct dcesrv_call_state *call){	struct ncacn_packet *pkt = &call->pkt;	struct dcesrv_connection *dce_conn = call->conn;	enum ndr_err_code ndr_err;	/* on a pure interface change there is no auth blob */	if (pkt->u.alter.auth_info.length == 0) {		return true;	}	/* We can't work without an existing gensec state */	if (!dce_conn->auth_state.gensec_security) {		return false;	}	dce_conn->auth_state.auth_info = talloc(dce_conn, struct dcerpc_auth);	if (!dce_conn->auth_state.auth_info) {		return false;	}	ndr_err = ndr_pull_struct_blob(&pkt->u.alter.auth_info,				       call, NULL,				       dce_conn->auth_state.auth_info,				       (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return false;	}	return true;}/*  add any auth information needed in a alter ack, and process the authentication  information found in the alter.*/NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt){	struct dcesrv_connection *dce_conn = call->conn;	NTSTATUS status;	/* on a pure interface change there is no auth_info structure	   setup */	if (!call->conn->auth_state.auth_info ||	    dce_conn->auth_state.auth_info->credentials.length == 0) {		return NT_STATUS_OK;	}	if (!call->conn->auth_state.gensec_security) {		return NT_STATUS_INVALID_PARAMETER;	}	status = gensec_update(dce_conn->auth_state.gensec_security,			       call,			       dce_conn->auth_state.auth_info->credentials, 			       &dce_conn->auth_state.auth_info->credentials);	if (NT_STATUS_IS_OK(status)) {		status = gensec_session_info(dce_conn->auth_state.gensec_security,					     &dce_conn->auth_state.session_info);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));			return status;		}		/* Now that we are authenticated, got back to the generic session key... */		dce_conn->auth_state.session_key = dcesrv_generic_session_key;		return NT_STATUS_OK;	} else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {		dce_conn->auth_state.auth_info->auth_pad_length = 0;		dce_conn->auth_state.auth_info->auth_reserved = 0;		return NT_STATUS_OK;	}

⌨️ 快捷键说明

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