📄 srv_pipe.c
字号:
p->out_data.data_sent_length = 0; p->out_data.current_pdu_len = prs_offset(&outgoing_pdu); p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True;}#endif/******************************************************************* Ensure a bind request has the correct abstract & transfer interface. Used to reject unknown binds from Win2k.*******************************************************************/BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, RPC_IFACE* transfer, uint32 context_id){ char *pipe_name = p->name; int i=0; fstring pname; fstrcpy(pname,"\\PIPE\\"); fstrcat(pname,pipe_name); DEBUG(3,("check_bind_req for %s\n", pname)); /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ for ( i=0; pipe_names[i].client_pipe; i++ ) { DEBUG(10,("checking %s\n", pipe_names[i].client_pipe)); if ( strequal(pipe_names[i].client_pipe, pname) && (abstract->version == pipe_names[i].abstr_syntax.version) && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct uuid)) == 0) && (transfer->version == pipe_names[i].trans_syntax.version) && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) ) { struct api_struct *fns = NULL; int n_fns = 0; PIPE_RPC_FNS *context_fns; if ( !(context_fns = SMB_MALLOC_P(PIPE_RPC_FNS)) ) { DEBUG(0,("check_bind_req: malloc() failed!\n")); return False; } /* save the RPC function table associated with this bind */ get_pipe_fns(i, &fns, &n_fns); context_fns->cmds = fns; context_fns->n_cmds = n_fns; context_fns->context_id = context_id; /* add to the list of open contexts */ DLIST_ADD( p->contexts, context_fns ); break; } } if(pipe_names[i].client_pipe == NULL) { return False; } return True;}/******************************************************************* Register commands to an RPC pipe*******************************************************************/NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv, const struct api_struct *cmds, int size){ struct rpc_table *rpc_entry; if (!clnt || !srv || !cmds) { return NT_STATUS_INVALID_PARAMETER; } if (version != SMB_RPC_INTERFACE_VERSION) { DEBUG(0,("Can't register rpc commands!\n" "You tried to register a rpc module with SMB_RPC_INTERFACE_VERSION %d" ", while this version of samba uses version %d!\n", version,SMB_RPC_INTERFACE_VERSION)); return NT_STATUS_OBJECT_TYPE_MISMATCH; } /* TODO: * * we still need to make sure that don't register the same commands twice!!! * * --metze */ /* We use a temporary variable because this call can fail and rpc_lookup will still be valid afterwards. It could then succeed if called again later */ rpc_lookup_size++; rpc_entry = SMB_REALLOC_ARRAY(rpc_lookup, struct rpc_table, rpc_lookup_size); if (NULL == rpc_entry) { rpc_lookup_size--; DEBUG(0, ("rpc_pipe_register_commands: memory allocation failed\n")); return NT_STATUS_NO_MEMORY; } else { rpc_lookup = rpc_entry; } rpc_entry = rpc_lookup + (rpc_lookup_size - 1); ZERO_STRUCTP(rpc_entry); rpc_entry->pipe.clnt = SMB_STRDUP(clnt); rpc_entry->pipe.srv = SMB_STRDUP(srv); rpc_entry->cmds = SMB_REALLOC_ARRAY(rpc_entry->cmds, struct api_struct, rpc_entry->n_cmds + size); memcpy(rpc_entry->cmds + rpc_entry->n_cmds, cmds, size * sizeof(struct api_struct)); rpc_entry->n_cmds += size; return NT_STATUS_OK;}/******************************************************************* Handle a SPNEGO krb5 bind auth.*******************************************************************/static BOOL pipe_spnego_auth_bind_kerberos(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, DATA_BLOB *psecblob, prs_struct *pout_auth){ return False;}/******************************************************************* Handle the first part of a SPNEGO bind auth.*******************************************************************/static BOOL pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth){ DATA_BLOB blob; DATA_BLOB secblob; DATA_BLOB response; DATA_BLOB chal; char *OIDs[ASN1_MAX_OIDS]; int i; NTSTATUS status; BOOL got_kerberos_mechanism = False; AUTH_NTLMSSP_STATE *a = NULL; RPC_HDR_AUTH auth_info; ZERO_STRUCT(secblob); ZERO_STRUCT(chal); ZERO_STRUCT(response); /* Grab the SPNEGO blob. */ blob = data_blob(NULL,p->hdr.auth_len); if (!prs_copy_data_out((char *)blob.data, rpc_in_p, p->hdr.auth_len)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to pull %u bytes - the SPNEGO auth header.\n", (unsigned int)p->hdr.auth_len )); goto err; } if (blob.data[0] != ASN1_APPLICATION(0)) { goto err; } /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob, OIDs, &secblob)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to parse the security blob.\n")); goto err; } if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { got_kerberos_mechanism = True; } for (i=0;OIDs[i];i++) { DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got OID %s\n", OIDs[i])); SAFE_FREE(OIDs[i]); } DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { BOOL ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth); data_blob_free(&secblob); data_blob_free(&blob); return ret; } if (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP && p->auth.a_u.auth_ntlmssp_state) { /* Free any previous auth type. */ free_pipe_ntlmssp_auth_data(&p->auth); } /* Initialize the NTLM engine. */ status = auth_ntlmssp_start(&a); if (!NT_STATUS_IS_OK(status)) { goto err; } /* * Pass the first security blob of data to it. * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED * which means we need another packet to complete the bind. */ status = auth_ntlmssp_update(a, secblob, &chal); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n")); goto err; } /* Generate the response blob we need for step 2 of the bind. */ response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); /* Copy the blob into the pout_auth parse struct */ init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of RPC_HDR_AUTH failed.\n")); goto err; } if (!prs_copy_data_in(pout_auth, (char *)response.data, response.length)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of data blob failed.\n")); goto err; } p->auth.a_u.auth_ntlmssp_state = a; p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data; p->auth.auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; data_blob_free(&blob); data_blob_free(&secblob); data_blob_free(&chal); data_blob_free(&response); /* We can't set pipe_bound True yet - we need an RPC_ALTER_CONTEXT response packet... */ return True; err: data_blob_free(&blob); data_blob_free(&secblob); data_blob_free(&chal); data_blob_free(&response); p->auth.a_u.auth_ntlmssp_state = NULL; return False;}/******************************************************************* Handle the second part of a SPNEGO bind auth.*******************************************************************/static BOOL pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth){ RPC_HDR_AUTH auth_info; DATA_BLOB spnego_blob; DATA_BLOB auth_blob; DATA_BLOB auth_reply; DATA_BLOB response; AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; ZERO_STRUCT(spnego_blob); ZERO_STRUCT(auth_blob); ZERO_STRUCT(auth_reply); ZERO_STRUCT(response); if (p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) { DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n")); goto err; } /* Grab the SPNEGO blob. */ spnego_blob = data_blob(NULL,p->hdr.auth_len); if (!prs_copy_data_out((char *)spnego_blob.data, rpc_in_p, p->hdr.auth_len)) { DEBUG(0,("pipe_spnego_auth_bind_continue: Failed to pull %u bytes - the SPNEGO auth header.\n", (unsigned int)p->hdr.auth_len )); goto err; } if (spnego_blob.data[0] != ASN1_CONTEXT(1)) { DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob type.\n")); goto err; } if (!spnego_parse_auth(spnego_blob, &auth_blob)) { DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob.\n")); goto err; } /* * The following call actually checks the challenge/response data. * for correctness against the given DOMAIN\user name. */ if (!pipe_ntlmssp_verify_final(p, &auth_blob)) { goto err; } data_blob_free(&spnego_blob); data_blob_free(&auth_blob); /* Generate the spnego "accept completed" blob - no incoming data. */ response = spnego_gen_auth_response(&auth_reply, NT_STATUS_OK, OID_NTLMSSP); /* Copy the blob into the pout_auth parse struct */ init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_spnego_auth_bind_continue: marshalling of RPC_HDR_AUTH failed.\n")); goto err; } if (!prs_copy_data_in(pout_auth, (char *)response.data, response.length)) { DEBUG(0,("pipe_spnego_auth_bind_continue: marshalling of data blob failed.\n")); goto err; } data_blob_free(&auth_reply); data_blob_free(&response); p->pipe_bound = True; return True; err: data_blob_free(&spnego_blob); data_blob_free(&auth_blob); data_blob_free(&auth_reply); data_blob_free(&response); free_pipe_ntlmssp_auth_data(&p->auth); p->auth.a_u.auth_ntlmssp_state = NULL; return False;}/******************************************************************* Handle an schannel bind auth.*******************************************************************/static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth){ RPC_HDR_AUTH auth_info; RPC_AUTH_SCHANNEL_NEG neg; RPC_AUTH_VERIFIER auth_verifier; BOOL ret; struct dcinfo stored_dcinfo; uint32 flags; if (!smb_io_rpc_auth_schannel_neg("", &neg, rpc_in_p, 0)) { DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n")); return False; } ZERO_STRUCT(stored_dcinfo); become_root(); ret = secrets_restore_schannel_session_info(p->mem_ctx, neg.myname, &stored_dcinfo); unbecome_root(); if (!ret) { DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n")); return False; } p->auth.a_u.schannel_auth = TALLOC_P(p->pipe_state_mem_ctx, struct schannel_auth_struct); if (!p->auth.a_u.schannel_auth) { return False; } memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key)); memcpy(p->auth.a_u.schannel_auth->sess_key, stored_dcinfo.sess_key, sizeof(stored_dcinfo.sess_key)); p->auth.a_u.schannel_auth->seq_num = 0; /* * JRA. Should we also copy the schannel session key into the pipe session key p->session_key * here ? We do that for NTLMSPP, but the session key is already set up from the vuser * struct of the person who opened the pipe. I need to test this further. JRA. */ /* The client opens a second RPC NETLOGON pipe without doing a auth2. The credentials for the schannel are re-used from the auth2 the client did before. */ p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo); if (!p->dc) { return False; } *p->dc = stored_dcinfo; init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); return False; } /*** SCHANNEL verifier ***/ init_rpc_auth_verifier(&auth_verifier, "\001", 0x0); if(!smb_io_rpc_schannel_verifier("", &auth_verifier, pout_auth, 0)) { DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_AUTH_VERIFIER failed.\n")); return False; } prs_align(pout_auth); flags = 5; if(!prs_uint32("flags ", pout_auth, 0, &flags)) { return False; } DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n", neg.domain, neg.myname)); /* We're finished with this bind - no more packets. */ p->auth.auth_data_free_func = NULL; p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL; p->pipe_bound = True; return True;}/******************************************************************* Handle an NTLMSSP bind auth.*******************************************************************/static BOOL pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth){ RPC_HDR_AUTH auth_info; DATA_BLOB blob; DATA_BLOB response; NTSTATUS status; AUTH_NTLMSSP_STATE *a = NULL; ZERO_STRUCT(blob); ZERO_STRUCT(response); /* Grab the NTLMSSP blob. */ blob = data_blob(NULL,p->hdr.auth_len); if (!prs_copy_data_out((char *)blob.data, rpc_in_p, p->hdr.auth_len)) { DEBUG(0,("pipe_ntlmssp_auth_bind: Failed to pull %u bytes - the NTLM auth header.\n", (unsigned int)p->hdr.auth_len )); goto err; } if (strncmp((char *)blob.data, "NTLMSSP", 7) != 0) { DEBUG(0,("pipe_ntlmssp_auth_bind: Failed to read NTLMSSP in blob\n")); goto err; } /* We have an NTLMSSP blob. */ status = auth_ntlmssp_start(&a); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_start failed: %s\n", nt_errstr(status) )); goto err; } status = auth_ntlmssp_update(a, blob, &response); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -