1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

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>

Autobuild-User: Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date: Tue Mar 13 12:23:44 CET 2012 on sn-devel-104
This commit is contained in:
Alexander Bokovoy 2012-03-02 16:18:16 +02:00 committed by Andreas Schneider
parent e25f830f1d
commit 7d4ed89983
5 changed files with 120 additions and 79 deletions

View 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;
}

View 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 */

View 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

View 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,

View 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);