s4-rpc_server: use netlogon_creds_encrypt_samlogon().
[obnox/samba/samba-obnox.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
index 125fb3859eb60e4811620316001cd4921fa4af43..d463e85af15b571b44d1e3ca4a84770d29d95d6c 100644 (file)
@@ -91,40 +91,50 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
 
        const char *trust_dom_attrs[] = {"flatname", NULL};
        const char *account_name;
+       uint32_t negotiate_flags = 0;
 
        ZERO_STRUCTP(r->out.return_credentials);
        *r->out.rid = 0;
 
+       negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
+                         NETLOGON_NEG_PERSISTENT_SAMREPL |
+                         NETLOGON_NEG_ARCFOUR |
+                         NETLOGON_NEG_PROMOTION_COUNT |
+                         NETLOGON_NEG_CHANGELOG_BDC |
+                         NETLOGON_NEG_FULL_SYNC_REPL |
+                         NETLOGON_NEG_MULTIPLE_SIDS |
+                         NETLOGON_NEG_REDO |
+                         NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
+                         NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
+                         NETLOGON_NEG_GENERIC_PASSTHROUGH |
+                         NETLOGON_NEG_CONCURRENT_RPC |
+                         NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
+                         NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
+                         NETLOGON_NEG_TRANSITIVE_TRUSTS |
+                         NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
+                         NETLOGON_NEG_PASSWORD_SET2 |
+                         NETLOGON_NEG_GETDOMAININFO |
+                         NETLOGON_NEG_CROSS_FOREST_TRUSTS |
+                         NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
+                         NETLOGON_NEG_RODC_PASSTHROUGH |
+                         NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
+                         NETLOGON_NEG_AUTHENTICATED_RPC;
+
+       if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
+               negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
+       }
+
+       if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+               negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
+       }
+
        /*
         * According to Microsoft (see bugid #6099)
         * Windows 7 looks at the negotiate_flags
         * returned in this structure *even if the
         * call fails with access denied!
         */
-       *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
-                                 NETLOGON_NEG_PERSISTENT_SAMREPL |
-                                 NETLOGON_NEG_ARCFOUR |
-                                 NETLOGON_NEG_PROMOTION_COUNT |
-                                 NETLOGON_NEG_CHANGELOG_BDC |
-                                 NETLOGON_NEG_FULL_SYNC_REPL |
-                                 NETLOGON_NEG_MULTIPLE_SIDS |
-                                 NETLOGON_NEG_REDO |
-                                 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
-                                 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
-                                 NETLOGON_NEG_GENERIC_PASSTHROUGH |
-                                 NETLOGON_NEG_CONCURRENT_RPC |
-                                 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
-                                 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
-                                 NETLOGON_NEG_STRONG_KEYS |
-                                 NETLOGON_NEG_TRANSITIVE_TRUSTS |
-                                 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
-                                 NETLOGON_NEG_PASSWORD_SET2 |
-                                 NETLOGON_NEG_GETDOMAININFO |
-                                 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
-                                 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
-                                 NETLOGON_NEG_RODC_PASSTHROUGH |
-                                 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
-                                 NETLOGON_NEG_AUTHENTICATED_RPC;
+       *r->out.negotiate_flags = negotiate_flags;
 
        switch (r->in.secure_channel_type) {
        case SEC_CHAN_WKSTA:
@@ -261,8 +271,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
                                           mach_pwd,
                                           r->in.credentials,
                                           r->out.return_credentials,
-                                          *r->in.negotiate_flags);
-
+                                          negotiate_flags);
        if (!creds) {
                return NT_STATUS_ACCESS_DENIED;
        }
@@ -478,7 +487,12 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
 
        memcpy(password_buf.data, r->in.new_password->data, 512);
        SIVAL(password_buf.data, 512, r->in.new_password->length);
-       netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
+
+       if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+               netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
+       } else {
+               netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
+       }
 
        if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
                DEBUG(3,("samr: failed to decode password buffer\n"));
@@ -605,7 +619,6 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
        struct auth_usersupplied_info *user_info;
        struct auth_user_info_dc *user_info_dc;
        NTSTATUS nt_status;
-       static const char zeros[16];
        struct netr_SamBaseInfo *sam;
        struct netr_SamInfo2 *sam2;
        struct netr_SamInfo3 *sam3;
@@ -621,7 +634,14 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
        case NetlogonServiceInformation:
        case NetlogonInteractiveTransitiveInformation:
        case NetlogonServiceTransitiveInformation:
