diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/kludge_acl.c | 15 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/objectclass.c | 37 | ||||
-rw-r--r-- | source4/kdc/kdc.c | 2 | ||||
-rw-r--r-- | source4/libcli/raw/smb_signing.c | 5 | ||||
-rw-r--r-- | source4/libcli/util/nterr.c | 1 | ||||
-rw-r--r-- | source4/libcli/util/ntstatus.h | 1 | ||||
-rw-r--r-- | source4/librpc/idl/drsblobs.idl | 62 | ||||
-rw-r--r-- | source4/librpc/idl/lsa.idl | 66 | ||||
-rw-r--r-- | source4/rpc_server/lsa/dcesrv_lsa.c | 488 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 2 | ||||
-rw-r--r-- | source4/setup/mmr_syncrepl.conf | 1 | ||||
-rw-r--r-- | source4/smb_server/smb/sesssetup.c | 12 | ||||
-rw-r--r-- | source4/smb_server/smb/signing.c | 8 | ||||
-rw-r--r-- | source4/torture/rpc/lsa.c | 166 |
14 files changed, 695 insertions, 171 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c index 2c01594722..bc998a835a 100644 --- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c +++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c @@ -238,7 +238,6 @@ static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ld { switch (ac->user_type) { case SECURITY_SYSTEM: - case SECURITY_ADMINISTRATOR: if (ac->allowedAttributesEffective) { ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributesEffective"); if (ret != LDB_SUCCESS) { @@ -252,6 +251,20 @@ static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ld } } break; + case SECURITY_ADMINISTRATOR: + if (ac->allowedAttributesEffective) { + ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributesEffective"); + if (ret != LDB_SUCCESS) { + return ret; + } + } + if (ac->allowedChildClassesEffective) { + ret = kludge_acl_childClasses(ldb, ares->message, "allowedChildClassesEffective"); + if (ret != LDB_SUCCESS) { + return ret; + } + } + /* fall though */ default: /* remove password attributes */ for (i = 0; data->password_attrs[i]; i++) { diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 4d4ef585cb..b048a8d8e1 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -534,6 +534,8 @@ static int objectclass_do_add(struct ldb_handle *h) } /* Last one is the critical one */ if (!current->next) { + struct ldb_message_element *el; + int32_t systemFlags = 0; if (!ldb_msg_find_element(msg, "objectCategory")) { ldb_msg_add_string(msg, "objectCategory", current->objectclass->defaultObjectCategory); @@ -548,6 +550,41 @@ static int objectclass_do_add(struct ldb_handle *h) ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); } } + + /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */ + el = ldb_msg_find_element(msg, "systemFlags"); + + systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0); + + if (el) { + /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */ + /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */ + ldb_msg_remove_element(msg, el); + } + + /* This flag is only allowed on attributeSchema objects */ + if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "attributeSchema") == 0) { + systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN; + } + + if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "server") == 0) { + systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE); + } else if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "site") == 0 + || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "serverContainer") == 0 + || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "ntDSDSA") == 0) { + systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE); + + } else if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLink") == 0 + || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLinkBridge") == 0 + || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "nTDSConnection") == 0) { + systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME); + } + + /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */ + + if (el || systemFlags != 0) { + samdb_msg_add_int(ac->module->ldb, msg, msg, "systemFlags", systemFlags); + } } } } diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index 5d7b48afe4..b7009b030f 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -3,7 +3,7 @@ KDC Server startup - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008 Copyright (C) Andrew Tridgell 2005 Copyright (C) Stefan Metzmacher 2005 diff --git a/source4/libcli/raw/smb_signing.c b/source4/libcli/raw/smb_signing.c index 97bb688d1a..1d03686d9a 100644 --- a/source4/libcli/raw/smb_signing.c +++ b/source4/libcli/raw/smb_signing.c @@ -263,7 +263,6 @@ bool smbcli_set_signing_off(struct smb_signing_context *sign_info) { DEBUG(5, ("Shutdown SMB signing\n")); sign_info->doing_signing = false; - sign_info->next_seq_num = 0; data_blob_free(&sign_info->mac_key); sign_info->signing_state = SMB_SIGNING_ENGINE_OFF; return true; @@ -350,9 +349,6 @@ bool smbcli_simple_set_signing(TALLOC_CTX *mem_ctx, dump_data_pw("Started Signing with key:\n", sign_info->mac_key.data, sign_info->mac_key.length); - /* Initialise the sequence number */ - sign_info->next_seq_num = 0; - sign_info->signing_state = SMB_SIGNING_ENGINE_ON; return true; @@ -379,6 +375,7 @@ bool smbcli_transport_simple_set_signing(struct smbcli_transport *transport, bool smbcli_init_signing(struct smbcli_transport *transport) { + transport->negotiate.sign_info.next_seq_num = 0; transport->negotiate.sign_info.mac_key = data_blob(NULL, 0); if (!smbcli_set_signing_off(&transport->negotiate.sign_info)) { return false; diff --git a/source4/libcli/util/nterr.c b/source4/libcli/util/nterr.c index ef4055adaa..4e046c78ca 100644 --- a/source4/libcli/util/nterr.c +++ b/source4/libcli/util/nterr.c @@ -545,6 +545,7 @@ static const nt_err_code_struct nt_errs[] = { "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES }, { "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED }, { "NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX", NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX }, + { "NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED", NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED }, { "NT_STATUS_OBJECTID_NOT_FOUND", NT_STATUS_OBJECTID_NOT_FOUND }, { "NT_STATUS_DOWNGRADE_DETECTED", NT_STATUS_DOWNGRADE_DETECTED }, { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES }, diff --git a/source4/libcli/util/ntstatus.h b/source4/libcli/util/ntstatus.h index 527a95bd09..9c7bee0dfe 100644 --- a/source4/libcli/util/ntstatus.h +++ b/source4/libcli/util/ntstatus.h @@ -591,6 +591,7 @@ typedef uint32_t NTSTATUS; #define NT_STATUS_QUOTA_LIST_INCONSISTENT NT_STATUS(0xC0000000 | 0x0266) #define NT_STATUS_FILE_IS_OFFLINE NT_STATUS(0xC0000000 | 0x0267) #define NT_STATUS_NOT_A_REPARSE_POINT NT_STATUS(0xC0000000 | 0x0275) +#define NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED NT_STATUS(0xC0000000 | 0x02E9) #define NT_STATUS_OBJECTID_NOT_FOUND NT_STATUS(0xC0000000 | 0x02F0) #define NT_STATUS_NO_SUCH_JOB NT_STATUS(0xC0000000 | 0xEDE) /* scheduler */ #define NT_STATUS_DOWNGRADE_DETECTED NT_STATUS(0xC0000000 | 0x0388) diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index eb85989eda..196423c7dd 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -1,6 +1,6 @@ #include "idl_types.h" -import "drsuapi.idl", "misc.idl", "samr.idl"; +import "drsuapi.idl", "misc.idl", "samr.idl", "lsa.idl"; [ uuid("12345778-1234-abcd-0001-00000001"), @@ -12,7 +12,7 @@ interface drsblobs { typedef bitmap drsuapi_DsReplicaSyncOptions drsuapi_DsReplicaSyncOptions; typedef bitmap drsuapi_DsReplicaNeighbourFlags drsuapi_DsReplicaNeighbourFlags; typedef [v1_enum] enum drsuapi_DsAttributeId drsuapi_DsAttributeId; - + typedef [v1_enum] enum lsa_TrustAuthType lsa_TrustAuthType; /* * replPropertyMetaData * w2k uses version 1 @@ -357,25 +357,6 @@ interface drsblobs { ); typedef struct { - NTTIME time1; - uint32 unknown1; - DATA_BLOB value; - [flag(NDR_ALIGN4)] DATA_BLOB _pad; - } trustAuthInOutSecret1; - - typedef struct { - [relative] trustAuthInOutSecret1 *value1; - [relative] trustAuthInOutSecret1 *value2; - } trustAuthInOutCtr1; - - typedef [v1_enum] enum { - TRUST_AUTH_TYPE_NONE = 0, - TRUST_AUTH_TYPE_NT4OWF = 1, - TRUST_AUTH_TYPE_CLEAR = 2, - TRUST_AUTH_TYPE_VERSION = 3 - } trustAuthType; - - typedef struct { [value(0)] uint32 size; } AuthInfoNone; @@ -384,6 +365,20 @@ interface drsblobs { samr_Password password; } AuthInfoNT4Owf; + /* + * the secret value is encoded as UTF16 if it's a string + * but depending the AuthType, it might also be krb5 trusts have random bytes here, so converting to UTF16 + * mayfail... + * + * TODO: We should try handle the case of a random buffer in all places + * we deal with cleartext passwords from windows + * + * so we don't use this: + * + * uint32 value_len; + * [charset(UTF16)] uint8 value[value_len]; + */ + typedef struct { uint32 size; uint8 password[size]; @@ -403,21 +398,8 @@ interface drsblobs { typedef [public] struct { NTTIME LastUpdateTime; - trustAuthType AuthType; + lsa_TrustAuthType AuthType; - /* - * the secret value is encoded as UTF16 if it's a string - * but depending the AuthType, it might also be krb5 trusts have random bytes here, so converting to UTF16 - * mayfail... - * - * TODO: We should try handle the case of a random buffer in all places - * we deal with cleartext passwords from windows - * - * so we don't use this: - * - * uint32 value_len; - * [charset(UTF16)] uint8 value[value_len]; - */ [switch_is(AuthType)] AuthInfo AuthInfo; [flag(NDR_ALIGN4)] DATA_BLOB _pad; } AuthenticationInformation; @@ -427,12 +409,20 @@ interface drsblobs { [size_is(1)] AuthenticationInformation array[]; } AuthenticationInformationArray; - typedef [public,nopull,nopush,noprint] struct { + typedef [public,nopull,nopush,noprint,gensize] struct { uint32 count; [relative] AuthenticationInformationArray *current; [relative] AuthenticationInformationArray *previous; } trustAuthInOutBlob; + typedef [public] struct { + uint8 confounder[512]; + trustAuthInOutBlob outgoing; + trustAuthInOutBlob incoming; + [value(ndr_size_trustAuthInOutBlob(&outgoing, ndr->flags))] uint32 outgoing_size; + [value(ndr_size_trustAuthInOutBlob(&incoming, ndr->flags))] uint32 incoming_size; + } trustAuthInAndOutBlob; + void decode_trustAuthInOut( [in] trustAuthInOutBlob blob ); diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 408956b3fa..b26d50c173 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -311,7 +311,7 @@ import "misc.idl", "security.idl"; /* Function: 0x0c */ [public] NTSTATUS lsa_CreateTrustedDomain( - [in] policy_handle *handle, + [in] policy_handle *policy_handle, [in] lsa_DomainInfo *info, [in] uint32 access_mask, [out] policy_handle *trustdom_handle @@ -578,9 +578,16 @@ import "misc.idl", "security.idl"; lsa_TrustAttributes trust_attributes; } lsa_TrustDomainInfoInfoEx; + typedef [public,v1_enum] enum { + TRUST_AUTH_TYPE_NONE = 0, + TRUST_AUTH_TYPE_NT4OWF = 1, + TRUST_AUTH_TYPE_CLEAR = 2, + TRUST_AUTH_TYPE_VERSION = 3 + } lsa_TrustAuthType; + typedef struct { NTTIME_hyper last_update_time; - uint32 secret_type; + lsa_TrustAuthType AuthType; lsa_DATA_BUF2 data; } lsa_TrustDomainInfoBuffer; @@ -600,16 +607,26 @@ import "misc.idl", "security.idl"; } lsa_TrustDomainInfoFullInfo; typedef struct { + lsa_DATA_BUF2 auth_blob; + } lsa_TrustDomainInfoAuthInfoInternal; + + typedef struct { + lsa_TrustDomainInfoInfoEx info_ex; + lsa_TrustDomainInfoPosixOffset posix_offset; + lsa_TrustDomainInfoAuthInfoInternal auth_info; + } lsa_TrustDomainInfoFullInfoInternal; + + typedef struct { lsa_TrustDomainInfoInfoEx info_ex; - lsa_DATA_BUF2 data1; + uint32 forest_trust_length; + [size_is(forest_trust_length)] uint8 *forest_trust_data; } lsa_TrustDomainInfoInfoEx2Internal; typedef struct { - lsa_TrustDomainInfoInfoEx info_ex; - lsa_DATA_BUF2 data1; + lsa_TrustDomainInfoInfoEx2Internal info; lsa_TrustDomainInfoPosixOffset posix_offset; lsa_TrustDomainInfoAuthInfo auth_info; - } lsa_TrustDomainInfoInfo2Internal; + } lsa_TrustDomainInfoFullInfo2Internal; typedef struct { kerb_EncTypes enc_types; @@ -633,13 +650,13 @@ import "misc.idl", "security.idl"; [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)] lsa_TrustDomainInfoFullInfo full_info; [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL)] - lsa_TrustDomainInfoAuthInfo auth_info_internal; + lsa_TrustDomainInfoAuthInfoInternal auth_info_internal; [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL)] - lsa_TrustDomainInfoFullInfo full_info_internal; + lsa_TrustDomainInfoFullInfoInternal full_info_internal; [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL)] lsa_TrustDomainInfoInfoEx2Internal info_ex2_internal; [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL)] - lsa_TrustDomainInfoInfo2Internal info2_internal; + lsa_TrustDomainInfoFullInfo2Internal full_info2_internal; [case(LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES)] lsa_TrustDomainInfoSupportedEncTypes enc_types; } lsa_TrustedDomainInfo; @@ -652,7 +669,11 @@ import "misc.idl", "security.idl"; ); /* Function: 0x1b */ - [todo] NTSTATUS lsa_SetInformationTrustedDomain(); + NTSTATUS lsa_SetInformationTrustedDomain( + [in] policy_handle *trustdom_handle, + [in] lsa_TrustDomInfoEnum level, + [in,switch_is(level)] lsa_TrustedDomainInfo *info + ); /* Function: 0x1c */ [public] NTSTATUS lsa_OpenSecret( @@ -770,7 +791,12 @@ import "misc.idl", "security.idl"; ); /* Function: 0x28 */ - [todo] NTSTATUS lsa_SetTrustedDomainInfo(); + NTSTATUS lsa_SetTrustedDomainInfo( + [in] policy_handle *handle, + [in] dom_sid2 *dom_sid, + [in] lsa_TrustDomInfoEnum level, + [in,switch_is(level)] lsa_TrustedDomainInfo *info + ); /* Function: 0x29 */ NTSTATUS lsa_DeleteTrustedDomain( [in] policy_handle *handle, @@ -855,9 +881,15 @@ import "misc.idl", "security.idl"; [in] uint32 max_size ); - /* Function 0x33 */ - [todo] NTSTATUS lsa_CreateTrustedDomainEx(); + NTSTATUS lsa_CreateTrustedDomainEx( + [in] policy_handle *policy_handle, + [in] lsa_TrustDomainInfoInfoEx *info, + [in] lsa_TrustDomainInfoAuthInfoInternal *auth_info, + [in] uint32 access_mask, + [out] policy_handle *trustdom_handle + ); + /* Function 0x34 */ NTSTATUS lsa_CloseTrustedDomainEx( @@ -971,7 +1003,13 @@ import "misc.idl", "security.idl"; ); /* Function 0x3b */ - [todo] NTSTATUS lsa_CreateTrustedDomainEx2(); + NTSTATUS lsa_CreateTrustedDomainEx2( + [in] policy_handle *policy_handle, + [in] lsa_TrustDomainInfoInfoEx *info, + [in] lsa_TrustDomainInfoAuthInfoInternal *auth_info, + [in] uint32 access_mask, + [out] policy_handle *trustdom_handle + ); /* Function 0x3c */ [todo] NTSTATUS lsa_CREDRWRITE(); diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index f67b5dee10..a1ca3b4a46 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -4,7 +4,7 @@ endpoint server for the lsarpc pipe Copyright (C) Andrew Tridgell 2004 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,9 @@ #include "libcli/ldap/ldap_ndr.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" +#include "librpc/gen_ndr/ndr_lsa.h" +#include "lib/crypto/crypto.h" /* this type allows us to distinguish handle types @@ -58,6 +61,7 @@ struct lsa_trusted_domain_state { struct lsa_policy_state *policy; uint32_t access_mask; struct ldb_dn *trusted_domain_dn; + struct ldb_dn *trusted_domain_user_dn; }; static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, @@ -138,13 +142,32 @@ static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_OK; } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) { struct lsa_trusted_domain_state *trusted_domain_state = h->data; + ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb); + if (ret != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + ret = ldb_delete(trusted_domain_state->policy->sam_ldb, trusted_domain_state->trusted_domain_dn); - talloc_free(h); if (ret != 0) { + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); return NT_STATUS_INVALID_HANDLE; } + if (trusted_domain_state->trusted_domain_user_dn) { + ret = ldb_delete(trusted_domain_state->policy->sam_ldb, + trusted_domain_state->trusted_domain_user_dn); + if (ret != 0) { + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + return NT_STATUS_INVALID_HANDLE; + } + } + + ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb); + if (ret != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + talloc_free(h); ZERO_STRUCTP(r->out.handle); return NT_STATUS_OK; @@ -585,49 +608,45 @@ static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALL /* lsa_CreateTrustedDomainEx2 */ -static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct lsa_CreateTrustedDomainEx2 *r) -{ - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); -} - -/* - lsa_CreateTrustedDomainEx -*/ -static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct lsa_CreateTrustedDomainEx *r) -{ - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); -} - -/* - lsa_CreateTrustedDomain -*/ -static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_CreateTrustedDomain *r) +static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct lsa_CreateTrustedDomainEx2 *r, + int op) { struct dcesrv_handle *policy_handle; struct lsa_policy_state *policy_state; struct lsa_trusted_domain_state *trusted_domain_state; struct dcesrv_handle *handle; - struct ldb_message **msgs, *msg; + struct ldb_message **msgs, *msg, *msg_user; const char *attrs[] = { NULL }; + const char *netbios_name; + const char *dns_name; const char *name; + DATA_BLOB session_key = data_blob(NULL, 0); + DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob; + struct trustAuthInAndOutBlob auth_struct; int ret; - - DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); + NTSTATUS nt_status; + enum ndr_err_code ndr_err; + + DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY); ZERO_STRUCTP(r->out.trustdom_handle); policy_state = policy_handle->data; - if (!r->in.info->name.string) { + nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + netbios_name = r->in.info->netbios_name.string; + if (!netbios_name) { return NT_STATUS_INVALID_PARAMETER; } - name = r->in.info->name.string; + + dns_name = r->in.info->domain_name.string; trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state); if (!trusted_domain_state) { @@ -635,36 +654,115 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_cal } trusted_domain_state->policy = policy_state; - msg = ldb_msg_new(mem_ctx); - if (msg == NULL) { - return NT_STATUS_NO_MEMORY; + if (strcasecmp(netbios_name, "BUILTIN") == 0 + || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0) + || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) { + return NT_STATUS_INVALID_PARAMETER;; } - /* search for the trusted_domain record */ - ret = gendb_search(trusted_domain_state->policy->sam_ldb, - mem_ctx, policy_state->system_dn, &msgs, attrs, - "(&(cn=%s)(objectclass=trustedDomain))", - ldb_binary_encode_string(mem_ctx, r->in.info->name.string)); - if (ret > 0) { - return NT_STATUS_OBJECT_NAME_COLLISION; + if (strcasecmp(netbios_name, policy_state->domain_name) == 0 + || strcasecmp(netbios_name, policy_state->domain_dns) == 0 + || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0) + || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0) + || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) { + return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED; + } + + /* While this is a REF pointer, some of the functions that wrap this don't provide this */ + if (op == NDR_LSA_CREATETRUSTEDDOMAIN) { + /* No secrets are created at this time, for this function */ + auth_struct.outgoing.count = 0; + auth_struct.incoming.count = 0; + } else { + auth_blob = data_blob_const(r->in.auth_info->auth_blob.data, r->in.auth_info->auth_blob.size); + arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key); + ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx, + lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), + &auth_struct, + (ndr_pull_flags_fn_t)ndr_pull_trustAuthInAndOutBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NT_STATUS_INVALID_PARAMETER; + } + } + + if (auth_struct.incoming.count) { + ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx, + lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), + &auth_struct.incoming, + (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NT_STATUS_INVALID_PARAMETER; + } + } else { + trustAuthIncoming = data_blob(NULL, 0); } - if (ret < 0 || ret > 1) { - DEBUG(0,("Found %d records matching DN %s\n", ret, - ldb_dn_get_linearized(policy_state->system_dn))); + if (auth_struct.outgoing.count) { + ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx, + lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), + &auth_struct.outgoing, + (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NT_STATUS_INVALID_PARAMETER; + } + } else { + trustAuthOutgoing = data_blob(NULL, 0); + } + + ret = ldb_transaction_start(policy_state->sam_ldb); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (dns_name) { + char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name); + char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name); + /* search for the trusted_domain record */ + ret = gendb_search(policy_state->sam_ldb, + mem_ctx, policy_state->system_dn, &msgs, attrs, + "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", + dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded); + if (ret > 0) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + } else { + char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name); + /* search for the trusted_domain record */ + ret = gendb_search(policy_state->sam_ldb, + mem_ctx, policy_state->system_dn, &msgs, attrs, + "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", + netbios_encoded, netbios_encoded, netbios_encoded); + if (ret > 0) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + } + + if (ret < 0 ) { + ldb_transaction_cancel(policy_state->sam_ldb); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + name = dns_name ? dns_name : netbios_name; + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + return NT_STATUS_NO_MEMORY; + } + msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn); if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) { + ldb_transaction_cancel(policy_state->sam_ldb); return NT_STATUS_NO_MEMORY; } - samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", name); + samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", netbios_name); if (r->in.info->sid) { const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid); if (!sid_string) { + ldb_transaction_cancel(policy_state->sam_ldb); return NT_STATUS_NO_MEMORY; } @@ -672,7 +770,32 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_cal } samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain"); + + samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type); + + samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes); + + samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction); + if (dns_name) { + samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustPartner", dns_name); + } + + if (trustAuthIncoming.data) { + ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_NO_MEMORY; + } + } + if (trustAuthOutgoing.data) { + ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_NO_MEMORY; + } + } + trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn); /* create the trusted_domain */ @@ -700,6 +823,94 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_cal return NT_STATUS_INTERNAL_DB_CORRUPTION; } + if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) { + msg_user = ldb_msg_new(mem_ctx); + if (msg == NULL) { + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + /* Inbound trusts must also create a cn=users object to match */ + + trusted_domain_state->trusted_domain_user_dn = msg_user->dn + = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn); + if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + ldb_msg_add_string(msg_user, "objectClass", "user"); + + ldb_msg_add_steal_string(msg_user, "samAccountName", + talloc_asprintf(mem_ctx, "%s$", netbios_name)); + + if (samdb_msg_add_uint(trusted_domain_state->policy->sam_ldb, mem_ctx, msg_user, + "userAccountControl", + UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) { + ldb_transaction_cancel(policy_state->sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + if (auth_struct.incoming.count) { + int i; + for (i=0; i < auth_struct.incoming.count; i++ ) { + if (auth_struct.incoming.current->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) { + samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb, + mem_ctx, msg_user, "unicodePwd", + &auth_struct.incoming.current->array[i].AuthInfo.nt4owf.password); + } else if (auth_struct.incoming.current->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) { + struct samr_Password hash; +/* + . We cannot do this, as windows chooses to send in random passwords here, that won't convert to UTF8 + samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, + mem_ctx, msg_user, "userPassword", + auth_struct.incoming.current->array[i].AuthInfo.clear.password); +*/ + mdfour(hash.hash, auth_struct.incoming.current->array[i].AuthInfo.clear.password, + auth_struct.incoming.current->array[i].AuthInfo.clear.size); + samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb, + mem_ctx, msg_user, "unicodePwd", + &hash); + } + } + } + + /* create the cn=users trusted_domain account */ + ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg_user); + switch (ret) { + case LDB_SUCCESS: + break; + case LDB_ERR_ENTRY_ALREADY_EXISTS: + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + DEBUG(0,("Failed to create trusted domain record %s: %s\n", + ldb_dn_get_linearized(msg_user->dn), + ldb_errstring(trusted_domain_state->policy->sam_ldb))); + return NT_STATUS_DOMAIN_EXISTS; + case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + DEBUG(0,("Failed to create trusted domain record %s: %s\n", + ldb_dn_get_linearized(msg_user->dn), + ldb_errstring(trusted_domain_state->policy->sam_ldb))); + return NT_STATUS_ACCESS_DENIED; + default: + ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb); + DEBUG(0,("Failed to create user record %s: %s\n", + ldb_dn_get_linearized(msg_user->dn), + ldb_errstring(trusted_domain_state->policy->sam_ldb))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } + + ret = ldb_transaction_commit(policy_state->sam_ldb); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN); if (!handle) { return NT_STATUS_NO_MEMORY; @@ -715,6 +926,59 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_cal return NT_STATUS_OK; } +/* + lsa_CreateTrustedDomainEx2 +*/ +static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct lsa_CreateTrustedDomainEx2 *r) +{ + return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2); +} +/* + lsa_CreateTrustedDomainEx +*/ +static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct lsa_CreateTrustedDomainEx *r) +{ + struct lsa_CreateTrustedDomainEx2 r2; + + r2.in.policy_handle = r->in.policy_handle; + r2.in.info = r->in.info; + r2.in.auth_info = r->in.auth_info; + r2.out.trustdom_handle = r->out.trustdom_handle; + return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX); +} + +/* + lsa_CreateTrustedDomain +*/ +static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct lsa_CreateTrustedDomain *r) +{ + struct lsa_CreateTrustedDomainEx2 r2; + + r2.in.policy_handle = r->in.policy_handle; + r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx); + if (!r2.in.info) { + return NT_STATUS_NO_MEMORY; + } + + r2.in.info->domain_name.string = NULL; + r2.in.info->netbios_name = r->in.info->name; + r2.in.info->sid = r->in.info->sid; + r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND; + r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL; + r2.in.info->trust_attributes = 0; + + r2.in.access_mask = r->in.access_mask; + r2.out.trustdom_handle = r->out.trustdom_handle; + + return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN); + +} + /* lsa_OpenTrustedDomain */ @@ -728,6 +992,8 @@ static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, struct dcesrv_handle *handle; struct ldb_message **msgs; const char *attrs[] = { + "trustDirection", + "flatname", NULL }; @@ -765,7 +1031,20 @@ static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, } trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn); - + + trusted_domain_state->trusted_domain_user_dn = NULL; + + if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) { + const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL)); + /* search for the trusted_domain record */ + ret = gendb_search(trusted_domain_state->policy->sam_ldb, + mem_ctx, policy_state->domain_dn, &msgs, attrs, + "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))", + flatname, UF_INTERDOMAIN_TRUST_ACCOUNT); + if (ret == 1) { + trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn); + } + } handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN); if (!handle) { return NT_STATUS_NO_MEMORY; @@ -988,10 +1267,10 @@ static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_ return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex); case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL: - ZERO_STRUCT(r->out.info->info2_internal); - r->out.info->info2_internal.posix_offset.posix_offset + ZERO_STRUCT(r->out.info->full_info2_internal); + r->out.info->full_info2_internal.posix_offset.posix_offset = samdb_result_uint(msg, "posixOffset", 0); - return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info2_internal.info_ex); + return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info2_internal.info.info_ex); case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES: r->out.info->enc_types.enc_types @@ -1739,7 +2018,9 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL if (strncmp("G$", r->in.name.string, 2) == 0) { const char *name2; name = &r->in.name.string[2]; - secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb); + /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */ + secret_state->sam_ldb = talloc_reference(secret_state, + samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx))); secret_state->global = true; if (strlen(name) < 1) { @@ -1883,7 +2164,9 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC if (strncmp("G$", r->in.name.string, 2) == 0) { name = &r->in.name.string[2]; - secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb); + /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */ + secret_state->sam_ldb = talloc_reference(secret_state, + samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx))); secret_state->global = true; if (strlen(name) < 1) { @@ -2012,16 +2295,60 @@ static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_NO_MEMORY; } - if (!r->in.new_val) { - /* set old value mtime */ - if (samdb_msg_add_uint64(secret_state->sam_ldb, - mem_ctx, msg, "lastSetTime", nt_now) != 0) { + } else { + /* If the old value is not set, then migrate the + * current value to the old value */ + const struct ldb_val *old_val; + NTTIME last_set_time; + struct ldb_message **res; + const char *attrs[] = { + "currentValue", + "lastSetTime", + NULL + }; + + /* search for the secret record */ + ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx, + secret_state->secret_dn, &res, attrs); + if (ret == 0) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (ret != 1) { + DEBUG(0,("Found %d records matching dn=%s\n", ret, + ldb_dn_get_linearized(secret_state->secret_dn))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + old_val = ldb_msg_find_ldb_val(res[0], "currentValue"); + last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0); + + if (old_val) { + /* set old value */ + if (samdb_msg_add_value(secret_state->sam_ldb, + mem_ctx, msg, "priorValue", + old_val) != 0) { return NT_STATUS_NO_MEMORY; } + } else { if (samdb_msg_add_delete(secret_state->sam_ldb, - mem_ctx, msg, "currentValue")) { + mem_ctx, msg, "priorValue")) { return NT_STATUS_NO_MEMORY; } + + } + + /* set old value mtime */ + if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) { + if (samdb_msg_add_uint64(secret_state->sam_ldb, + mem_ctx, msg, "priorSetTime", last_set_time) != 0) { + return NT_STATUS_NO_MEMORY; + } + } else { + if (samdb_msg_add_uint64(secret_state->sam_ldb, + mem_ctx, msg, "priorSetTime", nt_now) != 0) { + return NT_STATUS_NO_MEMORY; + } } } @@ -2050,50 +2377,15 @@ static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_NO_MEMORY; } - /* If the old value is not set, then migrate the - * current value to the old value */ - if (!r->in.old_val) { - const struct ldb_val *new_val; - NTTIME last_set_time; - struct ldb_message **res; - const char *attrs[] = { - "currentValue", - "lastSetTime", - NULL - }; - - /* search for the secret record */ - ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx, - secret_state->secret_dn, &res, attrs); - if (ret == 0) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - if (ret != 1) { - DEBUG(0,("Found %d records matching dn=%s\n", ret, - ldb_dn_get_linearized(secret_state->secret_dn))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - new_val = ldb_msg_find_ldb_val(res[0], "currentValue"); - last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0); - - if (new_val) { - /* set value */ - if (samdb_msg_add_value(secret_state->sam_ldb, - mem_ctx, msg, "priorValue", - new_val) != 0) { - return NT_STATUS_NO_MEMORY; - } - } - - /* set new value mtime */ - if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) { - if (samdb_msg_add_uint64(secret_state->sam_ldb, - mem_ctx, msg, "priorSetTime", last_set_time) != 0) { - return NT_STATUS_NO_MEMORY; - } - } + } else { + /* NULL out the NEW value */ + if (samdb_msg_add_uint64(secret_state->sam_ldb, + mem_ctx, msg, "lastSetTime", nt_now) != 0) { + return NT_STATUS_NO_MEMORY; + } + if (samdb_msg_add_delete(secret_state->sam_ldb, + mem_ctx, msg, "currentValue")) { + return NT_STATUS_NO_MEMORY; } } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 36ac650b08..6f4287f9d8 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -3,7 +3,7 @@ endpoint server for the netlogon pipe - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005 This program is free software; you can redistribute it and/or modify diff --git a/source4/setup/mmr_syncrepl.conf b/source4/setup/mmr_syncrepl.conf index 5fa8b8f8a0..3a207b2d13 100644 --- a/source4/setup/mmr_syncrepl.conf +++ b/source4/setup/mmr_syncrepl.conf @@ -9,4 +9,3 @@ syncrepl rid=${RID} binddn="CN=Manager,${MMRDN}" credentials="${MMR_PASSWORD}" - diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index 2c4068bda5..f45cbf1756 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -188,11 +188,6 @@ static void sesssetup_nt1_send(struct auth_check_password_request *areq, req->session = smb_sess; sess->nt1.out.vuid = smb_sess->vuid; - if (!session_info->server_info->authenticated) { - /* don't try signing as anonymous */ - goto done; - } - if (!smbsrv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) { /* Already signing, or disabled */ goto done; @@ -205,7 +200,8 @@ static void sesssetup_nt1_send(struct auth_check_password_request *areq, /* Unfortunetly win2k3 as a client doesn't sign the request * packet here, so we have to force signing to start again */ - smbsrv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2); + smbsrv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2, + session_info->server_info->authenticated); done: status = NT_STATUS_OK; @@ -326,12 +322,12 @@ static void sesssetup_spnego_send(struct gensec_update_request *greq, void *priv skey_status = gensec_session_key(smb_sess->gensec_ctx, &session_key); if (NT_STATUS_IS_OK(skey_status) && - session_info->server_info->authenticated && smbsrv_setup_signing(req->smb_conn, &session_key, NULL)) { /* Force check of the request packet, now we know the session key */ smbsrv_signing_check_incoming(req); - smbsrv_signing_restart(req->smb_conn, &session_key, NULL); + smbsrv_signing_restart(req->smb_conn, &session_key, NULL, + session_info->server_info->authenticated); } /* Ensure this is marked as a 'real' vuid, not one diff --git a/source4/smb_server/smb/signing.c b/source4/smb_server/smb/signing.c index 186f5548ab..ee4531c8f6 100644 --- a/source4/smb_server/smb/signing.c +++ b/source4/smb_server/smb/signing.c @@ -77,7 +77,8 @@ bool smbsrv_setup_signing(struct smbsrv_connection *smb_conn, void smbsrv_signing_restart(struct smbsrv_connection *smb_conn, DATA_BLOB *session_key, - DATA_BLOB *response) + DATA_BLOB *response, + bool authenticated_session) { if (!smb_conn->signing.seen_valid) { DEBUG(5, ("Client did not send a valid signature on " @@ -85,7 +86,9 @@ void smbsrv_signing_restart(struct smbsrv_connection *smb_conn, /* force things back on (most clients do not sign this packet)... */ smbsrv_setup_signing(smb_conn, session_key, response); smb_conn->signing.next_seq_num = 2; - if (smb_conn->signing.mandatory_signing) { + + /* If mandetory_signing is set, and this was an authenticated logon, then force on */ + if (smb_conn->signing.mandatory_signing && authenticated_session) { DEBUG(5, ("Configured for mandatory signing, 'good packet seen' forced on\n")); /* if this is mandatory, then * pretend we have seen a @@ -117,6 +120,7 @@ bool smbsrv_init_signing(struct smbsrv_connection *smb_conn) case SMB_SIGNING_AUTO: if (lp_server_role(smb_conn->lp_ctx) == ROLE_DOMAIN_CONTROLLER) { smb_conn->signing.allow_smb_signing = true; + smb_conn->signing.mandatory_signing = true; } else { smb_conn->signing.allow_smb_signing = false; } diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index ec74426ac6..a13a8d8818 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -23,11 +23,13 @@ #include "torture/torture.h" #include "librpc/gen_ndr/ndr_lsa_c.h" #include "librpc/gen_ndr/netlogon.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" #include "lib/events/events.h" #include "libcli/security/security.h" #include "libcli/auth/libcli_auth.h" #include "torture/rpc/rpc.h" #include "param/param.h" +#include "lib/crypto/crypto.h" #define TEST_MACHINENAME "lsatestmach" static void init_lsa_String(struct lsa_String *name, const char *s) @@ -1882,6 +1884,9 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, return false; } + /* Start from the bottom again */ + resume_handle = 0; + do { r.in.handle = handle; r.in.resume_handle = &resume_handle; @@ -2000,7 +2005,7 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p, trustinfo.sid = domsid[i]; init_lsa_String((struct lsa_String *)&trustinfo.name, trust_name); - r.in.handle = handle; + r.in.policy_handle = handle; r.in.info = &trustinfo; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.trustdom_handle = &trustdom_handle[i]; @@ -2016,7 +2021,7 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p, } else { q.in.trustdom_handle = &trustdom_handle[i]; - q.in.level = LSA_TRUSTED_DOMAIN_INFO_NAME; + q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX; status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); if (!NT_STATUS_IS_OK(status)) { printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status)); @@ -2024,9 +2029,156 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p, } else if (!q.out.info) { ret = false; } else { - if (strcmp(q.out.info->name.netbios_name.string, trustinfo.name.string) != 0) { + if (strcmp(q.out.info->info_ex.netbios_name.string, trustinfo.name.string) != 0) { printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n", - q.out.info->name.netbios_name.string, trustinfo.name.string); + q.out.info->info_ex.netbios_name.string, trustinfo.name.string); + ret = false; + } + if (q.out.info->info_ex.trust_type != LSA_TRUST_TYPE_DOWNLEVEL) { + printf("QueryTrustedDomainInfo of %s returned incorrect trust type %d != %d\n", + trust_name, q.out.info->info_ex.trust_type, LSA_TRUST_TYPE_DOWNLEVEL); + ret = false; + } + if (q.out.info->info_ex.trust_attributes != 0) { + printf("QueryTrustedDomainInfo of %s returned incorrect trust attributes %d != %d\n", + trust_name, q.out.info->info_ex.trust_attributes, 0); + ret = false; + } + if (q.out.info->info_ex.trust_direction != LSA_TRUST_DIRECTION_OUTBOUND) { + printf("QueryTrustedDomainInfo of %s returned incorrect trust direction %d != %d\n", + trust_name, q.out.info->info_ex.trust_direction, LSA_TRUST_DIRECTION_OUTBOUND); + ret = false; + } + } + } + } + + /* now that we have some domains to look over, we can test the enum calls */ + if (!test_EnumTrustDom(p, mem_ctx, handle)) { + ret = false; + } + + for (i=0; i<12; i++) { + if (!test_DeleteTrustedDomainBySid(p, mem_ctx, handle, domsid[i])) { + ret = false; + } + } + + return ret; +} + +static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p, + struct torture_context *tctx, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + NTSTATUS status; + bool ret = true; + struct lsa_CreateTrustedDomainEx2 r; + struct lsa_TrustDomainInfoInfoEx trustinfo; + struct lsa_TrustDomainInfoAuthInfoInternal authinfo; + struct trustAuthInAndOutBlob auth_struct; + DATA_BLOB auth_blob; + struct dom_sid *domsid[12]; + struct policy_handle trustdom_handle[12]; + struct lsa_QueryTrustedDomainInfo q; + DATA_BLOB session_key; + enum ndr_err_code ndr_err; + int i; + + printf("Testing CreateTrustedDomainEx2 for 12 domains\n"); + + status = dcerpc_fetch_session_key(p, &session_key); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_fetch_session_key failed - %s\n", nt_errstr(status)); + return false; + } + + for (i=0; i< 12; i++) { + char *trust_name = talloc_asprintf(mem_ctx, "torturedom%02d", i); + char *trust_name_dns = talloc_asprintf(mem_ctx, "torturedom%02d.samba.example.com", i); + char *trust_sid = talloc_asprintf(mem_ctx, "S-1-5-21-97398-379795-100%02d", i); + + domsid[i] = dom_sid_parse_talloc(mem_ctx, trust_sid); + + trustinfo.sid = domsid[i]; + trustinfo.netbios_name.string = trust_name; + trustinfo.domain_name.string = trust_name_dns; + + /* Create inbound, some outbound, and some + * bi-directional trusts in a repeating pattern based + * on i */ + + /* 1 == inbound, 2 == outbound, 3 == both */ + trustinfo.trust_direction = (i % 3) + 1; + + /* Try different trust types too */ + + /* 1 == downleven (NT4), 2 == uplevel (ADS), 3 == MIT (kerberos but not AD) */ + trustinfo.trust_type = (((i / 3) + 1) % 3) + 1; + + trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION; + + generate_random_buffer(auth_struct.confounder, sizeof(auth_struct.confounder)); + + auth_struct.outgoing.count = 0; + auth_struct.incoming.count = 0; + + ndr_err = ndr_push_struct_blob(&auth_blob, mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &auth_struct, + (ndr_push_flags_fn_t)ndr_push_trustAuthInAndOutBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + printf("ndr_push_struct_blob of trustAuthInAndOutBlob structure failed"); + ret = false; + } + + arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key); + + authinfo.auth_blob.size = auth_blob.length; + authinfo.auth_blob.data = auth_blob.data; + + r.in.policy_handle = handle; + r.in.info = &trustinfo; + r.in.auth_info = &authinfo; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.trustdom_handle = &trustdom_handle[i]; + + status = dcerpc_lsa_CreateTrustedDomainEx2(p, mem_ctx, &r); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + test_DeleteTrustedDomain(p, mem_ctx, handle, trustinfo.netbios_name); + status = dcerpc_lsa_CreateTrustedDomainEx2(p, mem_ctx, &r); + } + if (!NT_STATUS_IS_OK(status)) { + printf("CreateTrustedDomainEx failed2 - %s\n", nt_errstr(status)); + ret = false; + } else { + + q.in.trustdom_handle = &trustdom_handle[i]; + q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX; + status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); + if (!NT_STATUS_IS_OK(status)) { + printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status)); + ret = false; + } else if (!q.out.info) { + ret = false; + } else { + if (strcmp(q.out.info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) { + printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n", + q.out.info->info_ex.netbios_name.string, trustinfo.netbios_name.string); + ret = false; + } + if (q.out.info->info_ex.trust_type != trustinfo.trust_type) { + printf("QueryTrustedDomainInfo of %s returned incorrect trust type %d != %d\n", + trust_name, q.out.info->info_ex.trust_type, trustinfo.trust_type); + ret = false; + } + if (q.out.info->info_ex.trust_attributes != LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION) { + printf("QueryTrustedDomainInfo of %s returned incorrect trust attributes %d != %d\n", + trust_name, q.out.info->info_ex.trust_attributes, LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION); + ret = false; + } + if (q.out.info->info_ex.trust_direction != trustinfo.trust_direction) { + printf("QueryTrustedDomainInfo of %s returned incorrect trust direction %d != %d\n", + trust_name, q.out.info->info_ex.trust_direction, trustinfo.trust_direction); ret = false; } } @@ -2333,7 +2485,11 @@ bool torture_rpc_lsa(struct torture_context *tctx) if (!test_CreateTrustedDomain(p, tctx, handle)) { ret = false; } - + + if (!test_CreateTrustedDomainEx2(p, tctx, tctx, handle)) { + ret = false; + } + if (!test_EnumAccounts(p, tctx, handle)) { ret = false; } |