summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/kludge_acl.c15
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c37
-rw-r--r--source4/kdc/kdc.c2
-rw-r--r--source4/libcli/raw/smb_signing.c5
-rw-r--r--source4/libcli/util/nterr.c1
-rw-r--r--source4/libcli/util/ntstatus.h1
-rw-r--r--source4/librpc/idl/drsblobs.idl62
-rw-r--r--source4/librpc/idl/lsa.idl66
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c488
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c2
-rw-r--r--source4/setup/mmr_syncrepl.conf1
-rw-r--r--source4/smb_server/smb/sesssetup.c12
-rw-r--r--source4/smb_server/smb/signing.c8
-rw-r--r--source4/torture/rpc/lsa.c166
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;
}