-               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+               if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+                       netlogon_creds_aes_decrypt(creds,
+                                                  r->in.logon->password->lmpassword.hash,
+                                                  sizeof(r->in.logon->password->lmpassword.hash));
+                       netlogon_creds_aes_decrypt(creds,
+                                                  r->in.logon->password->ntpassword.hash,
+                                                  sizeof(r->in.logon->password->ntpassword.hash));
+               } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
                        netlogon_creds_arcfour_crypt(creds,
                                            r->in.logon->password->lmpassword.hash,
                                            sizeof(r->in.logon->password->lmpassword.hash));
@@ -684,7 +704,10 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 
        case NetlogonGenericInformation:
        {
-               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+               if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+                       netlogon_creds_aes_decrypt(creds,
+                                           r->in.logon->generic->data, r->in.logon->generic->length);
+               } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
                        netlogon_creds_arcfour_crypt(creds,
                                            r->in.logon->generic->data, r->in.logon->generic->length);
                } else {
@@ -793,31 +816,9 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
                return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
-       /* It appears that level 6 is not individually encrypted */
-       if ((r->in.validation_level != 6) &&
-           memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
-               /* This key is sent unencrypted without the ARCFOUR flag set */
-               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
-                       netlogon_creds_arcfour_crypt(creds,
-                                           sam->key.key,
-                                           sizeof(sam->key.key));
-               }
-       }
-
-       /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
-       /* It appears that level 6 is not individually encrypted */
-       if ((r->in.validation_level != 6) &&
-           memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
-               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
-                       netlogon_creds_arcfour_crypt(creds,
-                                           sam->LMSessKey.key,
-                                           sizeof(sam->LMSessKey.key));
-               } else {
-                       netlogon_creds_des_encrypt_LMKey(creds,
-                                               &sam->LMSessKey);
-               }
-       }
+       netlogon_creds_encrypt_samlogon_validation(creds,
+                                                  r->in.validation_level,
+                                                  r->out.validation);
 
        /* TODO: Describe and deal with these flags */
        *r->out.flags = 0;
@@ -1234,9 +1235,27 @@ static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state
 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonGetCapabilities *r)
 {
+       struct netlogon_creds_CredentialState *creds;
+       NTSTATUS status;
 
-       /* we don't support AES yet */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       status = dcesrv_netr_creds_server_step_check(dce_call,
+                                                    mem_ctx,
+                                                    r->in.computer_name,
+                                                    r->in.credential,
+                                                    r->out.return_authenticator,
+                                                    &creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,(__location__ " Bad credentials - error\n"));
+       }
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       if (r->in.query_level != 1) {
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       r->out.capabilities->server_capabilities = creds->negotiate_flags;
+
+       return NT_STATUS_OK;
 }
 
 
@@ -1296,6 +1315,11 @@ static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TAL
                return WERR_DS_UNAVAILABLE;
        }
 
+       /*
+        * We assume to be a DC when we get called over NETLOGON. Hence we
+        * get our site name always by using "samdb_server_site_name()"
+        * and not "samdb_client_site_name()".
+        */
        *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
        W_ERROR_HAVE_NO_MEMORY(*r->out.site);
 
@@ -1653,7 +1677,8 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
                }
 
                domain_info->workstation_flags =
-                       r->in.query->workstation_info->workstation_flags;
+                       r->in.query->workstation_info->workstation_flags & (
+                       NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
 
                r->out.info->domain_info = domain_info;
        break;
@@ -2083,21 +2108,6 @@ static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_ca
 }
 
 
-#define GET_CHECK_STR(dest, mem, msg, attr) \
-do {\
-       const char *s; \
-       s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
-       if (!s) { \
-               DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
-                         "without flatname\n", \
-                         ldb_dn_get_linearized(msg->dn))); \
-               continue; \
-       } \
-       dest = talloc_strdup(mem, s); \
-       W_ERROR_HAVE_NO_MEMORY(dest); \
-} while(0)
-
-
 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
                                         struct ldb_context *sam_ctx,
                                         struct netr_DomainTrustList *trusts,
@@ -2153,10 +2163,14 @@ static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
                                               n + 1);
                W_ERROR_HAVE_NO_MEMORY(trusts->array);
 
-               GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
-                             dom_res[i], "flatname");
-               GET_CHECK_STR(trusts->array[n].dns_name, trusts,
-                             dom_res[i], "trustPartner");
+               trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
+               if (!trusts->array[n].netbios_name) {
+                       DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
+                                 "without flatname\n", 
+                                 ldb_dn_get_linearized(dom_res[i]->dn)));
+               }
+
+               trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
 
                trusts->array[n].trust_flags = flags;
                if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&