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 + -
显示快捷键?