*/
#include "includes.h"
-#include "../libcli/auth/libcli_auth.h"
#include "librpc/gen_ndr/cli_epmapper.h"
#include "../librpc/gen_ndr/ndr_schannel.h"
#include "../libcli/auth/schannel.h"
-#include "../libcli/auth/schannel_proto.h"
+#include "../libcli/auth/spnego.h"
+#include "smb_krb5.h"
+#include "ntlmssp.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_CLI
-/*******************************************************************
-interface/version dce/rpc pipe identification
-********************************************************************/
-
-#define PIPE_SRVSVC "\\PIPE\\srvsvc"
-#define PIPE_SAMR "\\PIPE\\samr"
-#define PIPE_WINREG "\\PIPE\\winreg"
-#define PIPE_WKSSVC "\\PIPE\\wkssvc"
-#define PIPE_NETLOGON "\\PIPE\\NETLOGON"
-#define PIPE_NTLSA "\\PIPE\\ntlsa"
-#define PIPE_NTSVCS "\\PIPE\\ntsvcs"
-#define PIPE_LSASS "\\PIPE\\lsass"
-#define PIPE_LSARPC "\\PIPE\\lsarpc"
-#define PIPE_SPOOLSS "\\PIPE\\spoolss"
-#define PIPE_NETDFS "\\PIPE\\netdfs"
-#define PIPE_ECHO "\\PIPE\\rpcecho"
-#define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
-#define PIPE_EPM "\\PIPE\\epmapper"
-#define PIPE_SVCCTL "\\PIPE\\svcctl"
-#define PIPE_EVENTLOG "\\PIPE\\eventlog"
-#define PIPE_EPMAPPER "\\PIPE\\epmapper"
-#define PIPE_DRSUAPI "\\PIPE\\drsuapi"
+static const char *get_pipe_name_from_iface(
+ TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface)
+{
+ int i;
+ const struct ndr_interface_string_array *ep = interface->endpoints;
+ char *p;
-/*
- * IMPORTANT!! If you update this structure, make sure to
- * update the index #defines in smb.h.
- */
+ for (i=0; i<ep->count; i++) {
+ if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) {
+ break;
+ }
+ }
+ if (i == ep->count) {
+ return NULL;
+ }
-static const struct pipe_id_info {
- /* the names appear not to matter: the syntaxes _do_ matter */
+ /*
+ * extract the pipe name without \\pipe from for example
+ * ncacn_np:[\\pipe\\epmapper]
+ */
+ p = strchr(ep->names[i]+15, ']');
+ if (p == NULL) {
+ return "PIPE";
+ }
+ return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15);
+}
- const char *client_pipe;
- const struct ndr_syntax_id *abstr_syntax; /* this one is the abstract syntax id */
-} pipe_names [] =
+static const struct ndr_interface_table **interfaces;
+
+bool smb_register_ndr_interface(const struct ndr_interface_table *interface)
{
- { PIPE_LSARPC, &ndr_table_lsarpc.syntax_id },
- { PIPE_LSARPC, &ndr_table_dssetup.syntax_id },
- { PIPE_SAMR, &ndr_table_samr.syntax_id },
- { PIPE_NETLOGON, &ndr_table_netlogon.syntax_id },
- { PIPE_SRVSVC, &ndr_table_srvsvc.syntax_id },
- { PIPE_WKSSVC, &ndr_table_wkssvc.syntax_id },
- { PIPE_WINREG, &ndr_table_winreg.syntax_id },
- { PIPE_SPOOLSS, &ndr_table_spoolss.syntax_id },
- { PIPE_NETDFS, &ndr_table_netdfs.syntax_id },
- { PIPE_ECHO, &ndr_table_rpcecho.syntax_id },
- { PIPE_SHUTDOWN, &ndr_table_initshutdown.syntax_id },
- { PIPE_SVCCTL, &ndr_table_svcctl.syntax_id },
- { PIPE_EVENTLOG, &ndr_table_eventlog.syntax_id },
- { PIPE_NTSVCS, &ndr_table_ntsvcs.syntax_id },
- { PIPE_EPMAPPER, &ndr_table_epmapper.syntax_id },
- { PIPE_DRSUAPI, &ndr_table_drsuapi.syntax_id },
- { NULL, NULL }
-};
+ int num_interfaces = talloc_array_length(interfaces);
+ const struct ndr_interface_table **tmp;
+ int i;
+
+ for (i=0; i<num_interfaces; i++) {
+ if (ndr_syntax_id_equal(&interfaces[i]->syntax_id,
+ &interface->syntax_id)) {
+ return true;
+ }
+ }
+
+ tmp = talloc_realloc(NULL, interfaces,
+ const struct ndr_interface_table *,
+ num_interfaces + 1);
+ if (tmp == NULL) {
+ DEBUG(1, ("smb_register_ndr_interface: talloc failed\n"));
+ return false;
+ }
+ interfaces = tmp;
+ interfaces[num_interfaces] = interface;
+ return true;
+}
+
+static bool initialize_interfaces(void)
+{
+ if (!smb_register_ndr_interface(&ndr_table_lsarpc)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_dssetup)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_samr)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_netlogon)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_srvsvc)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_wkssvc)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_winreg)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_spoolss)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_netdfs)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_rpcecho)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_initshutdown)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_svcctl)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_eventlog)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_epmapper)) {
+ return false;
+ }
+ if (!smb_register_ndr_interface(&ndr_table_drsuapi)) {
+ return false;
+ }
+ return true;
+}
+
+const struct ndr_interface_table *get_iface_from_syntax(
+ const struct ndr_syntax_id *syntax)
+{
+ int num_interfaces;
+ int i;
+
+ if (interfaces == NULL) {
+ if (!initialize_interfaces()) {
+ return NULL;
+ }
+ }
+ num_interfaces = talloc_array_length(interfaces);
+
+ for (i=0; i<num_interfaces; i++) {
+ if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) {
+ return interfaces[i];
+ }
+ }
+
+ return NULL;
+}
/****************************************************************************
Return the pipe name from the interface.
****************************************************************************/
-const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface)
+const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx,
+ const struct ndr_syntax_id *syntax)
{
+ const struct ndr_interface_table *interface;
char *guid_str;
const char *result;
- int i;
- for (i = 0; pipe_names[i].client_pipe; i++) {
- if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
- interface)) {
- return &pipe_names[i].client_pipe[5];
+
+ interface = get_iface_from_syntax(syntax);
+ if (interface != NULL) {
+ result = get_pipe_name_from_iface(mem_ctx, interface);
+ if (result != NULL) {
+ return result;
}
}
* interested in the known pipes mentioned in pipe_names[]
*/
- guid_str = GUID_string(talloc_tos(), &interface->uuid);
+ guid_str = GUID_string(talloc_tos(), &syntax->uuid);
if (guid_str == NULL) {
return NULL;
}
- result = talloc_asprintf(talloc_tos(), "Interface %s.%d", guid_str,
- (int)interface->if_version);
+ result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str,
+ (int)syntax->if_version);
TALLOC_FREE(guid_str);
if (result == NULL) {
RPC_HDR_AUTH auth_info;
uint32 save_offset = prs_offset(current_pdu);
uint32 auth_len = prhdr->auth_len;
- NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
+ struct ntlmssp_state *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
unsigned char *data = NULL;
size_t data_len;
unsigned char *full_packet_data = NULL;
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
"packet from %s. Error was %s.\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
nt_errstr(status) ));
return status;
}
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
"packet from %s. Error was %s.\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
nt_errstr(status) ));
return status;
}
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
"Connection to %s (%s).\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
nt_errstr(status)));
return NT_STATUS_INVALID_PARAMETER;
}
DEBUG(3, ("cli_pipe_validate_rpc_response: "
"Connection to %s - got non-zero "
"auth len %u.\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
(unsigned int)prhdr->auth_len ));
return NT_STATUS_INVALID_PARAMETER;
}
default:
DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
"to %s - unknown internal auth type %u.\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
cli->auth->auth_type ));
return NT_STATUS_INVALID_INFO_CLASS;
}
case DCERPC_PKT_BIND_NAK:
DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
"received from %s!\n",
- rpccli_pipe_txt(debug_ctx(), cli)));
+ rpccli_pipe_txt(talloc_tos(), cli)));
/* Use this for now... */
return NT_STATUS_NETWORK_ACCESS_DENIED;
DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
"code %s received from %s!\n",
- dcerpc_errstr(debug_ctx(), NT_STATUS_V(fault_resp.status)),
- rpccli_pipe_txt(debug_ctx(), cli)));
+ dcerpc_errstr(talloc_tos(), NT_STATUS_V(fault_resp.status)),
+ rpccli_pipe_txt(talloc_tos(), cli)));
if (NT_STATUS_IS_OK(fault_resp.status)) {
return NT_STATUS_UNSUCCESSFUL;
} else {
DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
"from %s!\n",
(unsigned int)prhdr->pkt_type,
- rpccli_pipe_txt(debug_ctx(), cli)));
+ rpccli_pipe_txt(talloc_tos(), cli)));
return NT_STATUS_INVALID_INFO_CLASS;
}
if (prhdr->pkt_type != expected_pkt_type) {
DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
"got an unexpected RPC packet type - %u, not %u\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
prhdr->pkt_type,
expected_pkt_type));
return NT_STATUS_INVALID_INFO_CLASS;
goto post_status;
}
- DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
+ DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
max_recv_frag = cli->max_recv_frag;
-#ifdef DEVELOPER
+#if 0
max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
#endif
if (rdata == NULL) {
DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
- rpccli_pipe_txt(debug_ctx(), state->cli)));
+ rpccli_pipe_txt(talloc_tos(), state->cli)));
tevent_req_done(req);
return;
}
*/
DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
"big-endian.\n",
- rpccli_pipe_txt(debug_ctx(), state->cli)));
+ rpccli_pipe_txt(talloc_tos(), state->cli)));
prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
}
/*
if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) {
DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
- rpccli_pipe_txt(debug_ctx(), state->cli),
+ rpccli_pipe_txt(talloc_tos(), state->cli),
(unsigned)prs_data_size(&state->incoming_pdu)));
tevent_req_done(req);
return;
/* 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, NULL, NULL);
+ &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
if (ret) {
DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
{
uint32 data_space, data_len;
-#ifdef DEVELOPER
+#if 0
if ((data_left > 0) && (sys_random() % 2)) {
data_left = MAX(data_left/2, 1);
}
}
DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
- rpccli_pipe_txt(debug_ctx(), cli),
+ rpccli_pipe_txt(talloc_tos(), cli),
(unsigned int)auth->auth_type,
(unsigned int)auth->auth_level ));
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
- rpccli_pipe_txt(debug_ctx(), state->cli),
+ rpccli_pipe_txt(talloc_tos(), state->cli),
nt_errstr(status)));
tevent_req_nterror(req, status);
return;
data_blob_free(&tmp_blob);
DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
- "%s.\n", rpccli_pipe_txt(debug_ctx(), state->cli)));
+ "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
tevent_req_done(req);
}
return 0;
}
-NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
+static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
enum pipe_auth_type auth_type,
enum dcerpc_AuthLevel auth_level,
const char *domain,
}
#endif
-NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
+static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
enum dcerpc_AuthLevel auth_level,
const char *service_princ,
const char *username,
NTSTATUS status;
uint16_t port = 0;
- *presult = NULL;
-
status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
if (!NT_STATUS_IS_OK(status)) {
- goto done;
+ return status;
}
- status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
+ return rpc_pipe_open_tcp_port(mem_ctx, host, port,
abstract_syntax, presult);
-
-done:
- return status;
}
/********************************************************************
}
DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
"%s failed with error %s\n",
- get_pipe_name_from_iface(interface),
+ get_pipe_name_from_syntax(talloc_tos(), interface),
nt_errstr(status) ));
TALLOC_FREE(result);
return status;
DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
"%s and bound anonymously.\n",
- get_pipe_name_from_iface(interface), cli->desthost));
+ get_pipe_name_from_syntax(talloc_tos(), interface),
+ cli->desthost));
*presult = result;
return NT_STATUS_OK;
DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
"machine %s and bound NTLMSSP as user %s\\%s.\n",
- get_pipe_name_from_iface(interface), cli->desthost, domain,
- username ));
+ get_pipe_name_from_syntax(talloc_tos(), interface),
+ cli->desthost, domain, username ));
*presult = result;
return NT_STATUS_OK;
const char *domain,
uint32 *pneg_flags)
{
- uint32 sec_chan_type = 0;
+ enum netr_SchannelType sec_chan_type = 0;
unsigned char machine_pwd[16];
const char *machine_account;
NTSTATUS status;
* in - reference them in
*/
result->dc = talloc_move(result, pdc);
- if (result->dc == NULL) {
- DEBUG(0, ("talloc reference failed\n"));
- TALLOC_FREE(result);
- return NT_STATUS_NO_MEMORY;
- }
DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
"for domain %s and bound using schannel.\n",
- get_pipe_name_from_iface(interface),
+ get_pipe_name_from_syntax(talloc_tos(), interface),
cli->desthost, domain ));
*presult = result;
*presult = result;
}
- return NT_STATUS_OK;
+ return status;
}
/****************************************************************************