s3-rpc: Decrypt with the proper session key in CreateTrustedDomainEx2. master
authorAlexander Bokovoy <ab@samba.org>
Fri, 2 Mar 2012 14:18:16 +0000 (16:18 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Tue, 13 Mar 2012 11:23:44 +0000 (12:23 +0100)
On LSA and SAMR pipes session_key is truncated to 16 byte when doing encryption/decryption.
However, this was not done for trusted domain-related modifying operations.

As result, Samba 4 client libraries do not work against Samba 3 while working
against Windows 2008 r2.

Solved this by introducing "session_extract_session_key()" function that allows to specify
intent of use of the key.

Signed-off-by: Andreas Schneider <asn@samba.org>
Autobuild-User: Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date: Tue Mar 13 12:23:44 CET 2012 on sn-devel-104

source3/auth/auth_util.c
source3/auth/proto.h
source3/include/auth.h
source3/rpc_server/lsa/srv_lsa_nt.c
source3/rpc_server/samr/srv_samr_nt.c

index 21a8642751a61c00857c84ce8bd14675707e2f32..4f6ebfa4a4afb4a78740d564148b70f58012c32b 100644 (file)
@@ -1618,3 +1618,31 @@ NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
 
        return status;
 }
+
+/*
+  Extract session key from a session info and return it in a blob
+  if intent is KEY_USE_16BYTES, truncate it to 16 bytes
+
+  See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
+  Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
+
+  Note that returned session_key is referencing the original key, it is supposed to be
+  short-lived. If original session_info->session_key is gone, the reference will be broken.
+*/
+NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
+{
+
+       if (session_key == NULL || session_info == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (session_info->session_key.length == 0) {
+               return NT_STATUS_NO_USER_SESSION_KEY;
+       }
+
+       *session_key = session_info->session_key;
+       if (intent == KEY_USE_16BYTES) {
+               session_key->length = MIN(session_info->session_key.length, 16);
+       }
+       return NT_STATUS_OK;
+}
index 01e2934dc7dd57b20ebd12520d5fa5ffaed6c96f..44ae9097a556fc9a783cb98a749df0f04b88d48b 100644 (file)
@@ -248,6 +248,7 @@ NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
                                          struct auth_serversupplied_info **server_info);
 void free_user_info(struct auth_usersupplied_info **user_info);
 bool is_trusted_domain(const char* dom_name);
+NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent);
 
 /* The following definitions come from auth/user_info.c  */
 
