r13583: Realise that the member server name appears in all calls that use the
authorAndrew Bartlett <abartlet@samba.org>
Tue, 21 Feb 2006 00:07:59 +0000 (00:07 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:51:58 +0000 (13:51 -0500)
credentials.

Consistantly rename these elements in the IDL to computer_name.

Fix the server-side code to always lookup by this name.

Add new, even nastier tests to RPC-SCHANNEL to prove this.

Andrew Bartlett

source/auth/gensec/schannel_state.c
source/librpc/idl/netlogon.idl
source/rpc_server/netlogon/dcerpc_netlogon.c
source/torture/rpc/netlogon.c
source/torture/rpc/samlogon.c
source/torture/rpc/samsync.c
source/torture/rpc/schannel.c
source/winbind/wb_pam_auth.c

index a73e450ec81d99ffb21658172de90672dcda20bd..beaa8cfb08b7cd25eb3d6665446e496cfb19e624 100644 (file)
@@ -175,7 +175,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
 NTSTATUS schannel_fetch_session_key_ldb(TALLOC_CTX *mem_ctx,
                                        struct ldb_context *ldb,
                                        const char *computer_name, 
-                                       const char *domain, 
+                                       const char *domain,
                                        struct creds_CredentialState **creds)
 {
        struct ldb_result *res;
index fe0a1adbe4232c6c775790e6b963f6035799bd49..75d1b3316b62e71e441ea8fb7741ca2364f71987 100644 (file)
@@ -229,7 +229,7 @@ interface netlogon
 
        NTSTATUS netr_LogonSamLogon(
                [in] [string,charset(UTF16)] uint16 *server_name,
-               [in] [string,charset(UTF16)] uint16 *workstation,
+               [in] [string,charset(UTF16)] uint16 *computer_name,
                [in] netr_Authenticator *credential,
                [in][out] netr_Authenticator *return_authenticator,
                [in]  uint16 logon_level,
@@ -1096,7 +1096,7 @@ interface netlogon
        /* Function 0x27 */
        NTSTATUS netr_LogonSamLogonEx(
                [in] [string,charset(UTF16)] uint16 *server_name,
-               [in] [string,charset(UTF16)] uint16 *workstation,
+               [in] [string,charset(UTF16)] uint16 *computer_name,
                [in]  uint16 logon_level,
                [in]  [switch_is(logon_level)] netr_LogonLevel logon,
                [in]  uint16 validation_level,
@@ -1175,7 +1175,7 @@ interface netlogon
        /* this is the ADS varient. I don't yet know what the "flags" are for */
        NTSTATUS netr_LogonSamLogonWithFlags(
                [in] [string,charset(UTF16)] uint16 *server_name,
-               [in] [string,charset(UTF16)] uint16 *workstation,
+               [in] [string,charset(UTF16)] uint16 *computer_name,
                [in] netr_Authenticator *credential,
                [in][out] netr_Authenticator *return_authenticator,
                [in]  uint16 logon_level,
index 176246901b8cce4812db667b82ae41e400d880a5..d506d9192d529d701da9ce2aae936e764c34c902 100644 (file)
 struct server_pipe_state {
        struct netr_Credential client_challenge;
        struct netr_Credential server_challenge;
-
-       /* This is a bit (dangeroursly?) tricky:
-          - The session key, computer name and domain elements are
-            valid. 
-          - However the credentials chaining (seed, client, server etc)
-            should be obtained from the database at runtime */
-       struct creds_CredentialState *creds; 
 };
 
 
-/*
-  a client has connected to the netlogon server using schannel, so we need
-  to re-establish the credentials state
-*/
-static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call) 
-{
-       struct server_pipe_state *state;
-       NTSTATUS status;
-
-       /* We want the client and server challenge zero */
-       state = talloc_zero(dce_call->conn, struct server_pipe_state);
-       if (state == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       status = dcerpc_schannel_creds(dce_call->conn->auth_state.gensec_security, 
-                                      state, 
-                                      &state->creds);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("getting schannel credentials failed with %s\n", nt_errstr(status)));
-               talloc_free(state);
-               return status;
-       }
-       
-       dce_call->context->private = state;
-
-       return NT_STATUS_OK;
-}
-
-/*
-  a hook for bind on the netlogon pipe
-*/
-static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di) 
-{
-       dce_call->context->private = NULL;
-
-       /* if this is a schannel bind then we need to reconstruct the pipe state */
-       if (dce_call->conn->auth_state.auth_info &&
-           dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-               NTSTATUS status;
-
-               DEBUG(5, ("schannel bind on netlogon\n"));
-
-               status = netlogon_schannel_setup(dce_call);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(3, ("schannel bind on netlogon failed with %s\n", nt_errstr(status)));
-                       return status;
-               }
-       }
-
-       return NT_STATUS_OK;
-}
-
-#define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
-
 static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_ServerReqChallenge *r)
 {
@@ -116,8 +53,6 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL
                return NT_STATUS_NO_MEMORY;
        }
 
