*
* 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 2 of the License, or
+ * 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,
* 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
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 = (unsigned char *)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. */
return NT_STATUS_BUFFER_TOO_SMALL;
}
- auth_blob.data = prs_data_p(current_pdu) + prs_offset(current_pdu);
+ auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
auth_blob.length = auth_len;
switch (cli->auth.auth_level) {
DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
"packet from remote machine %s on pipe %s "
"fnum 0x%x. Error was %s.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
nt_errstr(status) ));
DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
"packet from remote machine %s on pipe %s "
"fnum 0x%x. Error was %s.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
nt_errstr(status) ));
DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
"Connection to remote machine %s "
"pipe %s fnum 0x%x.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum ));
return NT_STATUS_INVALID_PARAMETER;
if (prhdr->auth_len) {
DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
"pipe %s fnum 0x%x - got non-zero auth len %u.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
(unsigned int)prhdr->auth_len ));
default:
DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
"pipe %s fnum %x - unknown internal auth type %u.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
cli->auth.auth_type ));
case RPC_BINDNACK:
DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s "
"pipe %s fnum 0x%x!\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
/* Use this for now... */
DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
"pipe %s fnum 0x%x!\n",
- nt_errstr(fault_resp.status),
- cli->cli->desthost,
+ dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
if (NT_STATUS_IS_OK(fault_resp.status)) {
DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
"from remote machine %s pipe %s fnum 0x%x!\n",
(unsigned int)prhdr->pkt_type,
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
return NT_STATUS_INVALID_INFO_CLASS;
DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
"pipe %s fnum %x got an unexpected RPC packet "
"type - %u, not %u\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
prhdr->pkt_type,
/* Common case. */
if (current_pdu_len == (uint32)prhdr->frag_len) {
prs_mem_free(current_pdu);
- prs_init(current_pdu, 0, prs_get_mem_context(current_pdu), UNMARSHALL);
+ prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
/* Make current_pdu dynamic with no memory. */
prs_give_memory(current_pdu, 0, 0, True);
return NT_STATUS_OK;
char *rparam = NULL;
uint32 rparam_len = 0;
uint16 setup[2];
- char *pdata = data ? prs_data_p(data) : NULL;
- uint32 data_len = data ? prs_offset(data) : 0;
+ char *pdata = prs_data_p(data);
+ uint32 data_len = prs_offset(data);
char *prdata = NULL;
uint32 rdata_len = 0;
uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
#endif
/* Set up the current pdu parse struct. */
- prs_init(¤t_pdu, 0, prs_get_mem_context(rbuf), UNMARSHALL);
+ prs_init_empty(¤t_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
/* Create setup parameters - must be in native byte order. */
setup[0] = TRANSACT_DCERPCCMD;
setup[1] = cli->fnum; /* Pipe file handle. */
DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum ));
&rparam, &rparam_len, /* return params, len */
&prdata, &rdata_len)) /* return data, len */
{
- DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x"
+ DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x "
"returned critical error. Error was %s\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
cli_errstr(cli->cli)));
ret = cli_get_nt_error(cli->cli);
+ SAFE_FREE(rparam);
+ SAFE_FREE(prdata);
goto err;
}
if (prdata == NULL) {
DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s "
"fnum 0x%x failed to return data.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
/* Yes - some calls can truely return no data... */
/* Set the data type correctly for big-endian data on the first packet. */
DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x "
"PDU data format is big-endian.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
}
DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum,
(unsigned int)prs_data_size(rbuf) ));
#ifdef HAVE_KRB5
int ret;
struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;
- DATA_BLOB tkt = data_blob(NULL, 0);
- DATA_BLOB tkt_wrapped = data_blob(NULL, 0);
+ DATA_BLOB tkt = data_blob_null;
+ DATA_BLOB tkt_wrapped = data_blob_null;
/* We may change the pad length before marshalling. */
init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
/* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
- &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED);
+ &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
if (ret) {
DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
}
DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
- dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length);
+ dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
data_blob_free(&tkt_wrapped);
return NT_STATUS_OK;
prs_struct *auth_data)
{
NTSTATUS nt_status;
- DATA_BLOB null_blob = data_blob(NULL, 0);
- DATA_BLOB request = data_blob(NULL, 0);
- DATA_BLOB spnego_msg = data_blob(NULL, 0);
+ DATA_BLOB null_blob = data_blob_null;
+ DATA_BLOB request = data_blob_null;
+ DATA_BLOB spnego_msg = data_blob_null;
/* We may change the pad length before marshalling. */
init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
}
DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
- dump_data(5, (const char *)spnego_msg.data, spnego_msg.length);
+ dump_data(5, spnego_msg.data, spnego_msg.length);
data_blob_free(&spnego_msg);
return NT_STATUS_OK;
prs_struct *auth_data)
{
NTSTATUS nt_status;
- DATA_BLOB null_blob = data_blob(NULL, 0);
- DATA_BLOB request = data_blob(NULL, 0);
+ DATA_BLOB null_blob = data_blob_null;
+ DATA_BLOB request = data_blob_null;
/* We may change the pad length before marshalling. */
init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
}
DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
- dump_data(5, (const char *)request.data, request.length);
+ dump_data(5, request.data, request.length);
data_blob_free(&request);
return NT_STATUS_OK;
/* Use lp_workgroup() if domain not specified */
if (!cli->domain || !cli->domain[0]) {
- cli->domain = lp_workgroup();
+ cli->domain = talloc_strdup(cli, lp_workgroup());
+ if (cli->domain == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
Creates the internals of a DCE/RPC bind request or alter context PDU.
********************************************************************/
-static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type,
+static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
prs_struct *rpc_out,
uint32 rpc_call_id,
- RPC_IFACE *abstract,
- RPC_IFACE *transfer,
+ const RPC_IFACE *abstract,
+ const RPC_IFACE *transfer,
RPC_HDR_AUTH *phdr_auth,
prs_struct *pauth_info)
{
if(auth_len != 0) {
if (ss_padding_len) {
- unsigned char pad[8];
+ char pad[8];
memset(pad, '\0', 8);
if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
prs_struct *rpc_out,
uint32 rpc_call_id,
- RPC_IFACE *abstract, RPC_IFACE *transfer,
+ const RPC_IFACE *abstract,
+ const RPC_IFACE *transfer,
enum pipe_auth_type auth_type,
enum pipe_auth_level auth_level)
{
NTSTATUS ret = NT_STATUS_OK;
ZERO_STRUCT(hdr_auth);
- prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
+ if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
+ return NT_STATUS_NO_MEMORY;
switch (auth_type) {
case PIPE_AUTH_TYPE_SCHANNEL:
{
RPC_HDR_AUTH auth_info;
NTSTATUS status;
- DATA_BLOB auth_blob = data_blob(NULL, 0);
+ DATA_BLOB auth_blob = data_blob_null;
uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
if (!cli->auth.a_u.ntlmssp_state) {
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,
+ (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
data_and_pad_len,
- prs_data_p(outgoing_pdu),
+ (unsigned char *)prs_data_p(outgoing_pdu),
(size_t)prs_offset(outgoing_pdu),
&auth_blob);
if (!NT_STATUS_IS_OK(status)) {
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,
+ (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
data_and_pad_len,
- prs_data_p(outgoing_pdu),
+ (unsigned char *)prs_data_p(outgoing_pdu),
(size_t)prs_offset(outgoing_pdu),
&auth_blob);
if (!NT_STATUS_IS_OK(status)) {
/* Finally marshall the blob. */
- if (!prs_copy_data_in(outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) {
+ if (!prs_copy_data_in(outgoing_pdu, (const char *)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_INVALID_PARAMETER;
}
- prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL);
+ if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
+ return NT_STATUS_NO_MEMORY;
while (1) {
RPC_HDR hdr;
ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
prs_mem_free(&outgoing_pdu);
-
if (DEBUGLEVEL >= 50) {
- pstring dump_name;
+ char *dump_name = NULL;
/* Also capture received data */
- slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d",
- dyn_LOGFILEBASE, cli->pipe_name, op_num);
- prs_dump(dump_name, op_num, out_data);
+ if (asprintf(&dump_name, "%s/reply_%s_%d",
+ get_dyn_LOGFILEBASE(), cli->pipe_name,
+ op_num) > 0) {
+ prs_dump(dump_name, op_num, out_data);
+ SAFE_FREE(dump_name);
+ }
}
return ret;
Set the handle state.
****************************************************************************/
-static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
+static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
const char *pipe_name, uint16 device_state)
{
- BOOL state_set = False;
+ bool state_set = False;
char param[2];
uint16 setup[2]; /* only need 2 uint16 setup parameters */
char *rparam = NULL;
Check the rpc bind acknowledge response.
****************************************************************************/
-static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer)
-{
- if ( pipe_idx >= PI_MAX_PIPES ) {
- DEBUG(0,("valid_pipe_name: Programmer error! Invalid pipe index [%d]\n",
- pipe_idx));
- return False;
- }
-
- DEBUG(5,("Bind Abstract Syntax: "));
- dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax,
- sizeof(pipe_names[pipe_idx].abstr_syntax));
- DEBUG(5,("Bind Transfer Syntax: "));
- dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax,
- sizeof(pipe_names[pipe_idx].trans_syntax));
-
- /* copy the required syntaxes out so we can do the right bind */
-
- *transfer = pipe_names[pipe_idx].trans_syntax;
- *abstract = pipe_names[pipe_idx].abstr_syntax;
-
- return True;
-}
-
-/****************************************************************************
- Check the rpc bind acknowledge response.
-****************************************************************************/
-
-static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
+static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
{
if ( hdr_ba->addr.len == 0) {
DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
}
-# if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
- if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
- !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
- {
- DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s. oh well!\n",
- pipe_names[i].server_pipe ,hdr_ba->addr.str));
- return False;
- }
-
- DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", pipe_names[i].server_pipe ));
-
- if (pipe_names[pipe_idx].server_pipe == NULL) {
- DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
- return False;
- }
-#endif /* JERRY */
-
/* check the transfer syntax */
- if ((hdr_ba->transfer.version != transfer->version) ||
+ if ((hdr_ba->transfer.if_version != transfer->if_version) ||
(memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
return False;
enum pipe_auth_type auth_type,
enum pipe_auth_level auth_level)
{
- DATA_BLOB server_response = data_blob(NULL,0);
- DATA_BLOB client_reply = data_blob(NULL,0);
+ DATA_BLOB server_response = data_blob_null;
+ DATA_BLOB client_reply = data_blob_null;
RPC_HDR_AUTH hdr_auth;
NTSTATUS nt_status;
prs_struct rpc_out;
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
+ data_blob_free(&server_response);
return nt_status;
}
- prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
+ prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
auth_type, auth_level,
DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
"fnum 0x%x sent auth3 response ok.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
********************************************************************/
static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
- RPC_IFACE *abstract,
- RPC_IFACE *transfer,
+ const RPC_IFACE *abstract,
+ const RPC_IFACE *transfer,
enum pipe_auth_level auth_level,
const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
prs_struct *rpc_out)
NTSTATUS ret = NT_STATUS_OK;
ZERO_STRUCT(hdr_auth);
- prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
+ if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
+ return NT_STATUS_NO_MEMORY;
/* We may change the pad length before marshalling. */
init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
RPC_HDR *phdr,
prs_struct *rbuf,
uint32 rpc_call_id,
- RPC_IFACE *abstract,
- RPC_IFACE *transfer,
+ const RPC_IFACE *abstract,
+ const RPC_IFACE *transfer,
enum pipe_auth_type auth_type,
enum pipe_auth_level auth_level)
{
- DATA_BLOB server_spnego_response = data_blob(NULL,0);
- DATA_BLOB server_ntlm_response = data_blob(NULL,0);
- DATA_BLOB client_reply = data_blob(NULL,0);
- DATA_BLOB tmp_blob = data_blob(NULL, 0);
+ DATA_BLOB server_spnego_response = data_blob_null;
+ DATA_BLOB server_ntlm_response = data_blob_null;
+ DATA_BLOB client_reply = data_blob_null;
+ DATA_BLOB tmp_blob = data_blob_null;
RPC_HDR_AUTH hdr_auth;
NTSTATUS nt_status;
prs_struct rpc_out;
tmp_blob = spnego_gen_auth(client_reply);
data_blob_free(&client_reply);
client_reply = tmp_blob;
- tmp_blob = data_blob(NULL,0); /* Ensure it's safe to free this just in case. */
+ tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
/* Now prepare the alter context pdu. */
- prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
+ prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
nt_status = create_rpc_alter_context(rpc_call_id,
abstract,
/* Initialize the returning data struct. */
prs_mem_free(rbuf);
- prs_init(rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
+ prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
if (!NT_STATUS_IS_OK(nt_status)) {
prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
/* Check we got a valid auth response. */
- if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, &tmp_blob)) {
+ if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
data_blob_free(&server_spnego_response);
data_blob_free(&tmp_blob);
return NT_STATUS_INVALID_PARAMETER;
DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
"remote machine %s pipe %s fnum 0x%x.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
{
RPC_HDR hdr;
RPC_HDR_BA hdr_ba;
- RPC_IFACE abstract;
- RPC_IFACE transfer;
prs_struct rpc_out;
prs_struct rbuf;
uint32 rpc_call_id;
(unsigned int)auth_type,
(unsigned int)auth_level ));
- if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL);
+ prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
rpc_call_id = get_rpc_call_id();
/* Marshall the outgoing data. */
status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
- &abstract, &transfer,
+ cli->abstract_syntax,
+ cli->transfer_syntax,
auth_type,
auth_level);
}
/* Initialize the incoming data struct. */
- prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
+ prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
/* send data on \PIPE\. receive a response */
status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
"fnum 0x%x bind request returned ok.\n",
- cli->cli->desthost,
+ cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
return NT_STATUS_BUFFER_TOO_SMALL;
}
- if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {
+ if(!check_bind_response(&hdr_ba, cli->transfer_syntax)) {
DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
prs_mem_free(&rbuf);
return NT_STATUS_BUFFER_TOO_SMALL;
case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
/* Need to send alter context request and reply. */
status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
- &abstract, &transfer,
+ cli->abstract_syntax,
+ cli->transfer_syntax,
auth_type, auth_level);
if (!NT_STATUS_IS_OK(status)) {
prs_mem_free(&rbuf);
return NT_STATUS_INVALID_INFO_CLASS;
}
+ /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
+ if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
+ if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+ if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
+ prs_mem_free(&rbuf);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+ if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+ DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
+ prs_mem_free(&rbuf);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+
/* Pipe is bound - set up auth_type and auth_level data. */
cli->auth.auth_type = auth_type;
return NT_STATUS_OK;
}
+unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli,
+ unsigned int timeout)
+{
+ return cli_set_timeout(cli->cli, timeout);
+}
+
+bool rpccli_is_pipe_idx(struct rpc_pipe_client *cli, int pipe_idx)
+{
+ return (cli->abstract_syntax == pipe_names[pipe_idx].abstr_syntax);
+}
+
+static int rpc_pipe_destructor(struct rpc_pipe_client *p)
+{
+ bool ret;
+
+ ret = cli_close(p->cli, p->fnum);
+ if (!ret) {
+ DEBUG(1, ("rpc_pipe_destructor: cli_close failed on pipe %s, "
+ "fnum 0x%x to machine %s. Error was %s\n",
+ p->pipe_name, (int) p->fnum,
+ p->desthost, cli_errstr(p->cli)));
+ }
+
+ if (p->auth.cli_auth_data_free_func) {
+ (*p->auth.cli_auth_data_free_func)(&p->auth);
+ }
+
+ DEBUG(10, ("rpc_pipe_destructor: closed pipe %s to machine %s\n",
+ p->pipe_name, p->desthost ));
+
+ DLIST_REMOVE(p->cli->pipe_list, p);
+
+ return ret ? -1 : 0;
+}
+
/****************************************************************************
Open a named pipe over SMB to a remote server.
+ *
+ * CAVEAT CALLER OF THIS FUNCTION:
+ * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
+ * so be sure that this function is called AFTER any structure (vs pointer)
+ * assignment of the cli. In particular, libsmbclient does structure
+ * assignments of cli, which invalidates the data in the returned
+ * rpc_pipe_client if this function is called before the structure assignment
+ * of cli.
+ *
****************************************************************************/
static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
{
- TALLOC_CTX *mem_ctx;
struct rpc_pipe_client *result;
int fnum;
*perr = NT_STATUS_NO_MEMORY;
- /* The pipe name index must fall within our array */
- SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
+ /* sanity check to protect against crashes */
- mem_ctx = talloc_init("struct rpc_pipe_client");
- if (mem_ctx == NULL) {
+ if ( !cli ) {
+ *perr = NT_STATUS_INVALID_HANDLE;
return NULL;
}
- result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
+ /* The pipe name index must fall within our array */
+ SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
+
+ result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
if (result == NULL) {
+ *perr = NT_STATUS_NO_MEMORY;
return NULL;
}
- result->mem_ctx = mem_ctx;
-
result->pipe_name = cli_get_pipe_name(pipe_idx);
- fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
-
- if (fnum == -1) {
- DEBUG(0,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
- "to machine %s. Error was %s\n",
- result->pipe_name, cli->desthost,
- cli_errstr(cli)));
- *perr = cli_get_nt_error(cli);
- talloc_destroy(result->mem_ctx);
- return NULL;
- }
-
- result->fnum = fnum;
result->cli = cli;
- result->pipe_idx = pipe_idx;
+ result->abstract_syntax = pipe_names[pipe_idx].abstr_syntax;
+ result->transfer_syntax = pipe_names[pipe_idx].trans_syntax;
result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
+ result->domain = talloc_strdup(result, cli->domain);
+ result->user_name = talloc_strdup(result, cli->user_name);
+ result->desthost = talloc_strdup(result, cli->desthost);
+ result->srv_name_slash = talloc_asprintf_strupper_m(
+ result, "\\\\%s", result->desthost);
+
+ if ((result->domain == NULL)
+ || (result->user_name == NULL)
+ || (result->desthost == NULL)
+ || (result->srv_name_slash == NULL)) {
+ *perr = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE(result);
+ return NULL;
+ }
+
if (pipe_idx == PI_NETLOGON) {
/* Set up a netlogon credential chain for a netlogon pipe. */
- result->dc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
+ result->dc = TALLOC_ZERO_P(result, struct dcinfo);
if (result->dc == NULL) {
- talloc_destroy(result->mem_ctx);
+ *perr = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE(result);
return NULL;
}
}
+ fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
+ if (fnum == -1) {
+ DEBUG(1,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
+ "to machine %s. Error was %s\n",
+ result->pipe_name, cli->desthost,
+ cli_errstr(cli)));
+ *perr = cli_get_nt_error(cli);
+ talloc_destroy(result);
+ return NULL;
+ }
+
+ result->fnum = fnum;
+
DLIST_ADD(cli->pipe_list, result);
+ talloc_set_destructor(result, rpc_pipe_destructor);
+
*perr = NT_STATUS_OK;
return result;
*perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
if (!NT_STATUS_IS_OK(*perr)) {
- DEBUG(0, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
+ int lvl = 0;
+ if (rpccli_is_pipe_idx(result, PI_DSSETUP)) {
+ /* non AD domains just don't have this pipe, avoid
+ * level 0 statement in that case - gd */
+ lvl = 3;
+ }
+ DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
return NULL;
}
result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
- result->domain = domain;
- result->user_name = username;
+ TALLOC_FREE(result->domain);
+ TALLOC_FREE(result->user_name);
+
+ result->domain = talloc_strdup(result, domain);
+ result->user_name = talloc_strdup(result, username);
+
+ if ((result->domain == NULL) || (result->user_name == NULL)) {
+ *perr = NT_STATUS_NO_MEMORY;
+ goto err;
+ }
+
pwd_set_cleartext(&result->pwd, password);
*perr = ntlmssp_client_start(&ntlmssp_state);
result->auth.a_u.ntlmssp_state = ntlmssp_state;
- *perr = ntlmssp_set_username(ntlmssp_state, cli->user_name);
+ *perr = ntlmssp_set_username(ntlmssp_state, username);
if (!NT_STATUS_IS_OK(*perr)) {
goto err;
}
- *perr = ntlmssp_set_domain(ntlmssp_state, cli->domain);
+ *perr = ntlmssp_set_domain(ntlmssp_state, domain);
if (!NT_STATUS_IS_OK(*perr)) {
goto err;
}
goto err;
}
- DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to machine %s and"
- "bound NTLMSSP as user %s\\%s.\n",
+ DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
+ "machine %s and bound NTLMSSP as user %s\\%s.\n",
result->pipe_name, cli->desthost,
domain, username ));
err:
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
return NULL;
}
}
/****************************************************************************
- Open a netlogon pipe and get the schannel session key.
+ Get a the schannel session key out of an already opened netlogon pipe.
****************************************************************************/
-
-static struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
- const char *domain,
- NTSTATUS *perr)
+static bool get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
+ struct cli_state *cli,
+ const char *domain,
+ uint32 *pneg_flags,
+ NTSTATUS *perr)
{
- uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
- struct rpc_pipe_client *netlogon_pipe = NULL;
uint32 sec_chan_type = 0;
- char machine_pwd[16];
- fstring machine_account;
-
- netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
- if (!netlogon_pipe) {
- return NULL;
- }
+ unsigned char machine_pwd[16];
+ const char *machine_account;
/* Get the machine account credentials from secrets.tdb. */
- if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
+ if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
+ &sec_chan_type))
+ {
DEBUG(0, ("get_schannel_session_key: could not fetch "
"trust account password for domain '%s'\n",
domain));
- cli_rpc_pipe_close(netlogon_pipe);
*perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- return NULL;
+ return false;
}
- if ( IS_DC ) {
- fstrcpy( machine_account, lp_workgroup() );
- } else {
- /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */
- if (strequal(domain, lp_workgroup())) {
- fstrcpy(machine_account, global_myname());
- } else {
- fstrcpy(machine_account, domain);
- }
- }
-
*perr = rpccli_netlogon_setup_creds(netlogon_pipe,
- cli->desthost,
- domain,
- machine_account,
+ cli->desthost, /* server name */
+ domain, /* domain */
+ global_myname(), /* client name */
+ machine_account, /* machine account name */
machine_pwd,
sec_chan_type,
- &neg_flags);
+ pneg_flags);
if (!NT_STATUS_IS_OK(*perr)) {
- DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds "
- "failed with result %s\n",
- nt_errstr(*perr) ));
- cli_rpc_pipe_close(netlogon_pipe);
- return NULL;
+ DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds "
+ "failed with result %s to server %s, domain %s, machine account %s.\n",
+ nt_errstr(*perr), cli->desthost, domain, machine_account ));
+ return false;
}
- if ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0) {
+ if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
cli->desthost));
- cli_rpc_pipe_close(netlogon_pipe);
*perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ Open a netlogon pipe and get the schannel session key.
+ Now exposed to external callers.
+ ****************************************************************************/
+
+
+struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
+ const char *domain,
+ uint32 *pneg_flags,
+ NTSTATUS *perr)
+{
+ struct rpc_pipe_client *netlogon_pipe = NULL;
+
+ netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
+ if (!netlogon_pipe) {
+ return NULL;
+ }
+
+ if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
+ pneg_flags, perr))
+ {
+ TALLOC_FREE(netlogon_pipe);
return NULL;
}
return NULL;
}
- result->auth.a_u.schannel_auth = TALLOC_ZERO_P(result->mem_ctx, struct schannel_auth_struct);
+ result->auth.a_u.schannel_auth = TALLOC_ZERO_P(
+ result, struct schannel_auth_struct);
if (!result->auth.a_u.schannel_auth) {
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
+ *perr = NT_STATUS_NO_MEMORY;
+ return NULL;
+ }
+
+ TALLOC_FREE(result->domain);
+ result->domain = talloc_strdup(result, domain);
+ if (result->domain == NULL) {
+ TALLOC_FREE(result);
*perr = NT_STATUS_NO_MEMORY;
return NULL;
}
- result->domain = domain;
memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
*perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
if (!NT_STATUS_IS_OK(*perr)) {
DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
nt_errstr(*perr) ));
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
return NULL;
}
const char *domain,
const char *username,
const char *password,
+ uint32 *pneg_flags,
NTSTATUS *perr)
{
- uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
struct rpc_pipe_client *netlogon_pipe = NULL;
- uint32 sec_chan_type = 0;
- char machine_pwd[16];
- fstring machine_account;
netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
if (!netlogon_pipe) {
return NULL;
}
- /* Get the machine account credentials from secrets.tdb. */
- if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
- DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch "
- "trust account password for domain '%s'\n",
- domain));
- cli_rpc_pipe_close(netlogon_pipe);
- *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- return NULL;
- }
-
- if ( IS_DC ) {
- fstrcpy( machine_account, lp_workgroup() );
- } else {
- /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */
- if (strequal(domain, lp_workgroup())) {
- fstrcpy(machine_account, global_myname());
- } else {
- fstrcpy(machine_account, domain);
- }
- }
-
- *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
- cli->desthost,
- domain,
- machine_account,
- machine_pwd,
- sec_chan_type,
- &neg_flags);
-
- if (!NT_STATUS_IS_OK(*perr)) {
- DEBUG(3,("get_schannel_session_key_auth_ntlmssp: rpccli_netlogon_setup_creds "
- "failed with result %s\n",
- nt_errstr(*perr) ));
- cli_rpc_pipe_close(netlogon_pipe);
- return NULL;
- }
-
- if ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0) {
- DEBUG(3, ("get_schannel_session_key_auth_ntlmssp: Server %s did not offer schannel\n",
- cli->desthost));
- cli_rpc_pipe_close(netlogon_pipe);
- *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
+ if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
+ pneg_flags, perr))
+ {
+ TALLOC_FREE(netlogon_pipe);
return NULL;
}
uses an ntlmssp bind to get the session key.
****************************************************************************/
-struct rpc_pipe_client *cli_rpc_pipe_open_ntlmttp_auth_schannel(struct cli_state *cli,
+struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
int pipe_idx,
enum pipe_auth_level auth_level,
const char *domain,
const char *password,
NTSTATUS *perr)
{
+ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
struct rpc_pipe_client *netlogon_pipe = NULL;
struct rpc_pipe_client *result = NULL;
- netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username, password, perr);
+ netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username,
+ password, &neg_flags, perr);
if (!netlogon_pipe) {
DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
"key from server %s for domain %s.\n",
domain, netlogon_pipe->dc, perr);
/* Now we've bound using the session key we can close the netlog pipe. */
- cli_rpc_pipe_close(netlogon_pipe);
+ TALLOC_FREE(netlogon_pipe);
return result;
}
const char *domain,
NTSTATUS *perr)
{
+ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
struct rpc_pipe_client *netlogon_pipe = NULL;
struct rpc_pipe_client *result = NULL;
- netlogon_pipe = get_schannel_session_key(cli, domain, perr);
+ netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, perr);
if (!netlogon_pipe) {
DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
"key from server %s for domain %s.\n",
domain, netlogon_pipe->dc, perr);
/* Now we've bound using the session key we can close the netlog pipe. */
- cli_rpc_pipe_close(netlogon_pipe);
+ TALLOC_FREE(netlogon_pipe);
return result;
}
+#ifdef HAVE_KRB5
+
/****************************************************************************
Free function for the kerberos spcific data.
****************************************************************************/
data_blob_free(&a->a_u.kerberos_auth->session_key);
}
+#endif
+
/****************************************************************************
Open a named pipe to an SMB server and bind using krb5 (bind type 16).
The idea is this can be called with service_princ, username and password all
return NULL;
}
- /* Default service principal is "host/server@realm" */
+ /* Default service principal is "desthost$@realm" */
if (!service_princ) {
- service_princ = talloc_asprintf(result->mem_ctx, "host/%s@%s",
- cli->desthost, lp_realm() );
+ service_princ = talloc_asprintf(result, "%s$@%s",
+ cli->desthost, lp_realm() );
if (!service_princ) {
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
return NULL;
}
}
/* Only get a new TGT if username/password are given. */
if (username && password) {
- int ret = kerberos_kinit_password(username, password, 0, NULL, NULL);
+ int ret = kerberos_kinit_password(username, password, 0, NULL);
if (ret) {
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
return NULL;
}
}
- result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(cli->mem_ctx, struct kerberos_auth_struct);
+ result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(
+ result, struct kerberos_auth_struct);
if (!result->auth.a_u.kerberos_auth) {
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
*perr = NT_STATUS_NO_MEMORY;
return NULL;
}
if (!NT_STATUS_IS_OK(*perr)) {
DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
nt_errstr(*perr) ));
- cli_rpc_pipe_close(result);
+ TALLOC_FREE(result);
return NULL;
}
return NULL;
#endif
}
-
-#if 0 /* Moved to libsmb/clientgen.c */
-/****************************************************************************
- External interface.
- Close an open named pipe over SMB. Free any authentication data.
- ****************************************************************************/
-
-void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
-{
- if (!cli_close(cli->cli, cli->fnum)) {
- DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
- "to machine %s. Error was %s\n",
- cli->pipe_name),
- cli->cli->desthost,
- cli_errstr(cli->cli)));
- }
-
- if (cli->auth.cli_auth_data_free_func) {
- (*cli->auth.cli_auth_data_free_func)(&cli->auth);
- }
- DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
- cli->pipe_name, cli->cli->desthost ));
-
- DLIST_REMOVE(cli->cli->pipe_list, cli);
- talloc_destroy(cli->mem_ctx);
-}
-#endif