diff options
author | Andreas Schneider <asn@cryptomilk.org> | 2012-03-09 16:48:57 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2012-03-09 16:48:57 +0100 |
commit | ff093f41d0516165a2d6deb4a35d3653b56b5bcb (patch) | |
tree | 6ec613462c40f552923f8ec870bf8be0f8e4bc5a | |
parent | 9d0b9cc8226cf7ecf74e8ae8b0d69a47b59071d1 (diff) | |
download | samba4-ff093f41d0516165a2d6deb4a35d3653b56b5bcb.tar.gz samba4-ff093f41d0516165a2d6deb4a35d3653b56b5bcb.tar.xz samba4-ff093f41d0516165a2d6deb4a35d3653b56b5bcb.zip |
Add session key patch.
-rw-r--r-- | samba4-samr-lsa-session_key.patch | 434 | ||||
-rw-r--r-- | samba4.spec | 2 |
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 |