-       pipe_state->creds = NULL;
-
        pipe_state->client_challenge = *r->in.credentials;
 
        generate_random_buffer(pipe_state->server_challenge.data, 
@@ -238,12 +173,6 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
        /* remember this session key state */
        nt_status = schannel_store_session_key(mem_ctx, creds);
 
-       if (pipe_state->creds) {
-               talloc_free(pipe_state->creds);
-       }
-       talloc_steal(pipe_state, creds);
-       pipe_state->creds = creds;
-
        return nt_status;
 }
                                                 
@@ -302,7 +231,7 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL
   the caller needs some of that information.
 
 */
-static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state,
+static NTSTATUS netr_creds_server_step_check(const char *computer_name,
                                             TALLOC_CTX *mem_ctx, 
                                             struct netr_Authenticator *received_authenticator,
                                             struct netr_Authenticator *return_authenticator,
@@ -313,11 +242,6 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
        struct ldb_context *ldb;
        int ret;
 
-       if (!pipe_state) {
-               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        ldb = schannel_db_connect(mem_ctx);
        if (!ldb) {
                return NT_STATUS_ACCESS_DENIED;
@@ -333,8 +257,8 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
         * disconnects) we must update the database every time we
         * update the structure */ 
        
-       nt_status = schannel_fetch_session_key_ldb(ldb, ldb, pipe_state->creds->computer_name, 
-                                                  pipe_state->creds->domain, &creds);
+       nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name, lp_workgroup(),
+                                                  &creds);
        if (NT_STATUS_IS_OK(nt_status)) {
                nt_status = creds_server_step_check(creds, 
                                                    received_authenticator, 
@@ -365,12 +289,11 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
 static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                       struct netr_ServerPasswordSet *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private;
        struct creds_CredentialState *creds;
        struct ldb_context *sam_ctx;
        NTSTATUS nt_status;
 
-       nt_status = netr_creds_server_step_check(pipe_state, mem_ctx, 
+       nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
                                                 &r->in.credential, &r->out.return_authenticator,
                                                 &creds);
        NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -400,7 +323,6 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
 static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                       struct netr_ServerPasswordSet2 *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private;
        struct creds_CredentialState *creds;
        struct ldb_context *sam_ctx;
        NTSTATUS nt_status;
@@ -410,7 +332,7 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
 
        struct samr_CryptPassword password_buf;
 
-       nt_status = netr_creds_server_step_check(pipe_state, mem_ctx, 
+       nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
                                                 &r->in.credential, &r->out.return_authenticator,
                                                 &creds);
        NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -464,15 +386,15 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
 
 /* 
-  netr_LogonSamLogonEx
+  netr_LogonSamLogon_base
 
   This version of the function allows other wrappers to say 'do not check the credentials'
+
+  We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
 */
-static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                    struct netr_LogonSamLogonEx *r)
+static NTSTATUS netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                       struct netr_LogonSamLogonEx *r, struct creds_CredentialState *creds)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private;
-       struct creds_CredentialState *creds = pipe_state->creds;
        struct auth_context *auth_context;
        struct auth_usersupplied_info *user_info;
        struct auth_serversupplied_info *server_info;
@@ -496,7 +418,7 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
        case 1:
        case 3:
        case 5:
-               if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
                        creds_arcfour_crypt(creds, 
                                            r->in.logon.password->lmpassword.hash, 
                                            sizeof(r->in.logon.password->lmpassword.hash));
@@ -633,6 +555,23 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
        return NT_STATUS_OK;
 }
 
