sesssetup.c
来自「samba最新软件」· C语言 代码 · 共 526 行 · 第 1/2 页
C
526 行
/* Unix SMB/CIFS implementation. Copyright (C) Andrew Tridgell 2005 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/>.*//* a composite API for making handling a generic async session setup*/#include "includes.h"#include "libcli/raw/libcliraw.h"#include "libcli/raw/raw_proto.h"#include "libcli/composite/composite.h"#include "libcli/smb_composite/smb_composite.h"#include "libcli/smb_composite/proto.h"#include "libcli/auth/libcli_auth.h"#include "auth/auth.h"#include "auth/gensec/gensec.h"#include "auth/credentials/credentials.h"#include "version.h"#include "param/param.h"struct sesssetup_state { union smb_sesssetup setup; NTSTATUS gensec_status; struct smb_composite_sesssetup *io; struct smbcli_request *req;};static int sesssetup_state_destructor(struct sesssetup_state *state){ if (state->req) { talloc_free(state->req); state->req = NULL; } return 0;}static NTSTATUS session_setup_old(struct composite_context *c, struct smbcli_session *session, struct smb_composite_sesssetup *io, struct smbcli_request **req); static NTSTATUS session_setup_nt1(struct composite_context *c, struct smbcli_session *session, struct smb_composite_sesssetup *io, struct smbcli_request **req); static NTSTATUS session_setup_spnego(struct composite_context *c, struct smbcli_session *session, struct smb_composite_sesssetup *io, struct smbcli_request **req);/* store the user session key for a transport*/static void set_user_session_key(struct smbcli_session *session, const DATA_BLOB *session_key){ session->user_session_key = data_blob_talloc(session, session_key->data, session_key->length);}/* handler for completion of a smbcli_request sub-request*/static void request_handler(struct smbcli_request *req){ struct composite_context *c = (struct composite_context *)req->async.private; struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); struct smbcli_session *session = req->session; DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB null_data_blob = data_blob(NULL, 0); NTSTATUS session_key_err, nt_status; c->status = smb_raw_sesssetup_recv(req, state, &state->setup); state->req = NULL; switch (state->setup.old.level) { case RAW_SESSSETUP_OLD: state->io->out.vuid = state->setup.old.out.vuid; /* This doesn't work, as this only happens on old * protocols, where this comparison won't match. */ if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) { /* we neet to reset the vuid for a new try */ session->vuid = 0; if (cli_credentials_wrong_password(state->io->in.credentials)) { nt_status = session_setup_old(c, session, state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; } } } break; case RAW_SESSSETUP_NT1: state->io->out.vuid = state->setup.nt1.out.vuid; if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) { /* we neet to reset the vuid for a new try */ session->vuid = 0; if (cli_credentials_wrong_password(state->io->in.credentials)) { nt_status = session_setup_nt1(c, session, state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; } } } break; case RAW_SESSSETUP_SPNEGO: state->io->out.vuid = state->setup.spnego.out.vuid; if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) { /* we need to reset the vuid for a new try */ session->vuid = 0; if (cli_credentials_wrong_password(state->io->in.credentials)) { nt_status = session_setup_spnego(c, session, state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; } } } if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(c->status)) { break; } if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { /* The status value here, from the earlier pass at GENSEC is * vital to the security of the system. Even if the other end * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then * you must keep feeding it blobs, or else the remote * host/attacker might avoid mutal authentication * requirements */ state->gensec_status = gensec_update(session->gensec, state, state->setup.spnego.out.secblob, &state->setup.spnego.in.secblob); c->status = state->gensec_status; if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(c->status)) { break; } } else { state->setup.spnego.in.secblob = data_blob(NULL, 0); } /* we need to do another round of session setup. We keep going until both sides are happy */ session_key_err = gensec_session_key(session->gensec, &session_key); if (NT_STATUS_IS_OK(session_key_err)) { set_user_session_key(session, &session_key); smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); } if (state->setup.spnego.in.secblob.length) { /* * set the session->vuid value only for calling * smb_raw_sesssetup_send() */ uint16_t vuid = session->vuid; session->vuid = state->io->out.vuid; state->req = smb_raw_sesssetup_send(session, &state->setup); session->vuid = vuid; composite_continue_smb(c, state->req, request_handler, c); return; } break; case RAW_SESSSETUP_SMB2: c->status = NT_STATUS_INTERNAL_ERROR; break; } /* enforce the local signing required flag */ if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { if (!session->transport->negotiate.sign_info.doing_signing && session->transport->negotiate.sign_info.mandatory_signing) { DEBUG(0, ("SMB signing required, but server does not support it\n")); c->status = NT_STATUS_ACCESS_DENIED; } } if (!NT_STATUS_IS_OK(c->status)) { composite_error(c, c->status); return; } composite_done(c);}/* send a nt1 style session setup*/static NTSTATUS session_setup_nt1(struct composite_context *c, struct smbcli_session *session, struct smb_composite_sesssetup *io, struct smbcli_request **req) { NTSTATUS nt_status; struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_iconv_convenience(global_loadparm), session->transport->socket->hostname, lp_workgroup(global_loadparm)); DATA_BLOB session_key; int flags = CLI_CRED_NTLM_AUTH; if (session->options.lanman_auth) { flags |= CLI_CRED_LANMAN_AUTH; } if (session->options.ntlmv2_auth) { flags |= CLI_CRED_NTLMv2_AUTH; } state->setup.nt1.level = RAW_SESSSETUP_NT1; state->setup.nt1.in.bufsize = session->transport->options.max_xmit; state->setup.nt1.in.mpx_max = session->transport->options.max_mux; state->setup.nt1.in.vc_num = 1; state->setup.nt1.in.sesskey = io->in.sesskey; state->setup.nt1.in.capabilities = io->in.capabilities; state->setup.nt1.in.os = "Unix"; state->setup.nt1.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); cli_credentials_get_ntlm_username_domain(io->in.credentials, state, &state->setup.nt1.in.user, &state->setup.nt1.in.domain); if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { nt_status = cli_credentials_get_ntlm_response(io->in.credentials, state, &flags, session->transport->negotiate.secblob, names_blob, &state->setup.nt1.in.password1, &state->setup.nt1.in.password2, NULL, &session_key); NT_STATUS_NOT_OK_RETURN(nt_status); smbcli_transport_simple_set_signing(session->transport, session_key, state->setup.nt1.in.password2);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?