s3-rpc_server: use NL_AUTH_MESSAGE in pipe_schannel_auth_bind().
[ira/wip.git] / source3 / rpc_server / srv_pipe.c
index 09b1f664401afabfe7ce91192d11906ee10bd80b..e42c81ed4f118a28a537e00f2607b469403bf3d0 100644 (file)
@@ -28,6 +28,8 @@
  */
 
 #include "includes.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "../librpc/gen_ndr/ndr_schannel.h"
 
 extern struct current_user current_user;
 
@@ -950,8 +952,10 @@ bool setup_cancel_ack_reply(pipes_struct *p, prs_struct *rpc_in_p)
  Used to reject unknown binds from Win2k.
 *******************************************************************/
 
-bool check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
-                    RPC_IFACE* transfer, uint32 context_id)
+static bool check_bind_req(struct pipes_struct *p,
+                          struct ndr_syntax_id* abstract,
+                          struct ndr_syntax_id* transfer,
+                          uint32 context_id)
 {
        int i=0;
        struct pipe_rpc_fns *context_fns;
@@ -1323,44 +1327,63 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
                                        RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
 {
        RPC_HDR_AUTH auth_info;
-       RPC_AUTH_SCHANNEL_NEG neg;
+       struct NL_AUTH_MESSAGE neg;
        RPC_AUTH_VERIFIER auth_verifier;
        bool ret;
-       struct dcinfo *pdcinfo;
+       NTSTATUS status;
+       struct netlogon_creds_CredentialState *creds;
        uint32 flags;
        DATA_BLOB session_key;
+       enum ndr_err_code ndr_err;
+       DATA_BLOB blob;
+
+       blob = data_blob_const(prs_data_p(rpc_in_p) + prs_offset(rpc_in_p),
+                              prs_data_size(rpc_in_p));
 
-       if (!smb_io_rpc_auth_schannel_neg("", &neg, rpc_in_p, 0)) {
+       ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &neg,
+                              (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n"));
-               return False;
+               return false;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &neg);
+       }
+
+       if (!(neg.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME)) {
+               DEBUG(0,("pipe_schannel_auth_bind: Did not receive netbios computer name\n"));
+               return false;
        }
 
        /*
-        * The neg.myname key here must match the remote computer name
+        * The neg.oem_netbios_computer.a key here must match the remote computer name
         * given in the DOM_CLNT_SRV.uni_comp_name used on all netlogon pipe
         * operations that use credentials.
         */
 
        become_root();
-       ret = secrets_restore_schannel_session_info(p->mem_ctx, neg.myname, &pdcinfo);
+       status = schannel_fetch_session_key(p->mem_ctx,
+                                           neg.oem_netbios_computer.a,
+                                           &creds);
        unbecome_root();
 
-       if (!ret) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n"));
                return False;
        }
 
        p->auth.a_u.schannel_auth = talloc(p, struct schannel_auth_struct);
        if (!p->auth.a_u.schannel_auth) {
-               TALLOC_FREE(pdcinfo);
+               TALLOC_FREE(creds);
                return False;
        }
 
        memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key));
-       memcpy(p->auth.a_u.schannel_auth->sess_key, pdcinfo->sess_key,
-                       sizeof(pdcinfo->sess_key));
+       memcpy(p->auth.a_u.schannel_auth->sess_key, creds->session_key,
+                       sizeof(creds->session_key));
 
-       TALLOC_FREE(pdcinfo);
+       TALLOC_FREE(creds);
 
        p->auth.a_u.schannel_auth->seq_num = 0;
 
@@ -1413,7 +1436,7 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
        }
 
        DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n",
-               neg.domain, neg.myname));
+               neg.oem_netbios_domain.a, neg.oem_netbios_computer.a));
 
        /* We're finished with this bind - no more packets. */
        p->auth.auth_data_free_func = NULL;
@@ -1718,13 +1741,11 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
                        0x1, 0x0, 0x0,
                        &hdr_rb.rpc_context[0].transfer[0]);
        } else {
-               RPC_IFACE null_interface;
-               ZERO_STRUCT(null_interface);
                /* 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_interface);
+                                       &null_ndr_syntax_id);
                p->pipe_bound = False;
        }
 
@@ -1908,13 +1929,11 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p)
                        0x1, 0x0, 0x0,
                        &hdr_rb.rpc_context[0].transfer[0]);
        } else {
-               RPC_IFACE null_interface;
-               ZERO_STRUCT(null_interface);
                /* 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_interface);
+                                       &null_ndr_syntax_id);
                p->pipe_bound = False;
        }
 
@@ -2113,7 +2132,11 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
 
        auth_len = p->hdr.auth_len;
 
-       if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
+       if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN ||
+                       auth_len > RPC_HEADER_LEN +
+                                       RPC_HDR_REQ_LEN +
+                                       RPC_HDR_AUTH_LEN +
+                                       auth_len) {
                DEBUG(0,("Incorrect auth_len %u.\n", (unsigned int)auth_len ));
                return False;
        }