summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Schneider <asn@cryptomilk.org>2012-03-09 16:48:57 +0100
committerAndreas Schneider <asn@cryptomilk.org>2012-03-09 16:48:57 +0100
commitff093f41d0516165a2d6deb4a35d3653b56b5bcb (patch)
tree6ec613462c40f552923f8ec870bf8be0f8e4bc5a
parent9d0b9cc8226cf7ecf74e8ae8b0d69a47b59071d1 (diff)
downloadsamba4-ff093f41d0516165a2d6deb4a35d3653b56b5bcb.tar.gz
samba4-ff093f41d0516165a2d6deb4a35d3653b56b5bcb.tar.xz
samba4-ff093f41d0516165a2d6deb4a35d3653b56b5bcb.zip
Add session key patch.
-rw-r--r--samba4-samr-lsa-session_key.patch434
-rw-r--r--samba4.spec2
2 files changed, 436 insertions, 0 deletions
diff --git a/samba4-samr-lsa-session_key.patch b/samba4-samr-lsa-session_key.patch
new file mode 100644
index 0000000..297f680
--- /dev/null
+++ b/samba4-samr-lsa-session_key.patch
@@ -0,0 +1,434 @@
+commit 23f06e8b48afdc9bdd698854bf7c8f80f9549911
+Author: Alexander Bokovoy <ab@samba.org>
+AuthorDate: Fri Mar 2 16:18:16 2012 +0200
+Commit: Andreas Schneider <asn@samba.org>
+CommitDate: Fri Mar 9 13:58:43 2012 +0100
+
+ s3-rpc: Decrypt with the proper session key in CreateTrustedDomainEx2.
+
+ 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>
+---
+ source3/auth/auth_util.c | 28 +++++++
+ source3/auth/proto.h | 1 +
+ source3/include/auth.h | 6 ++
+ source3/rpc_server/lsa/srv_lsa_nt.c | 127 +++++++++++++++++----------------
+ source3/rpc_server/samr/srv_samr_nt.c | 37 +++++-----
+ 5 files changed, 120 insertions(+), 79 deletions(-)
+
+diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
+index 21a8642..4f6ebfa 100644
+--- a/source3/auth/auth_util.c
++++ b/source3/auth/auth_util.c
+@@ -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;
++}
+diff --git a/source3/auth/proto.h b/source3/auth/proto.h
+index 01e2934..44ae909 100644
+--- a/source3/auth/proto.h
++++ b/source3/auth/proto.h
+@@ -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 */
+
+diff --git a/source3/include/auth.h b/source3/include/auth.h
+index 7f2c3e5..693a0df 100644
+--- a/source3/include/auth.h
++++ b/source3/include/auth.h
+@@ -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
+diff --git a/source3/rpc_server/lsa/srv_lsa_nt.c b/source3/rpc_server/lsa/srv_lsa_nt.c
+index 0a5cda5..48bdfdb 100644
+--- a/source3/rpc_server/lsa/srv_lsa_nt.c
++++ b/source3/rpc_server/lsa/srv_lsa_nt.c
+@@ -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,
+diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
+index ebe6e45..77888ea 100644
+--- a/source3/rpc_server/samr/srv_samr_nt.c
++++ b/source3/rpc_server/samr/srv_samr_nt.c
+@@ -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);
+
diff --git a/samba4.spec b/samba4.spec
index fc05f73..95cf227 100644
--- a/samba4.spec
+++ b/samba4.spec
@@ -53,6 +53,7 @@ Source6: samba.pamd
#Source7: smbprint
Patch1: samba4-libpdb-soversion.patch
+Patch2: samba4-samr-lsa-session_key.patch
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
@@ -297,6 +298,7 @@ link against the SMB, RPC and other protocols.
%setup -q -n samba-%{version}%{pre_release}
%patch1 -p1 -b .waf
+%patch2 -p1 -b .session_key
%build
%define talloc_lib %nil