Author: jra Date: 2005-09-02 19:53:20 +0000 (Fri, 02 Sep 2005) New Revision: 9968
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=9968 Log: NTLMSSP NTLMv2 signing and sealing now working. Check schannel next, then add NTLMSSP SPNEGO bind. Jeremy. Modified: branches/tmp/RPCREWRITE/source/rpc_client/cli_pipe.c branches/tmp/RPCREWRITE/source/rpcclient/rpcclient.c Changeset: Modified: branches/tmp/RPCREWRITE/source/rpc_client/cli_pipe.c =================================================================== --- branches/tmp/RPCREWRITE/source/rpc_client/cli_pipe.c 2005-09-02 19:45:48 UTC (rev 9967) +++ branches/tmp/RPCREWRITE/source/rpc_client/cli_pipe.c 2005-09-02 19:53:20 UTC (rev 9968) @@ -234,20 +234,20 @@ NTSTATUS status; if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) { - return NT_STATUS_OK; - } + return NT_STATUS_OK; + } - if (!ntlmssp_state) { - return NT_STATUS_INVALID_PARAMETER; - } + if (!ntlmssp_state) { + return NT_STATUS_INVALID_PARAMETER; + } - /* Ensure there's enough data for an authenticated response. */ - if ((auth_len > RPC_MAX_SIGN_SIZE) || - (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) { - DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n", - (unsigned int)auth_len )); - return NT_STATUS_BUFFER_TOO_SMALL; - } + /* Ensure there's enough data for an authenticated response. */ + if ((auth_len > RPC_MAX_SIGN_SIZE) || + (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) { + DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n", + (unsigned int)auth_len )); + return NT_STATUS_BUFFER_TOO_SMALL; + } /* * We need the full packet data + length (minus auth stuff) as well as the packet data + length @@ -256,16 +256,16 @@ * functions as NTLMv2 checks the rpc headers also. */ - data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HDR_RESP_LEN); + data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN); data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len); full_packet_data = prs_data_p(current_pdu); full_packet_data_len = prhdr->frag_len - auth_len; /* Pull the auth header and the following data into a blob. */ - if(!prs_set_offset(current_pdu, RPC_HDR_RESP_LEN + data_len)) { + if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) { DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n", - (unsigned int)RPC_HDR_RESP_LEN + data_len )); + (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len )); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -378,9 +378,9 @@ data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len; - if(!prs_set_offset(current_pdu, RPC_HDR_RESP_LEN + data_len)) { + if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) { DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n", - (unsigned int)RPC_HDR_RESP_LEN + data_len )); + (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len )); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -1097,15 +1097,93 @@ } +/******************************************************************* + Create and add the NTLMSSP sign/seal auth header and data. + ********************************************************************/ + static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, RPC_HDR *phdr, - prs_struct *p_outgoing_pdu) + uint32 ss_padding_len, + prs_struct *outgoing_pdu) { - return NT_STATUS_NO_MEMORY; + RPC_HDR_AUTH auth_info; + NTSTATUS status; + DATA_BLOB auth_blob = data_blob(NULL, 0); + uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + + if (!cli->auth.a_u.ntlmssp_state) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* Init and marshall the auth header. */ + init_rpc_hdr_auth(&auth_info, + map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type), + cli->auth.auth_level, + ss_padding_len, + 1 /* context id. */); + + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) { + DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n")); + data_blob_free(&auth_blob); + return NT_STATUS_NO_MEMORY; + } + + switch (cli->auth.auth_level) { + case PIPE_AUTH_LEVEL_PRIVACY: + /* Data portion is encrypted. */ + status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state, + prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, + data_and_pad_len, + prs_data_p(outgoing_pdu), + (size_t)prs_offset(outgoing_pdu), + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&auth_blob); + return status; + } + break; + + case PIPE_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state, + prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, + data_and_pad_len, + prs_data_p(outgoing_pdu), + (size_t)prs_offset(outgoing_pdu), + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&auth_blob); + return status; + } + break; + + default: + /* Can't happen. */ + smb_panic("bad auth level"); + /* Notreached. */ + return NT_STATUS_INVALID_PARAMETER; + } + + /* Finally marshall the blob. */ + + if (!prs_copy_data_in(outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) { + DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n", + (unsigned int)NTLMSSP_SIG_SIZE)); + data_blob_free(&auth_blob); + return NT_STATUS_NO_MEMORY; + } + + data_blob_free(&auth_blob); + return NT_STATUS_OK; } +/******************************************************************* + Create and add the schannel sign/seal auth header and data. + ********************************************************************/ + static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, RPC_HDR *phdr, + uint32 ss_padding_len, prs_struct *p_outgoing_pdu) { #if 0 @@ -1288,14 +1366,14 @@ break; case PIPE_AUTH_TYPE_NTLMSSP: case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - ret = add_ntlmssp_auth_footer(cli, &hdr, &outgoing_pdu); + ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&outgoing_pdu); return ret; } break; case PIPE_AUTH_TYPE_SCHANNEL: - ret = add_schannel_auth_footer(cli, &hdr, &outgoing_pdu); + ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&outgoing_pdu); return ret; Modified: branches/tmp/RPCREWRITE/source/rpcclient/rpcclient.c =================================================================== --- branches/tmp/RPCREWRITE/source/rpcclient/rpcclient.c 2005-09-02 19:45:48 UTC (rev 9967) +++ branches/tmp/RPCREWRITE/source/rpcclient/rpcclient.c 2005-09-02 19:53:20 UTC (rev 9968) @@ -315,21 +315,22 @@ static NTSTATUS cmd_set_ss_level(void) { struct cmd_list *tmp; - struct cmd_set *tmp_set; /* Close any existing connections not at this level. */ for (tmp = cmd_list; tmp; tmp = tmp->next) { - tmp_set = tmp->cmd_set; + struct cmd_set *tmp_set; - if (tmp_set->rpc_pipe == NULL) { - continue; - } + for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) { + if (tmp_set->rpc_pipe == NULL) { + continue; + } - if (tmp_set->rpc_pipe->auth.auth_type != pipe_default_auth_type || - tmp_set->rpc_pipe->auth.auth_level != pipe_default_auth_level) { - cli_rpc_pipe_close(tmp_set->rpc_pipe); - tmp_set->rpc_pipe = NULL; + if (tmp_set->rpc_pipe->auth.auth_type != pipe_default_auth_type || + tmp_set->rpc_pipe->auth.auth_level != pipe_default_auth_level) { + cli_rpc_pipe_close(tmp_set->rpc_pipe); + tmp_set->rpc_pipe = NULL; + } } } return NT_STATUS_OK;