index 7f2c3e5db79b3a06958e415e18a253f1c11b8853..693a0df383cdced777504769c75a6178f0a4a97b 100644 (file)
@@ -128,6 +128,12 @@ struct auth_init_function_entry {
 
 extern const struct gensec_security_ops gensec_ntlmssp3_server_ops;
 
+/* Intent of use for session key. LSA and SAMR pipes use 16 bytes of session key when doing create/modify calls */
+enum session_key_use_intent {
+       KEY_USE_FULL = 0,
+       KEY_USE_16BYTES
+};
+
 /* Changed from 1 -> 2 to add the logon_parameters field. */
 /* Changed from 2 -> 3 when we reworked many auth structures to use IDL or be in common with Samba4 */
 #define AUTH_INTERFACE_VERSION 3
index 0a5cda503d2cd70e4198e47675af6d87665a91e2..48bdfdb8addaf69b367ea028aa3525ab015614ed 100644 (file)
@@ -287,7 +287,7 @@ static NTSTATUS lookup_lsa_sids(TALLOC_CTX *mem_ctx,
                        return NT_STATUS_NO_MEMORY;
                }
 
-               DEBUG(5, ("init_lsa_sids: looking up name %s\n", full_name));
+               DEBUG(5, ("lookup_lsa_sids: looking up name %s\n", full_name));
 
                if (!lookup_name(mem_ctx, full_name, flags, &domain, NULL,
                                 &sid, &type)) {
@@ -300,12 +300,12 @@ static NTSTATUS lookup_lsa_sids(TALLOC_CTX *mem_ctx,
                case SID_NAME_DOMAIN:
                case SID_NAME_ALIAS:
                case SID_NAME_WKN_GRP:
-                       DEBUG(5, ("init_lsa_sids: %s found\n", full_name));
+                       DEBUG(5, ("lookup_lsa_sids: %s found\n", full_name));
                        /* Leave these unchanged */
                        break;
                default:
                        /* Don't hand out anything but the list above */
-                       DEBUG(5, ("init_lsa_sids: %s not found\n", full_name));
+                       DEBUG(5, ("lookup_lsa_sids: %s not found\n", full_name));
                        type = SID_NAME_UNKNOWN;
                        break;
                }
@@ -1309,10 +1309,7 @@ NTSTATUS _lsa_LookupNames3(struct pipes_struct *p,
                DEBUG(5,("_lsa_LookupNames3: truncating name lookup list to %d\n", num_entries));
        }
 
-       /* Probably the lookup_level is some sort of bitmask. */
-       if (r->in.level == 1) {
-               flags = LOOKUP_NAME_ALL;
-       }
+       flags = lsa_lookup_level_to_flags(r->in.level);
 
        domains = talloc_zero(p->mem_ctx, struct lsa_RefDomainList);
        if (!domains) {
@@ -1660,6 +1657,46 @@ NTSTATUS _lsa_OpenTrustedDomainByName(struct pipes_struct *p,
                                           r->out.trustdom_handle);
 }
 
+static NTSTATUS get_trustdom_auth_blob(struct pipes_struct *p,
+                                      TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
+                                      struct trustDomainPasswords *auth_struct)
+{
+       enum ndr_err_code ndr_err;
+       DATA_BLOB lsession_key;
+       NTSTATUS status;
+
+       status = session_extract_session_key(p->session_info, &lsession_key, KEY_USE_16BYTES);
+       if (!NT_STATUS_IS_OK(status)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       arcfour_crypt_blob(auth_blob->data, auth_blob->length, &lsession_key);
+       ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
+                                      auth_struct,
+                                      (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS get_trustauth_inout_blob(TALLOC_CTX *mem_ctx,
+                                        struct trustAuthInOutBlob *iopw,
+                                        DATA_BLOB *trustauth_blob)
+{
+       enum ndr_err_code ndr_err;
+
+       ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
+                                      iopw,
+                                      (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return NT_STATUS_OK;
+}
+
 /***************************************************************************
  _lsa_CreateTrustedDomainEx2
  ***************************************************************************/
@@ -1674,7 +1711,6 @@ NTSTATUS _lsa_CreateTrustedDomainEx2(struct pipes_struct *p,
        size_t sd_size;
        struct pdb_trusted_domain td;
        struct trustDomainPasswords auth_struct;
-       enum ndr_err_code ndr_err;
        DATA_BLOB auth_blob;
 
        if (!IS_DC) {
@@ -1738,27 +1774,18 @@ NTSTATUS _lsa_CreateTrustedDomainEx2(struct pipes_struct *p,
                auth_blob.length = r->in.auth_info_internal->auth_blob.size;
                auth_blob.data = r->in.auth_info_internal->auth_blob.data;
 
-               arcfour_crypt_blob(auth_blob.data, auth_blob.length,
-                                  &p->session_info->session_key);
-
-               ndr_err = ndr_pull_struct_blob(&auth_blob, p->mem_ctx,
-                                              &auth_struct,
-                                              (ndr_pull_flags_fn_t) ndr_pull_trustDomainPasswords);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = get_trustdom_auth_blob(p, p->mem_ctx, &auth_blob, &auth_struct);
+               if (!NT_STATUS_IS_OK(status)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
 
-               ndr_err = ndr_push_struct_blob(&td.trust_auth_incoming, p->mem_ctx,
-                                              &auth_struct.incoming,
-                                              (ndr_push_flags_fn_t) ndr_push_trustAuthInOutBlob);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = get_trustauth_inout_blob(p->mem_ctx, &auth_struct.incoming, &td.trust_auth_incoming);
+               if (!NT_STATUS_IS_OK(status)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
 
-               ndr_err = ndr_push_struct_blob(&td.trust_auth_outgoing, p->mem_ctx,
-                                              &auth_struct.outgoing,
-                                              (ndr_push_flags_fn_t) ndr_push_trustAuthInOutBlob);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = get_trustauth_inout_blob(p->mem_ctx, &auth_struct.outgoing, &td.trust_auth_outgoing);
+               if (!NT_STATUS_IS_OK(status)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
        } else {
@@ -2244,6 +2271,7 @@ NTSTATUS _lsa_SetSecret(struct pipes_struct *p,
        DATA_BLOB cleartext_blob_old = data_blob_null;
        DATA_BLOB *cleartext_blob_new_p = NULL;
        DATA_BLOB *cleartext_blob_old_p = NULL;
+       DATA_BLOB session_key;
 
        if (!find_policy_by_hnd(p, r->in.sec_handle, (void **)(void *)&info)) {
                return NT_STATUS_INVALID_HANDLE;
@@ -2257,12 +2285,17 @@ NTSTATUS _lsa_SetSecret(struct pipes_struct *p,
                return NT_STATUS_ACCESS_DENIED;
        }
 
+       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        if (r->in.new_val) {
                blob_new = data_blob_const(r->in.new_val->data,
                                           r->in.new_val->length);
 
                status = sess_decrypt_blob(p->mem_ctx, &blob_new,
-                                          &p->session_info->session_key,
+                                          &session_key,
                                           &cleartext_blob_new);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
@@ -2276,7 +2309,7 @@ NTSTATUS _lsa_SetSecret(struct pipes_struct *p,
                                           r->in.old_val->length);
 
                status = sess_decrypt_blob(p->mem_ctx, &blob_old,
-                                          &p->session_info->session_key,
+                                          &session_key,
                                           &cleartext_blob_old);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
@@ -2310,6 +2343,7 @@ NTSTATUS _lsa_QuerySecret(struct pipes_struct *p,
        struct lsa_info *info = NULL;
        DATA_BLOB blob_new, blob_old;
        DATA_BLOB blob_new_crypt, blob_old_crypt;
+       DATA_BLOB session_key;
        NTTIME nttime_new, nttime_old;
        NTSTATUS status;
 
@@ -2333,6 +2367,11 @@ NTSTATUS _lsa_QuerySecret(struct pipes_struct *p,
                return status;
        }
 
+       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        if (r->in.new_val) {
                if (blob_new.length) {
                        if (!r->out.new_val->buf) {
@@ -2343,7 +2382,7 @@ NTSTATUS _lsa_QuerySecret(struct pipes_struct *p,
                        }
 
                        blob_new_crypt = sess_encrypt_blob(p->mem_ctx, &blob_new,
-                                                          &p->session_info->session_key);
+                                                          &session_key);
                        if (!blob_new_crypt.length) {
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -2364,7 +2403,7 @@ NTSTATUS _lsa_QuerySecret(struct pipes_struct *p,
                        }
 
                        blob_old_crypt = sess_encrypt_blob(p->mem_ctx, &blob_old,
-                                                          &p->session_info->session_key);
+                                                          &session_key);
                        if (!blob_old_crypt.length) {
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -3468,40 +3507,6 @@ static NTSTATUS info_ex_2_pdb_trusted_domain(
        return NT_STATUS_OK;
 }
 
-static NTSTATUS get_trustdom_auth_blob(struct pipes_struct *p,
-                                      TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
-                                      struct trustDomainPasswords *auth_struct)
-{
-       enum ndr_err_code ndr_err;
-
-       arcfour_crypt_blob(auth_blob->data, auth_blob->length,
-                          &p->session_info->session_key);
-       ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
-                                      auth_struct,
-                                      (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS get_trustauth_inout_blob(TALLOC_CTX *mem_ctx,
-                                        struct trustAuthInOutBlob *iopw,
-                                        DATA_BLOB *trustauth_blob)
-{
-       enum ndr_err_code ndr_err;
-
-       ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
-                                      iopw,
-                                      (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       return NT_STATUS_OK;
-}
-
 static NTSTATUS setInfoTrustedDomain_base(struct pipes_struct *p,
                                          TALLOC_CTX *mem_ctx,
                                          struct lsa_info *policy,
index ebe6e451d4f4dce6aba3813b825194b7e46e184f..77888ea1e8526182934e43f5dd94b002fe1e8919 100644 (file)
@@ -5036,6 +5036,7 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
        uint32_t fields = 0;
        bool ret;
        char *rhost;
+       DATA_BLOB session_key;
 
        DEBUG(5,("_samr_SetUserInfo: %d\n", __LINE__));
 
@@ -5193,10 +5194,14 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
                        break;
 
                case 18:
+                       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+                       if(!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        /* Used by AS/U JRA. */
                        status = set_user_info_18(&info->info18,
                                                  p->mem_ctx,
-                                                 &p->session_info->session_key,
+                                                 &session_key,
                                                  pwd);
                        break;
 
@@ -5206,18 +5211,20 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
                        break;
 
                case 21:
+                       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+                       if(!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        status = set_user_info_21(&info->info21,
                                                  p->mem_ctx,
-                                                 &p->session_info->session_key,
+                                                 &session_key,
                                                  pwd);
                        break;
 
                case 23:
-                       if (!p->session_info->session_key.length) {
-                               status = NT_STATUS_NO_USER_SESSION_KEY;
-                       }
+                       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
                        arcfour_crypt_blob(info->info23.password.data, 516,
-                                          &p->session_info->session_key);
+                                          &session_key);
 
                        dump_data(100, info->info23.password.data, 516);
 
@@ -5228,12 +5235,10 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
                        break;
 
                case 24:
-                       if (!p->session_info->session_key.length) {
-                               status = NT_STATUS_NO_USER_SESSION_KEY;
-                       }
+                       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
                        arcfour_crypt_blob(info->info24.password.data,
                                           516,
-                                          &p->session_info->session_key);
+                                          &session_key);
 
                        dump_data(100, info->info24.password.data, 516);
 
@@ -5243,12 +5248,10 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
                        break;
 
                case 25:
-                       if (!p->session_info->session_key.length) {
-                               status = NT_STATUS_NO_USER_SESSION_KEY;
-                       }
+                       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
                        encode_or_decode_arc4_passwd_buffer(
                                info->info25.password.data,
-                               &p->session_info->session_key);
+                               &session_key);
 
                        dump_data(100, info->info25.password.data, 532);
 
@@ -5258,12 +5261,10 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
                        break;
 
                case 26:
-                       if (!p->session_info->session_key.length) {
-                               status = NT_STATUS_NO_USER_SESSION_KEY;
-                       }
+                       status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
                        encode_or_decode_arc4_passwd_buffer(
                                info->info26.password.data,
-                               &p->session_info->session_key);
+                               &session_key);
 
                        dump_data(100, info->info26.password.data, 516);