s3:ntlmssp: only include ntlmssp.h where actually needed
[samba.git] / source3 / rpc_client / cli_pipe.c
index 186696fbbcf259220e01107f27611d91d5499e7f..96531666d541603859386efe34a143a0594450ea 100644 (file)
  */
 
 #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;
                }
        }
 
@@ -102,12 +181,12 @@ const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface)
         * 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) {
@@ -553,7 +632,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr
        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;
@@ -617,7 +696,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr
                        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;
                        }
@@ -632,7 +711,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr
                        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;
                        }
@@ -755,7 +834,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
        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;
        }
@@ -813,7 +892,7 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_
                                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;
                        }
@@ -839,7 +918,7 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_
                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;
        }
@@ -943,7 +1022,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H
                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;
 
@@ -964,8 +1043,8 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H
 
                        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 {
@@ -977,14 +1056,14 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H
                        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;
@@ -1291,11 +1370,11 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
                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
 
@@ -1337,7 +1416,7 @@ static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
 
        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;
        }
@@ -1405,7 +1484,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
                 */
                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);
        }
        /*
@@ -1440,7 +1519,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 
        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;
@@ -1501,7 +1580,7 @@ static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
        /* 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 "
@@ -2004,7 +2083,7 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
 {
        uint32 data_space, data_len;
 
-#ifdef DEVELOPER
+#if 0
        if ((data_left > 0) && (sys_random() % 2)) {
                data_left = MAX(data_left/2, 1);
        }
@@ -2554,7 +2633,7 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
        }
 
        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 ));
 
@@ -2610,7 +2689,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
        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;
@@ -2913,7 +2992,7 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
        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);
 }
 
@@ -3012,7 +3091,7 @@ static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
        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,
@@ -3128,7 +3207,7 @@ static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
 }
 #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,
@@ -3390,18 +3469,13 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
        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;
 }
 
 /********************************************************************
@@ -3682,7 +3756,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
                }
                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;
@@ -3690,7 +3764,8 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
 
        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;
@@ -3748,8 +3823,8 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
 
        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;
@@ -3818,7 +3893,7 @@ static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon
                                                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;
@@ -3939,15 +4014,10 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
         * 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;
@@ -4068,7 +4138,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
                *presult = result;
        }
 
-       return NT_STATUS_OK;
+       return status;
 }
 
 /****************************************************************************