+static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                    struct netr_LogonSamLogonEx *r) 
+{
+       NTSTATUS nt_status;
+       struct creds_CredentialState *creds;
+       nt_status = schannel_fetch_session_key(mem_ctx, r->in.computer_name, lp_workgroup(), &creds);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+       if (!dce_call->conn->auth_state.auth_info
+           || dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+       return netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
+}
+
 /* 
   netr_LogonSamLogonWithFlags
 
@@ -640,8 +579,8 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
 static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                            struct netr_LogonSamLogonWithFlags *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private;
        NTSTATUS nt_status;
+       struct creds_CredentialState *creds;
        struct netr_LogonSamLogonEx r2;
 
        struct netr_Authenticator *return_authenticator;
@@ -649,21 +588,21 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
        return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
        NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
 
-       nt_status = netr_creds_server_step_check(pipe_state, mem_ctx, 
+       nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
                                                 r->in.credential, return_authenticator,
-                                                NULL);
+                                                &creds);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
        ZERO_STRUCT(r2);
 
        r2.in.server_name       = r->in.server_name;
-       r2.in.workstation       = r->in.workstation;
+       r2.in.computer_name     = r->in.computer_name;
        r2.in.logon_level       = r->in.logon_level;
        r2.in.logon             = r->in.logon;
        r2.in.validation_level  = r->in.validation_level;
        r2.in.flags             = r->in.flags;
 
-       nt_status = netr_LogonSamLogonEx(dce_call, mem_ctx, &r2);
+       nt_status = netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
 
        r->out.return_authenticator     = return_authenticator;
        r->out.validation               = r2.out.validation;
@@ -685,7 +624,7 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
        ZERO_STRUCT(r2);
 
        r2.in.server_name = r->in.server_name;
-       r2.in.workstation = r->in.workstation;
+       r2.in.computer_name = r->in.computer_name;
        r2.in.credential  = r->in.credential;
        r2.in.return_authenticator = r->in.return_authenticator;
        r2.in.logon_level = r->in.logon_level;
@@ -947,7 +886,6 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, struct ldb_message *
 static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_LogonGetDomainInfo *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private;
        const char * const attrs[] = { "dnsDomain", "objectSid", 
                                       "objectGUID", "flatName", "securityIdentifier",
                                       NULL };
@@ -960,7 +898,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
 
        const char *local_domain;
 
-       status = netr_creds_server_step_check(pipe_state, mem_ctx, 
+       status = netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
                                              r->in.credential, 
                                              r->out.return_authenticator,
                                              NULL);
index 7919e7c441ea215150954194434dd307066c3307..79e85cce578e1fb3dda8b6aedc1874f64c1e0b3b 100644 (file)
@@ -539,7 +539,7 @@ BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
 
        r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.workstation = cli_credentials_get_workstation(credentials);
+       r.in.computer_name = cli_credentials_get_workstation(credentials);
        r.in.credential = &auth;
        r.in.return_authenticator = &auth2;
        r.in.logon_level = 2;
@@ -564,7 +564,6 @@ BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        printf("Credential chaining failed\n");
                        ret = False;
                }
-               
        }
 
        r.in.credential = NULL;
@@ -573,7 +572,7 @@ BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
                r.in.validation_level = i;
 
-               printf("Testing SamLogon with validation level %d\n", i);
+               printf("Testing SamLogon with validation level %d and a NULL credential\n", i);
 
                status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
                if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
index 69c9ff6ea9d7a634302fc98ac3070880980755e6..03bec56ab634c03f8ca97adcd13ee282711a326e 100644 (file)
@@ -1335,17 +1335,17 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        generate_random_buffer(samlogon_state.chall.data, 8);
        samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
-       samlogon_state.r_flags.in.workstation = TEST_MACHINE_NAME;
+       samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
        samlogon_state.r_flags.in.credential = &samlogon_state.auth;
        samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
        samlogon_state.r_flags.in.flags = 0;
 
        samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
-       samlogon_state.r_ex.in.workstation = TEST_MACHINE_NAME;
+       samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
        samlogon_state.r_ex.in.flags = 0;
 
        samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
-       samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
+       samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
        samlogon_state.r.in.credential = &samlogon_state.auth;
        samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
 
@@ -1415,7 +1415,7 @@ BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        creds_client_authenticator(creds, &a);
 
        r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.workstation = TEST_MACHINE_NAME;
+       r.in.computer_name = TEST_MACHINE_NAME;
        r.in.credential = &a;
        r.in.return_authenticator = &ra;
        r.in.logon_level = 5;
index afa47e5932d9ff54bb91dfbb4cbe2d8fc33a0649..f0f19f0818a9a346dc392b1c53a71726b4745b96 100644 (file)
@@ -77,7 +77,7 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        }
 
        r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.workstation = workstation;
+       r.in.computer_name = workstation;
        r.in.credential = &auth;
        r.in.return_authenticator = &auth2;
        r.in.logon_level = 2;
index 80b223656d943d8e7b334bd5c6da0ee5042d71ea..3ad781c14528871aca4fe7ff18b3b4129a55da39 100644 (file)
@@ -85,7 +85,7 @@ BOOL test_netlogon_ex_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
 
        r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.workstation = cli_credentials_get_workstation(credentials);
+       r.in.computer_name = cli_credentials_get_workstation(credentials);
        r.in.logon_level = 2;
        r.in.logon.network = &ninfo;
        r.in.flags = 0;
@@ -238,6 +238,7 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx,
        struct dcerpc_pipe *p = NULL;
        struct dcerpc_pipe *p_netlogon = NULL;
        struct dcerpc_pipe *p_netlogon2 = NULL;
+       struct dcerpc_pipe *p_netlogon3 = NULL;
        struct dcerpc_pipe *p_samr2 = NULL;
        struct dcerpc_pipe *p_lsa = NULL;
        struct creds_CredentialState *creds;
@@ -395,14 +396,37 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx,
        
        /* Try the schannel-only SamLogonEx operation */
        if (!test_netlogon_ex_ops(p_netlogon2, test_ctx, credentials, creds)) {
-               printf("Failed to process schannel secured NETLOGON EX ops\n");
+               printf("Failed to process schannel secured NETLOGON EX ops (on fresh connection)\n");
                ret = False;
        }
 
        /* And the more traditional style, proving that the
         * credentials chaining state is fully present */
        if (!test_netlogon_ops(p_netlogon2, test_ctx, credentials, creds)) {
-               printf("Failed to process schannel secured NETLOGON EX ops\n");
+               printf("Failed to process schannel secured NETLOGON ops (on fresh connection)\n");
+               ret = False;
+       }
+
+       /* Drop the socket, we want to start from scratch (again) */
+       talloc_free(p_samr2);
+
+       /* We don't want schannel for this test */
+       b->flags &= ~DCERPC_AUTH_OPTIONS;
+
+       status = dcerpc_pipe_connect_b(test_ctx, &p_netlogon3, b, &dcerpc_table_netlogon,
+                                      credentials, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Failed to connect without schannel: %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       if (test_netlogon_ex_ops(p_netlogon3, test_ctx, credentials, creds)) {
+               printf("Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)\n");
+               ret = False;
+       }
+
+       if (!test_netlogon_ops(p_netlogon3, test_ctx, credentials, creds)) {
+               printf("Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth\n");
                ret = False;
        }
 
index 593cd22291dad5b1e85908fef13768ae15801ca0..f85cfd1f1aa91123d9a08bb0b79dfef22d53569b 100644 (file)
@@ -153,7 +153,7 @@ static void pam_auth_crap_recv_domain(struct composite_context *ctx)
 
        ZERO_STRUCT(state->auth2);
 
-       state->r.in.workstation =
+       state->r.in.computer_name =
                cli_credentials_get_workstation(domain->schannel_creds);
        state->r.in.credential = &state->auth;
        state->r.in.return_authenticator = &state->auth2;