diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 200 |
1 files changed, 89 insertions, 111 deletions
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 551041149f..3034b8aa68 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1448,19 +1448,17 @@ static bool pipe_ntlmssp_auth_bind(pipes_struct *p, bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) { - RPC_HDR hdr; - RPC_HDR_BA hdr_ba; struct dcerpc_auth auth_info; uint16 assoc_gid; - fstring ack_pipe_name; - prs_struct out_hdr_ba; - int auth_len = 0; unsigned int auth_type = DCERPC_AUTH_TYPE_NONE; - uint32_t ss_padding_len = 0; NTSTATUS status; struct ndr_syntax_id id; + union dcerpc_payload u; + struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; + DATA_BLOB blob = data_blob_null; + int pad_len = 0; /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { @@ -1517,10 +1515,6 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) } } - /* name has to be \PIPE\xxxxx */ - fstrcpy(ack_pipe_name, "\\PIPE\\"); - fstrcat(ack_pipe_name, rpc_srv_get_pipe_srv_name(&id)); - DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); if (pkt->u.bind.assoc_group_id != 0) { @@ -1538,17 +1532,6 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); /* - * Setup the memory to marshall the ba header, and the - * auth footers. - */ - - if(!prs_init(&out_hdr_ba, 1024, p->mem_ctx, MARSHALL)) { - DEBUG(0,("api_pipe_bind_req: malloc out_hdr_ba failed.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } - - /* * Create the bind response struct. */ @@ -1562,48 +1545,22 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) &pkt->u.bind.ctx_list[0].abstract_syntax, &pkt->u.bind.ctx_list[0].transfer_syntaxes[0], pkt->u.bind.ctx_list[0].context_id)) { - init_rpc_hdr_ba(&hdr_ba, - RPC_MAX_PDU_FRAG_LEN, - RPC_MAX_PDU_FRAG_LEN, - assoc_gid, - ack_pipe_name, - 0x1, 0x0, 0x0, - &pkt->u.bind.ctx_list[0].transfer_syntaxes[0]); + + bind_ack_ctx.result = 0; + bind_ack_ctx.reason = 0; + bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0]; } else { - /* Rejection reason: abstract syntax not supported */ - init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, - RPC_MAX_PDU_FRAG_LEN, assoc_gid, - ack_pipe_name, 0x1, 0x2, 0x1, - &null_ndr_syntax_id); p->pipe_bound = False; - } - - /* - * and marshall it. - */ - - if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n")); - goto err_exit; + /* Rejection reason: abstract syntax not supported */ + bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT; + bind_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX; + bind_ack_ctx.syntax = null_ndr_syntax_id; } /* * Check if this is an authenticated bind request. */ - if (pkt->auth_length) { - /* - * Decode the authentication verifier. - */ - - /* Work out any padding needed before the auth footer. */ - if ((RPC_HEADER_LEN + prs_offset(&out_hdr_ba)) % SERVER_NDR_PADDING_SIZE) { - ss_padding_len = SERVER_NDR_PADDING_SIZE - - ((RPC_HEADER_LEN + prs_offset(&out_hdr_ba)) % SERVER_NDR_PADDING_SIZE); - DEBUG(10,("api_pipe_bind_req: auth pad_len = %u\n", - (unsigned int)ss_padding_len )); - } - /* Quick length check. Won't catch a bad auth footer, * prevents overrun. */ @@ -1617,6 +1574,9 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) goto err_exit; } + /* + * Decode the authentication verifier. + */ status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.bind.auth_info, &auth_info); @@ -1640,11 +1600,8 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) (unsigned int)auth_info.auth_level )); goto err_exit; } - } else { - ZERO_STRUCT(auth_info); - } - switch(auth_type) { + switch (auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: if (!pipe_ntlmssp_auth_bind(p, pkt, &auth_info, &auth_resp)) { @@ -1668,26 +1625,72 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) break; case DCERPC_AUTH_TYPE_NONE: - /* Unauthenticated bind request. */ - /* We're finished - no more packets. */ - p->auth.auth_type = PIPE_AUTH_TYPE_NONE; - /* We must set the pipe auth_level here also. */ - p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE; - p->pipe_bound = True; - /* The session key was initialized from the SMB - * session in make_internal_rpc_pipe_p */ - ss_padding_len = 0; break; default: - DEBUG(0,("api_pipe_bind_req: unknown auth type %x requested.\n", auth_type )); + DEBUG(0, ("Unknown auth type %x requested.\n", auth_type)); goto err_exit; + } + } + + if (auth_type == DCERPC_AUTH_TYPE_NONE) { + /* Unauthenticated bind request. */ + /* We're finished - no more packets. */ + p->auth.auth_type = PIPE_AUTH_TYPE_NONE; + /* We must set the pipe auth_level here also. */ + p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE; + p->pipe_bound = True; + /* The session key was initialized from the SMB + * session in make_internal_rpc_pipe_p */ + } + + ZERO_STRUCT(u.bind_ack); + u.bind_ack.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; + u.bind_ack.max_recv_frag = RPC_MAX_PDU_FRAG_LEN; + u.bind_ack.assoc_group_id = assoc_gid; + + /* name has to be \PIPE\xxxxx */ + u.bind_ack.secondary_address = + talloc_asprintf(pkt, "\\PIPE\\%s", + rpc_srv_get_pipe_srv_name(&id)); + if (!u.bind_ack.secondary_address) { + DEBUG(0, ("Out of memory!\n")); + goto err_exit; + } + u.bind_ack.secondary_address_size = + strlen(u.bind_ack.secondary_address) + 1; + + u.bind_ack.num_results = 1; + u.bind_ack.ctx_list = &bind_ack_ctx; + + /* NOTE: We leave the auth_info empty so we can calculate the padding + * later and then append the auth_info --simo */ + + status = dcerpc_push_ncacn_packet(pkt, DCERPC_PKT_BIND_ACK, + DCERPC_PFC_FLAG_FIRST | + DCERPC_PFC_FLAG_LAST, + auth_resp.length, + pkt->call_id, + &u, &blob); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", + nt_errstr(status))); } + if (auth_resp.length) { + + /* Work out any padding needed before the auth footer. */ + pad_len = blob.length % SERVER_NDR_PADDING_SIZE; + if (pad_len) { + pad_len = SERVER_NDR_PADDING_SIZE - pad_len; + DEBUG(10, ("auth pad_len = %u\n", + (unsigned int)pad_len)); + } + status = dcerpc_push_dcerpc_auth(pkt, auth_type, auth_info.auth_level, - ss_padding_len, + pad_len, 1, /* auth_context_id */ &auth_resp, &auth_blob); @@ -1697,49 +1700,25 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) } } - /* - * Create the header, now we know the length. - */ - - if (auth_blob.length) { - auth_len = auth_blob.length - RPC_HDR_AUTH_LEN; - } - - init_rpc_hdr(&hdr, - DCERPC_PKT_BIND_ACK, - DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, - pkt->call_id, - RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + - ss_padding_len + auth_blob.length, - auth_len); - - /* - * Marshall the header into the outgoing PDU. - */ - - if (!smb_io_rpc_hdr("", &hdr, &p->out_data.frag, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR failed.\n")); - goto err_exit; - } - - /* - * Now add the RPC_HDR_BA and any auth needed. - */ + /* Now that we have the auth len store it into the right place in + * the dcerpc header */ + dcerpc_set_frag_length(&blob, blob.length + pad_len + auth_blob.length); - if(!prs_append_prs_data(&p->out_data.frag, &out_hdr_ba)) { - DEBUG(0,("api_pipe_bind_req: append of RPC_HDR_BA failed.\n")); + /* And finally copy all bits in the output pdu */ + if (!prs_copy_data_in(&p->out_data.frag, + (char *)blob.data, blob.length)) { + DEBUG(0, ("Failed to copy data to output buffer.\n")); goto err_exit; } - if (auth_len) { - if (ss_padding_len) { + if (auth_blob.length) { + if (pad_len) { char pad[SERVER_NDR_PADDING_SIZE]; memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!prs_copy_data_in(&p->out_data.frag, pad, - ss_padding_len)) { - DEBUG(0,("api_pipe_bind_req: failed to add %u " - "bytes of pad data.\n", - (unsigned int)ss_padding_len)); + if (!prs_copy_data_in(&p->out_data.frag, pad, pad_len)) { + DEBUG(0, ("api_pipe_bind_req: failed to add " + "%u bytes of pad data.\n", + (unsigned int)pad_len)); goto err_exit; } } @@ -1747,7 +1726,7 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) if (!prs_copy_data_in(&p->out_data.frag, (char *)auth_blob.data, auth_blob.length)) { - DEBUG(0,("api_pipe_bind_req: append of auth info failed.\n")); + DEBUG(0, ("Append of auth info failed.\n")); goto err_exit; } } @@ -1759,16 +1738,15 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) p->out_data.data_sent_length = 0; p->out_data.current_pdu_sent = 0; - prs_mem_free(&out_hdr_ba); TALLOC_FREE(auth_blob.data); - + TALLOC_FREE(blob.data); return True; err_exit: prs_mem_free(&p->out_data.frag); - prs_mem_free(&out_hdr_ba); TALLOC_FREE(auth_blob.data); + TALLOC_FREE(blob.data); return setup_bind_nak(p, pkt); } |