diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2015-03-17 22:18:09 +0300 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2015-03-17 22:18:09 +0300 |
commit | 1095152992d77a7c3e3ad6a4cc1e5a4042ffafac (patch) | |
tree | ba7a6e80661eb5ec05f779da021c6a823706b5d9 /source4 | |
parent | 96ccbc68d81ae0713a5072cbb5815441eef5f3e3 (diff) | |
parent | 85232b25a2bbf24b2677778653e6017cf329ec46 (diff) | |
download | samba-1095152992d77a7c3e3ad6a4cc1e5a4042ffafac.tar.gz |
Merge branch 'master' of git://anonscm.debian.org/pkg-samba/samba
Conflicts:
debian/changelog
debian/patches/series
Diffstat (limited to 'source4')
27 files changed, 770 insertions, 152 deletions
diff --git a/source4/auth/session.c b/source4/auth/session.c index bb0b5bca63..8c853021a1 100644 --- a/source4/auth/session.c +++ b/source4/auth/session.c @@ -204,6 +204,11 @@ struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx, { struct auth_session_info *session_info; session_info = talloc_steal(mem_ctx, session_info_transport->session_info); + /* + * This is to allow us to check the type of this pointer using + * talloc_get_type() + */ + talloc_set_name(session_info, "struct auth_session_info"); #ifdef HAVE_GSS_IMPORT_CRED if (session_info_transport->exported_gssapi_credentials.length) { struct cli_credentials *creds; diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 38b765aa0d..604d4b9ddd 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -103,6 +103,27 @@ static void b9_add_helper(struct dlz_bind9_data *state, const char *helper_name, } /* + * Add a trailing '.' if it's missing + */ +static const char *b9_format_fqdn(TALLOC_CTX *mem_ctx, const char *str) +{ + size_t len; + const char *tmp; + + if (str == NULL || str[0] == '\0') { + return str; + } + + len = strlen(str); + if (str[len-1] != '.') { + tmp = talloc_asprintf(mem_ctx, "%s.", str); + } else { + tmp = str; + } + return tmp; +} + +/* format a record for bind9 */ static bool b9_format(struct dlz_bind9_data *state, @@ -112,6 +133,7 @@ static bool b9_format(struct dlz_bind9_data *state, { uint32_t i; char *tmp; + const char *fqdn; switch (rec->wType) { case DNS_TYPE_A: @@ -126,7 +148,7 @@ static bool b9_format(struct dlz_bind9_data *state, case DNS_TYPE_CNAME: *type = "cname"; - *data = rec->data.cname; + *data = b9_format_fqdn(mem_ctx, rec->data.cname); break; case DNS_TYPE_TXT: @@ -140,23 +162,30 @@ static bool b9_format(struct dlz_bind9_data *state, case DNS_TYPE_PTR: *type = "ptr"; - *data = rec->data.ptr; + *data = b9_format_fqdn(mem_ctx, rec->data.ptr); break; case DNS_TYPE_SRV: *type = "srv"; + fqdn = b9_format_fqdn(mem_ctx, rec->data.srv.nameTarget); + if (fqdn == NULL) { + return false; + } *data = talloc_asprintf(mem_ctx, "%u %u %u %s", rec->data.srv.wPriority, rec->data.srv.wWeight, rec->data.srv.wPort, - rec->data.srv.nameTarget); + fqdn); break; case DNS_TYPE_MX: *type = "mx"; + fqdn = b9_format_fqdn(mem_ctx, rec->data.mx.nameTarget); + if (fqdn == NULL) { + return false; + } *data = talloc_asprintf(mem_ctx, "%u %s", - rec->data.mx.wPriority, - rec->data.mx.nameTarget); + rec->data.mx.wPriority, fqdn); break; case DNS_TYPE_HINFO: @@ -168,7 +197,7 @@ static bool b9_format(struct dlz_bind9_data *state, case DNS_TYPE_NS: *type = "ns"; - *data = rec->data.ns; + *data = b9_format_fqdn(mem_ctx, rec->data.ns); break; case DNS_TYPE_SOA: { @@ -179,8 +208,9 @@ static bool b9_format(struct dlz_bind9_data *state, * point at ourselves. This is how AD DNS servers * force clients to send updates to the right local DC */ - mname = talloc_asprintf(mem_ctx, "%s.%s", - lpcfg_netbios_name(state->lp), lpcfg_dnsdomain(state->lp)); + mname = talloc_asprintf(mem_ctx, "%s.%s.", + lpcfg_netbios_name(state->lp), + lpcfg_dnsdomain(state->lp)); if (mname == NULL) { return false; } @@ -189,11 +219,15 @@ static bool b9_format(struct dlz_bind9_data *state, return false; } + fqdn = b9_format_fqdn(mem_ctx, rec->data.soa.rname); + if (fqdn == NULL) { + return false; + } + state->soa_serial = rec->data.soa.serial; *data = talloc_asprintf(mem_ctx, "%s %s %u %u %u %u %u", - mname, - rec->data.soa.rname, + mname, fqdn, rec->data.soa.serial, rec->data.soa.refresh, rec->data.soa.retry, @@ -785,7 +819,13 @@ static isc_result_t b9_find_name_dn(struct dlz_bind9_data *state, const char *na /* see if we handle a given zone */ +#if DLZ_DLOPEN_VERSION < 3 _PUBLIC_ isc_result_t dlz_findzonedb(void *dbdata, const char *name) +#else +_PUBLIC_ isc_result_t dlz_findzonedb(void *dbdata, const char *name, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) +#endif { struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); return b9_find_zone_dn(state, name, NULL, NULL); @@ -846,7 +886,7 @@ static isc_result_t dlz_lookup_types(struct dlz_bind9_data *state, /* lookup one record */ -#ifdef BIND_VERSION_9_8 +#if DLZ_DLOPEN_VERSION == 1 _PUBLIC_ isc_result_t dlz_lookup(const char *zone, const char *name, void *dbdata, dns_sdlzlookup_t *lookup) #else @@ -867,7 +907,9 @@ _PUBLIC_ isc_result_t dlz_lookup(const char *zone, const char *name, _PUBLIC_ isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const char *client) { /* just say yes for all our zones for now */ - return dlz_findzonedb(dbdata, name); + struct dlz_bind9_data *state = talloc_get_type( + dbdata, struct dlz_bind9_data); + return b9_find_zone_dn(state, name, NULL, NULL); } /* @@ -942,6 +984,7 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, } else { name = talloc_asprintf(el_ctx, "%s.%s", rdn, zone); } + name = b9_format_fqdn(el_ctx, name); if (name == NULL) { talloc_free(tmp_ctx); return ISC_R_NOMEMORY; @@ -1073,7 +1116,12 @@ static bool b9_has_soa(struct dlz_bind9_data *state, struct ldb_dn *dn, const ch /* configure a writeable zone */ +#if DLZ_DLOPEN_VERSION < 3 _PUBLIC_ isc_result_t dlz_configure(dns_view_t *view, void *dbdata) +#else +_PUBLIC_ isc_result_t dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, + void *dbdata) +#endif { struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); TALLOC_CTX *tmp_ctx; @@ -1132,7 +1180,12 @@ _PUBLIC_ isc_result_t dlz_configure(dns_view_t *view, void *dbdata) if (!b9_has_soa(state, zone_dn, zone)) { continue; } + +#if DLZ_DLOPEN_VERSION < 3 result = state->writeable_zone(view, zone); +#else + result = state->writeable_zone(view, dlzdb, zone); +#endif if (result != ISC_R_SUCCESS) { state->log(ISC_LOG_ERROR, "samba_dlz: Failed to configure zone '%s'", zone); diff --git a/source4/dns_server/dlz_minimal.h b/source4/dns_server/dlz_minimal.h index 98fb34e974..11187f763c 100644 --- a/source4/dns_server/dlz_minimal.h +++ b/source4/dns_server/dlz_minimal.h @@ -16,36 +16,49 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* - This header provides a minimal set of defines and typedefs needed - for building an external DLZ module for bind9. When creating a new - external DLZ driver, please copy this header into your own source - tree. +/* This header is updated based on BIND 9.10.1 source. + * contrib/dlz/modules/include/dlz_minimal.h */ -typedef unsigned int isc_result_t; + +#ifndef DLZ_MINIMAL_H +#define DLZ_MINIMAL_H 1 + #ifdef BIND_VERSION_9_8 -typedef bool isc_boolean_t; +#define DLZ_DLOPEN_VERSION 1 +#elif BIND_VERSION_9_9 +#define DLZ_DLOPEN_VERSION 2 +#elif BIND_VERSION_9_10 +#define DLZ_DLOPEN_VERSION 3 +#define DLZ_DLOPEN_AGE 0 #else -typedef int isc_boolean_t; +#error Unsupported BIND version #endif -typedef uint32_t dns_ttl_t; -#ifdef BIND_VERSION_9_8 -#define DLZ_DLOPEN_VERSION 1 +typedef unsigned int isc_result_t; +#if DLZ_DLOPEN_VERSION == 1 +typedef bool isc_boolean_t; #else -#define DLZ_DLOPEN_VERSION 2 +typedef int isc_boolean_t; #endif +typedef uint32_t dns_ttl_t; -/* return this in flags to dlz_version() if thread safe */ +/* return these in flags from dlz_version() */ #define DNS_SDLZFLAG_THREADSAFE 0x00000001U +#define DNS_SDLZFLAG_RELATIVEOWNER 0x00000002U +#define DNS_SDLZFLAG_RELATIVERDATA 0x00000004U /* result codes */ #define ISC_R_SUCCESS 0 #define ISC_R_NOMEMORY 1 #define ISC_R_NOPERM 6 +#define ISC_R_NOSPACE 19 #define ISC_R_NOTFOUND 23 #define ISC_R_FAILURE 25 +#define ISC_R_NOTIMPLEMENTED 27 #define ISC_R_NOMORE 29 +#define ISC_R_INVALIDFILE 30 +#define ISC_R_UNEXPECTED 34 +#define ISC_R_FILENOTFOUND 38 /* boolean values */ #define ISC_TRUE 1 @@ -57,16 +70,51 @@ typedef uint32_t dns_ttl_t; #define ISC_LOG_WARNING (-3) #define ISC_LOG_ERROR (-4) #define ISC_LOG_CRITICAL (-5) +#define ISC_LOG_DEBUG(level) (level) -/* some opaque structures */ +/* opaque structures */ typedef void *dns_sdlzlookup_t; typedef void *dns_sdlzallnodes_t; typedef void *dns_view_t; -typedef void *dns_clientinfomethods_t; -typedef void *dns_clientinfo_t; +typedef void *dns_dlzdb_t; + +#if DLZ_DLOPEN_VERSION > 1 +/* + * Method and type definitions needed for retrieval of client info + * from the caller. + */ +typedef struct isc_sockaddr { + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_un sunix; + } type; + unsigned int length; + void * link; +} isc_sockaddr_t; + +#define DNS_CLIENTINFO_VERSION 1 +typedef struct dns_clientinfo { + uint16_t version; + void *data; +} dns_clientinfo_t; + +typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client, + isc_sockaddr_t **addrp); + +#define DNS_CLIENTINFOMETHODS_VERSION 1 +#define DNS_CLIENTINFOMETHODS_AGE 0 + +typedef struct dns_clientinfomethods { + uint16_t version; + uint16_t age; + dns_clientinfo_sourceip_t sourceip; +} dns_clientinfomethods_t; +#endif /* DLZ_DLOPEN_VERSION > 1 */ /* - * method definitions for callbacks provided by dlopen driver + * Method definitions for callbacks provided by the dlopen driver */ typedef void log_t(int level, const char *fmt, ...); @@ -82,103 +130,150 @@ typedef isc_result_t dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes, dns_ttl_t ttl, const char *data); +#if DLZ_DLOPEN_VERSION < 3 typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view, const char *zone_name); - +#else /* DLZ_DLOPEN_VERSION >= 3 */ +typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view, + dns_dlzdb_t *dlzdb, + const char *zone_name); +#endif /* DLZ_DLOPEN_VERSION */ /* - * prototypes for the functions you can include in your driver + * prototypes for the functions you can include in your module */ - /* * dlz_version() is required for all DLZ external drivers. It should - * return DLZ_DLOPEN_VERSION + * return DLZ_DLOPEN_VERSION. 'flags' is updated to indicate capabilities + * of the module. In particular, if the module is thread-safe then it + * sets 'flags' to include DNS_SDLZFLAG_THREADSAFE. Other capability + * flags may be added in the future. */ -int dlz_version(unsigned int *flags); +int +dlz_version(unsigned int *flags); /* * dlz_create() is required for all DLZ external drivers. */ -isc_result_t dlz_create(const char *dlzname, unsigned int argc, const char **argv, void **dbdata, ...); +isc_result_t +dlz_create(const char *dlzname, unsigned int argc, const char *argv[], + void **dbdata, ...); /* * dlz_destroy() is optional, and will be called when the driver is * unloaded if supplied */ -void dlz_destroy(void *dbdata); +void +dlz_destroy(void *dbdata); /* - dlz_findzonedb is required for all DLZ external drivers + * dlz_findzonedb is required for all DLZ external drivers */ -isc_result_t dlz_findzonedb(void *dbdata, const char *name); +#if DLZ_DLOPEN_VERSION < 3 +isc_result_t +dlz_findzonedb(void *dbdata, const char *name); +#else /* DLZ_DLOPEN_VERSION >= 3 */ +isc_result_t +dlz_findzonedb(void *dbdata, const char *name, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo); +#endif /* DLZ_DLOPEN_VERSION */ /* - dlz_lookup is required for all DLZ external drivers + * dlz_lookup is required for all DLZ external drivers */ -#ifdef BIND_VERSION_9_8 -isc_result_t dlz_lookup(const char *zone, const char *name, - void *dbdata, dns_sdlzlookup_t *lookup); -#else -isc_result_t dlz_lookup(const char *zone, const char *name, - void *dbdata, dns_sdlzlookup_t *lookup, - dns_clientinfomethods_t *methods, - dns_clientinfo_t *clientinfo); -#endif +#if DLZ_DLOPEN_VERSION == 1 +isc_result_t +dlz_lookup(const char *zone, const char *name, void *dbdata, + dns_sdlzlookup_t *lookup); +#else /* DLZ_DLOPEN_VERSION > 1 */ +isc_result_t +dlz_lookup(const char *zone, const char *name, void *dbdata, + dns_sdlzlookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo); +#endif /* DLZ_DLOPEN_VERSION */ /* - dlz_allowzonexfr() is optional, and should be supplied if you want - to support zone transfers + * dlz_authority() is optional if dlz_lookup() supplies + * authority information (i.e., SOA, NS) for the dns record */ -isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const char *client); - +isc_result_t +dlz_authority(const char *zone, void *dbdata, dns_sdlzlookup_t *lookup); /* - dlz_allnodes() is optional, but must be supplied if supply a - dlz_allowzonexfr() function + * dlz_allowzonexfr() is optional, and should be supplied if you want to + * support zone transfers */ -isc_result_t dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes); +isc_result_t +dlz_allowzonexfr(void *dbdata, const char *name, const char *client); /* - dlz_newversion() is optional. It should be supplied if you want to - support dynamic updates. + * dlz_allnodes() is optional, but must be supplied if supply a + * dlz_allowzonexfr() function */ -isc_result_t dlz_newversion(const char *zone, void *dbdata, void **versionp); +isc_result_t +dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes); /* - dlz_closeversion() is optional, but must be supplied if you supply - a dlz_newversion() function + * dlz_newversion() is optional. It should be supplied if you want to + * support dynamic updates. + */ +isc_result_t +dlz_newversion(const char *zone, void *dbdata, void **versionp); + +/* + * dlz_closeversion() is optional, but must be supplied if you supply a + * dlz_newversion() function */ -void dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, void **versionp); +void +dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, + void **versionp); /* - dlz_configure() is optional, but must be supplied if you want to - support dynamic updates + * dlz_configure() is optional, but must be supplied if you want to support + * dynamic updates */ -isc_result_t dlz_configure(dns_view_t *view, void *dbdata); +#if DLZ_DLOPEN_VERSION < 3 +isc_result_t +dlz_configure(dns_view_t *view, void *dbdata); +#else /* DLZ_DLOPEN_VERSION >= 3 */ +isc_result_t +dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata); +#endif /* DLZ_DLOPEN_VERSION */ /* - dlz_ssumatch() is optional, but must be supplied if you want to - support dynamic updates + * dlz_ssumatch() is optional, but must be supplied if you want to support + * dynamic updates */ -isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, - const char *type, const char *key, uint32_t keydatalen, uint8_t *keydata, - void *dbdata); +isc_boolean_t +dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, + uint8_t *keydata, void *dbdata); /* - dlz_addrdataset() is optional, but must be supplied if you want to - support dynamic updates + * dlz_addrdataset() is optional, but must be supplied if you want to + * support dynamic updates */ -isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, void *version); +isc_result_t +dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, + void *version); /* - dlz_subrdataset() is optional, but must be supplied if you want to - support dynamic updates + * dlz_subrdataset() is optional, but must be supplied if you want to + * support dynamic updates */ -isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, void *version); +isc_result_t +dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, + void *version); /* - dlz_delrdataset() is optional, but must be supplied if you want to - support dynamic updates + * dlz_delrdataset() is optional, but must be supplied if you want to + * support dynamic updates */ -isc_result_t dlz_delrdataset(const char *name, const char *type, void *dbdata, void *version); +isc_result_t +dlz_delrdataset(const char *name, const char *type, void *dbdata, + void *version); + +#endif /* DLZ_MINIMAL_H */ diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build index a92ab67a40..803ca62e6f 100644 --- a/source4/dns_server/wscript_build +++ b/source4/dns_server/wscript_build @@ -37,6 +37,16 @@ bld.SAMBA_LIBRARY('dlz_bind9_9', deps='samba-hostconfig samdb-common gensec popt dnsserver_common', enabled=bld.AD_DC_BUILD_IS_ENABLED()) +bld.SAMBA_LIBRARY('dlz_bind9_10', + source='dlz_bind9.c', + cflags='-DBIND_VERSION_9_10', + private_library=True, + link_name='modules/bind9/dlz_bind9_10.so', + realname='dlz_bind9_10.so', + install_path='${MODULESDIR}/bind9', + deps='samba-hostconfig samdb-common gensec popt dnsserver_common', + enabled=bld.AD_DC_BUILD_IS_ENABLED()) + bld.SAMBA_LIBRARY('dlz_bind9_for_torture', source='dlz_bind9.c', cflags='-DBIND_VERSION_9_8', diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 0807e899e6..50530f3a5d 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -1043,8 +1043,8 @@ int samdb_msg_set_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, /* * Handle ldb_request in transaction */ -static int dsdb_autotransaction_request(struct ldb_context *sam_ldb, - struct ldb_request *req) +int dsdb_autotransaction_request(struct ldb_context *sam_ldb, + struct ldb_request *req) { int ret; diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index ee02483acd..0a2b86eed6 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -1152,6 +1152,7 @@ void initdsdb(void) ADD_DSDB_FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION); ADD_DSDB_FLAG(UF_NO_AUTH_DATA_REQUIRED); ADD_DSDB_FLAG(UF_PARTIAL_SECRETS_ACCOUNT); + ADD_DSDB_FLAG(UF_USE_AES_KEYS); /* groupType flags */ ADD_DSDB_FLAG(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP); diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c index bd788ddf4a..10e79adefe 100644 --- a/source4/dsdb/repl/drepl_out_helpers.c +++ b/source4/dsdb/repl/drepl_out_helpers.c @@ -186,10 +186,35 @@ static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq) info28->repl_epoch = info48->repl_epoch; break; } - case 28: + case 28: { *info28 = state->bind_r.out.bind_info->info.info28; break; } + case 32: { + struct drsuapi_DsBindInfo32 *info32; + info32 = &state->bind_r.out.bind_info->info.info32; + + info28->supported_extensions = info32->supported_extensions; + info28->site_guid = info32->site_guid; + info28->pid = info32->pid; + info28->repl_epoch = info32->repl_epoch; + break; + } + case 52: { + struct drsuapi_DsBindInfo52 *info52; + info52 = &state->bind_r.out.bind_info->info.info52; + + info28->supported_extensions = info52->supported_extensions; + info28->site_guid = info52->site_guid; + info28->pid = info52->pid; + info28->repl_epoch = info52->repl_epoch; + break; + } + default: + DEBUG(1, ("Warning: invalid info length in bind info: %d\n", + state->bind_r.out.bind_info->length)); + break; + } } tevent_req_done(req); diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index b13dc9e5c5..111266f035 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -142,10 +142,8 @@ static int expand_dn_in_message(struct ldb_module *module, struct ldb_message *m return ret; } - - ret = ldb_request_add_control(req2, - LDB_CONTROL_EXTENDED_DN_OID, - edn_control->critical, edn); + ret = dsdb_request_add_controls(req2, DSDB_FLAG_AS_SYSTEM | + DSDB_SEARCH_SHOW_EXTENDED_DN); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ldb_error(ldb, ret, "Failed to add control"); diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 2f8c5728fe..2c8a0647cc 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -33,6 +33,7 @@ #include "includes.h" #include "libcli/ldap/ldap_ndr.h" #include "ldb_module.h" +#include "auth/auth.h" #include "dsdb/samdb/samdb.h" #include "dsdb/samdb/ldb_modules/util.h" #include "dsdb/samdb/ldb_modules/ridalloc.h" @@ -944,6 +945,10 @@ static int samldb_schema_info_update(struct samldb_ctx *ac) } static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid); +static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, + struct dom_sid *sid, + uint32_t user_account_control, + uint32_t user_account_control_old); /* * "Objectclass" trigger (MS-SAMR 3.1.1.8.1) @@ -1039,7 +1044,6 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) el = ldb_msg_find_element(ac->msg, "userAccountControl"); if (el != NULL) { uint32_t user_account_control, account_type; - /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */ user_account_control = ldb_msg_find_attr_as_uint(ac->msg, "userAccountControl", @@ -1155,6 +1159,12 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) return ret; } } + + ret = samldb_check_user_account_control_acl(ac, NULL, + user_account_control, 0); + if (ret != LDB_SUCCESS) { + return ret; + } } break; } @@ -1442,6 +1452,172 @@ static int samldb_prim_group_trigger(struct samldb_ctx *ac) return ret; } +/** + * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured + * + */ +static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, + struct dom_sid *sid, + uint32_t user_account_control, + uint32_t user_account_control_old) +{ + int i, ret = 0; + bool need_acl_check = false; + struct ldb_result *res; + const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; + struct security_token *user_token; + struct security_descriptor *domain_sd; + struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); + const struct uac_to_guid { + uint32_t uac; + const char *oid; + const char *guid; + enum sec_privilege privilege; + bool delete_is_privileged; + const char *error_string; + } map[] = { + { + .uac = UF_PASSWD_NOTREQD, + .guid = GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT, + .error_string = "Adding the UF_PASSWD_NOTREQD bit in userAccountControl requires the Update-Password-Not-Required-Bit right that was not given on the Domain object" + }, + { + .uac = UF_DONT_EXPIRE_PASSWD, + .guid = GUID_DRS_UNEXPIRE_PASSWORD, + .error_string = "Adding the UF_DONT_EXPIRE_PASSWD bit in userAccountControl requires the Unexpire-Password right that was not given on the Domain object" + }, + { + .uac = UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED, + .guid = GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD, + .error_string = "Adding the UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED bit in userAccountControl requires the Enable-Per-User-Reversibly-Encrypted-Password right that was not given on the Domain object" + }, + { + .uac = UF_SERVER_TRUST_ACCOUNT, + .guid = GUID_DRS_DS_INSTALL_REPLICA, + .error_string = "Adding the UF_SERVER_TRUST_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object" + }, + { + .uac = UF_PARTIAL_SECRETS_ACCOUNT, + .guid = GUID_DRS_DS_INSTALL_REPLICA, + .error_string = "Adding the UF_PARTIAL_SECRETS_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object" + }, + { + .uac = UF_INTERDOMAIN_TRUST_ACCOUNT, + .oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID, + .error_string = "Updating the UF_INTERDOMAIN_TRUST_ACCOUNT bit in userAccountControl is not permitted over LDAP. This bit is restricted to the LSA CreateTrustedDomain interface", + .delete_is_privileged = true + }, + { + .uac = UF_TRUSTED_FOR_DELEGATION, + .privilege = SEC_PRIV_ENABLE_DELEGATION, + .delete_is_privileged = true, + .error_string = "Updating the UF_TRUSTED_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege" + }, + { + .uac = UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, + .privilege = SEC_PRIV_ENABLE_DELEGATION, + .delete_is_privileged = true, + .error_string = "Updating the UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege" + } + + }; + + if (dsdb_module_am_system(ac->module)) { + return LDB_SUCCESS; + } + + for (i = 0; i < ARRAY_SIZE(map); i++) { + if (user_account_control & map[i].uac) { + need_acl_check = true; + break; + } + } + if (need_acl_check == false) { + return LDB_SUCCESS; + } + + user_token = acl_user_token(ac->module); + if (user_token == NULL) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + + ret = dsdb_module_search_dn(ac->module, ac, &res, + domain_dn, + sd_attrs, + DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + if (res->count != 1) { + return ldb_module_operr(ac->module); + } + + ret = dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module), + ac, res->msgs[0], &domain_sd); + + if (ret != LDB_SUCCESS) { + return ret; + } + + for (i = 0; i < ARRAY_SIZE(map); i++) { + uint32_t this_uac_new = user_account_control & map[i].uac; + uint32_t this_uac_old = user_account_control_old & map[i].uac; + if (this_uac_new != this_uac_old) { + if (this_uac_old != 0) { + if (map[i].delete_is_privileged == false) { + continue; + } + } + if (map[i].oid) { + struct ldb_control *control = ldb_request_get_control(ac->req, map[i].oid); + if (control == NULL) { + ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } else if (map[i].privilege != SEC_PRIV_INVALID) { + bool have_priv = security_token_has_privilege(user_token, + map[i].privilege); + if (have_priv == false) { + ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } else { + ret = acl_check_extended_right(ac, domain_sd, + user_token, + map[i].guid, + SEC_ADS_CONTROL_ACCESS, + sid); + } + if (ret != LDB_SUCCESS) { + break; + } + } + } + if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { + switch (ac->req->operation) { + case LDB_ADD: + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "Failed to add %s: %s", + ldb_dn_get_linearized(ac->msg->dn), + map[i].error_string); + break; + case LDB_MODIFY: + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "Failed to modify %s: %s", + ldb_dn_get_linearized(ac->msg->dn), + map[i].error_string); + break; + default: + return ldb_module_operr(ac->module); + } + if (map[i].guid) { + dsdb_acl_debug(domain_sd, acl_user_token(ac->module), + domain_dn, + true, + 10); + } + } + return ret; +} /** * This function is called on LDB modify operations. It performs some additions/ @@ -1453,10 +1629,11 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) uint32_t user_account_control, old_user_account_control, account_type; struct ldb_message_element *el; struct ldb_message *tmp_msg; + struct dom_sid *sid; int ret; struct ldb_result *res; const char * const attrs[] = { "userAccountControl", "objectClass", - "lockoutTime", NULL }; + "lockoutTime", "objectSid", NULL }; unsigned int i; bool is_computer = false, uac_generated = false; @@ -1646,6 +1823,17 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) el->values[0].length = strlen(tempstr); } + sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid"); + if (sid == NULL) { + return ldb_module_operr(ac->module); + } + + ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, + old_user_account_control); + if (ret != LDB_SUCCESS) { + return ret; + } + return LDB_SUCCESS; } diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 7f77d4e382..4f57343e05 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -135,6 +135,12 @@ struct dsdb_control_password_change { */ #define DSDB_CONTROL_SEC_DESC_PROPAGATION_OID "1.3.6.1.4.1.7165.4.3.21" +/* + * passed when creating a interdomain trust account through LSA + * to relax constraints in the samldb ldb module. + */ +#define DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID "1.3.6.1.4.1.7165.4.3.23" + #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1" struct dsdb_extended_replicated_object { struct ldb_message *msg; diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 3e4c7f871c..683879483f 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -1708,10 +1708,33 @@ static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s, drsuapi->remote_info28.repl_epoch = info48->repl_epoch; break; } - case 28: + case 28: { drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28; break; } + case 32: { + struct drsuapi_DsBindInfo32 *info32; + info32 = &drsuapi->bind_r.out.bind_info->info.info32; + drsuapi->remote_info28.supported_extensions = info32->supported_extensions; + drsuapi->remote_info28.site_guid = info32->site_guid; + drsuapi->remote_info28.pid = info32->pid; + drsuapi->remote_info28.repl_epoch = info32->repl_epoch; + break; + } + case 52: { + struct drsuapi_DsBindInfo52 *info52; + info52 = &drsuapi->bind_r.out.bind_info->info.info52; + drsuapi->remote_info28.supported_extensions = info52->supported_extensions; + drsuapi->remote_info28.site_guid = info52->site_guid; + drsuapi->remote_info28.pid = info52->pid; + drsuapi->remote_info28.repl_epoch = info52->repl_epoch; + break; + } + default: + DEBUG(1, ("Warning: invalid info length in bind info: %d\n", + drsuapi->bind_r.out.bind_info->length)); + break; + } } return WERR_OK; diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c index a46d1433bc..a830d3fb27 100644 --- a/source4/libnet/libnet_unbecome_dc.c +++ b/source4/libnet/libnet_unbecome_dc.c @@ -644,10 +644,33 @@ static void unbecomeDC_drsuapi_bind_recv(struct tevent_req *subreq) s->drsuapi.remote_info28.repl_epoch = info48->repl_epoch; break; } - case 28: + case 28: { s->drsuapi.remote_info28 = s->drsuapi.bind_r.out.bind_info->info.info28; break; } + case 32: { + struct drsuapi_DsBindInfo32 *info32; + info32 = &s->drsuapi.bind_r.out.bind_info->info.info32; + s->drsuapi.remote_info28.supported_extensions = info32->supported_extensions; + s->drsuapi.remote_info28.site_guid = info32->site_guid; + s->drsuapi.remote_info28.pid = info32->pid; + s->drsuapi.remote_info28.repl_epoch = info32->repl_epoch; + break; + } + case 52: { + struct drsuapi_DsBindInfo52 *info52; + info52 = &s->drsuapi.bind_r.out.bind_info->info.info52; + s->drsuapi.remote_info28.supported_extensions = info52->supported_extensions; + s->drsuapi.remote_info28.site_guid = info52->site_guid; + s->drsuapi.remote_info28.pid = info52->pid; + s->drsuapi.remote_info28.repl_epoch = info52->repl_epoch; + break; + } + default: + DEBUG(1, ("Warning: invalid info length in bind info: %d\n", + s->drsuapi.bind_r.out.bind_info->length)); + break; + } } unbecomeDC_drsuapi_remove_ds_server_send(s); diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index dee69fe238..ab027abf9e 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -196,8 +196,10 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate, r->ServerInfoW2K->fDsAvailable = serverinfo->fDsAvailable; r->ServerInfoW2K->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName); r->ServerInfoW2K->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer); - r->ServerInfoW2K->aipServerAddrs = ip4_array_copy(mem_ctx, serverinfo->aipServerAddrs); - r->ServerInfoW2K->aipListenAddrs = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs); + r->ServerInfoW2K->aipServerAddrs = dns_addr_array_to_ip4_array(mem_ctx, + serverinfo->aipServerAddrs); + r->ServerInfoW2K->aipListenAddrs = dns_addr_array_to_ip4_array(mem_ctx, + serverinfo->aipListenAddrs); r->ServerInfoW2K->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders); r->ServerInfoW2K->dwLogLevel = serverinfo->dwLogLevel; r->ServerInfoW2K->dwDebugLevel = serverinfo->dwDebugLevel; @@ -238,8 +240,10 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate, r->ServerInfoDotNet->fDsAvailable = serverinfo->fDsAvailable; r->ServerInfoDotNet->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName); r->ServerInfoDotNet->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer); - r->ServerInfoDotNet->aipServerAddrs = ip4_array_copy(mem_ctx, serverinfo->aipServerAddrs); - r->ServerInfoDotNet->aipListenAddrs = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs); + r->ServerInfoDotNet->aipServerAddrs = dns_addr_array_to_ip4_array(mem_ctx, + serverinfo->aipServerAddrs); + r->ServerInfoDotNet->aipListenAddrs = dns_addr_array_to_ip4_array(mem_ctx, + serverinfo->aipListenAddrs); r->ServerInfoDotNet->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders); r->ServerInfoDotNet->aipLogFilter = ip4_array_copy(mem_ctx, serverinfo->aipLogFilter); r->ServerInfoDotNet->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath); @@ -293,8 +297,8 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate, r->ServerInfo->fDsAvailable = serverinfo->fDsAvailable; r->ServerInfo->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName); r->ServerInfo->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer); - r->ServerInfo->aipServerAddrs = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipServerAddrs); - r->ServerInfo->aipListenAddrs = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipListenAddrs); + r->ServerInfo->aipServerAddrs = serverinfo->aipServerAddrs; + r->ServerInfo->aipListenAddrs = serverinfo->aipListenAddrs; r->ServerInfo->aipForwarders = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipForwarders); r->ServerInfo->aipLogFilter = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipLogFilter); r->ServerInfo->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath); @@ -694,9 +698,9 @@ static WERROR dnsserver_query_server(struct dnsserver_state *dsstate, is_addresses = 1; } else if (strcasecmp(operation, "ListenAddresses") == 0) { if (client_version == DNS_CLIENT_VERSION_LONGHORN) { - answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipListenAddrs); + answer_addrarray = serverinfo->aipListenAddrs; } else { - answer_iparray = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs); + answer_iparray = dns_addr_array_to_ip4_array(mem_ctx, serverinfo->aipListenAddrs); } is_addresses = 1; } else if (strcasecmp(operation, "BreakOnReceiveFrom") == 0) { diff --git a/source4/rpc_server/dnsserver/dnsdata.c b/source4/rpc_server/dnsserver/dnsdata.c index f752490101..63e35d9834 100644 --- a/source4/rpc_server/dnsserver/dnsdata.c +++ b/source4/rpc_server/dnsserver/dnsdata.c @@ -91,6 +91,62 @@ struct DNS_ADDR_ARRAY *ip4_array_to_dns_addr_array(TALLOC_CTX *mem_ctx, return ret; } +struct IP4_ARRAY *dns_addr_array_to_ip4_array(TALLOC_CTX *mem_ctx, + struct DNS_ADDR_ARRAY *ip) +{ + struct IP4_ARRAY *ret; + int i, count, curr; + + if (ip == NULL) { + return NULL; + } + /* We must only return IPv4 addresses. + The passed DNS_ADDR_ARRAY may contain: + - only ipv4 addresses + - only ipv6 addresses + - a mixture of both + - an empty array + */ + ret = talloc_zero(mem_ctx, struct IP4_ARRAY); + if (!ret) { + return ret; + } + if (ip->AddrCount == 0 || ip->Family == AF_INET6) { + ret->AddrCount = 0; + return ret; + } + /* Now only ipv4 addresses or a mixture are left */ + count = 0; + for (i = 0; i < ip->AddrCount; i++) { + if (ip->AddrArray[i].MaxSa[0] == 0x02) { + /* Is ipv4 */ + count++; + } + } + if (count == 0) { + /* should not happen */ + ret->AddrCount = 0; + return ret; + } + ret->AddrArray = talloc_zero_array(mem_ctx, uint32_t, count); + if (ret->AddrArray) { + curr = 0; + for (i = 0; i < ip->AddrCount; i++) { + if (ip->AddrArray[i].MaxSa[0] == 0x02) { + /* Is ipv4 */ + memcpy(&ret->AddrArray[curr], + &ip->AddrArray[i].MaxSa[4], + sizeof(uint32_t)); + curr++; + } + } + } else { + talloc_free(ret); + return NULL; + } + ret->AddrCount = curr; + return ret; +} struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx, struct DNS_ADDR_ARRAY *addr) diff --git a/source4/rpc_server/dnsserver/dnsserver.h b/source4/rpc_server/dnsserver/dnsserver.h index e3db0b2e1c..cfe6d4e81a 100644 --- a/source4/rpc_server/dnsserver/dnsserver.h +++ b/source4/rpc_server/dnsserver/dnsserver.h @@ -46,8 +46,8 @@ struct dnsserver_serverinfo { char * pszDomainDirectoryPartition; char * pszForestDirectoryPartition; - struct IP4_ARRAY * aipServerAddrs; - struct IP4_ARRAY * aipListenAddrs; + struct DNS_ADDR_ARRAY * aipServerAddrs; + struct DNS_ADDR_ARRAY * aipListenAddrs; struct IP4_ARRAY * aipForwarders; struct IP4_ARRAY * aipLogFilter; @@ -179,6 +179,8 @@ struct dns_tree { struct IP4_ARRAY *ip4_array_copy(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4); struct DNS_ADDR_ARRAY *ip4_array_to_dns_addr_array(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4); +struct IP4_ARRAY *dns_addr_array_to_ip4_array(TALLOC_CTX *mem_ctx, + struct DNS_ADDR_ARRAY *ip); struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx, struct DNS_ADDR_ARRAY *addr); int dns_split_name_components(TALLOC_CTX *mem_ctx, const char *name, char ***components); @@ -217,7 +219,6 @@ struct ldb_dn *dnsserver_name_to_dn(TALLOC_CTX *mem_ctx, struct dnsserver_zone * const char *name); uint32_t dnsserver_zone_to_request_filter(const char *zone); - /* Database functions from dnsdb.c */ struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ctx, diff --git a/source4/rpc_server/dnsserver/dnsutils.c b/source4/rpc_server/dnsserver/dnsutils.c index 9f956460f9..72b47f72b4 100644 --- a/source4/rpc_server/dnsserver/dnsutils.c +++ b/source4/rpc_server/dnsserver/dnsutils.c @@ -24,7 +24,78 @@ #include "rpc_server/common/common.h" #include "dsdb/samdb/samdb.h" #include "lib/socket/netif.h" +#include "lib/util/util_net.h" +static struct DNS_ADDR_ARRAY *fill_dns_addr_array(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx, + bool listen_only) +{ + struct interface *ifaces; + int num_interfaces, i; + struct DNS_ADDR_ARRAY *dns_addr_array; + const char *ipstr; + bool have_ipv4, have_ipv6; + uint16_t family; + + have_ipv4 = have_ipv6 = false; + + if (!listen_only) { + /* + Return all interfaces from kernel + Not implemented! + */ + return NULL; + } + + /* Only the used interfaces */ + load_interface_list(mem_ctx, lp_ctx, &ifaces); + num_interfaces = iface_list_count(ifaces); + + dns_addr_array = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY); + if (dns_addr_array == NULL) { + goto nomem; + } + dns_addr_array->MaxCount = num_interfaces; + dns_addr_array->AddrCount = num_interfaces; + if (num_interfaces == 0) { + goto nomem; + } + + dns_addr_array->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR, + num_interfaces); + if (!dns_addr_array->AddrArray) { + TALLOC_FREE(dns_addr_array); + goto nomem; + } + + for (i = 0; i < num_interfaces; i++) { + ipstr = iface_list_n_ip(ifaces, i); + if (is_ipaddress_v4(ipstr)) { + have_ipv4 = true; + dns_addr_array->AddrArray[i].MaxSa[0] = 0x02; + inet_pton(AF_INET, ipstr, + &dns_addr_array->AddrArray[i].MaxSa[4]); + } else { + have_ipv6 = true; + dns_addr_array->AddrArray[i].MaxSa[0] = 0x17; + inet_pton(AF_INET6, ipstr, + &dns_addr_array->AddrArray[i].MaxSa[8]); + } + } + + if (have_ipv4 && have_ipv6) { + family = 0; /* mixed: MS-DNSP */ + } else if (have_ipv4 && !have_ipv6) { + family = AF_INET; + } else { + family = AF_INET6; + } + dns_addr_array->Family = family; + +nomem: + talloc_free(ifaces); + return dns_addr_array; +} struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, @@ -33,8 +104,6 @@ struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx, struct dnsserver_serverinfo *serverinfo; struct dcerpc_server_info *dinfo; struct ldb_dn *domain_dn, *forest_dn; - struct interface *ifaces; - int num_interfaces, i; serverinfo = talloc_zero(mem_ctx, struct dnsserver_serverinfo); if (serverinfo == NULL) { @@ -80,31 +149,14 @@ struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx, serverinfo->pszForestDirectoryPartition = talloc_asprintf(mem_ctx, "DC=ForestDnsZones,%s", ldb_dn_get_linearized(forest_dn)); - - load_interface_list(mem_ctx, lp_ctx, &ifaces); - num_interfaces = iface_list_count(ifaces); - - serverinfo->aipServerAddrs = talloc_zero(mem_ctx, struct IP4_ARRAY); - - if (serverinfo->aipServerAddrs) { - serverinfo->aipServerAddrs->AddrCount = num_interfaces; - if (num_interfaces > 0) { - serverinfo->aipServerAddrs->AddrArray = talloc_zero_array(mem_ctx, - unsigned int, - num_interfaces); - if (serverinfo->aipServerAddrs->AddrArray) { - for (i=0; i<num_interfaces; i++) { - serverinfo->aipServerAddrs->AddrArray[i] = inet_addr(iface_list_n_ip(ifaces, i)); - } - } else { - serverinfo->aipServerAddrs->AddrCount = 0; - } - } - } - talloc_free(ifaces); - - /* Assume listen addresses are same as server addresses */ - serverinfo->aipListenAddrs = serverinfo->aipServerAddrs; + /* IP addresses on which the DNS server listens for DNS requests */ + serverinfo->aipListenAddrs = fill_dns_addr_array(mem_ctx, lp_ctx, true); + + /* All IP addresses available on the server + * Not implemented! + * Use same as listen addresses + */ + serverinfo->aipServerAddrs = serverinfo->aipListenAddrs; serverinfo->aipForwarders = NULL; diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 48864c8c04..a1eace1dcd 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -790,6 +790,7 @@ static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx, struct trustAuthInOutBlob *in, struct ldb_dn **user_dn) { + struct ldb_request *req; struct ldb_message *msg; struct ldb_dn *dn; uint32_t i; @@ -850,7 +851,19 @@ static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx, } /* create the trusted_domain user account */ - ret = ldb_add(sam_ldb, msg); + ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL, + ldb_op_default_callback, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + + ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID, + false, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + + ret = dsdb_autotransaction_request(sam_ldb, req); if (ret != LDB_SUCCESS) { DEBUG(0,("Failed to create user record %s: %s\n", ldb_dn_get_linearized(msg->dn), diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index e738d1d97d..9c7a41c988 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -382,7 +382,7 @@ for env in ["plugin_s4_dc", "dc", "s4member"]: nsstest4 = binpath("nsstest") for env in ["plugin_s4_dc", "dc", "s4member", "s3dc", "s3member", "member"]: if os.path.exists(nsstest4): - plantestsuite("samba4.nss.test using winbind(%s)" % env, env, [os.path.join(bbdir, "nsstest.sh"), nsstest4, os.path.join(samba4bindir, "default/nsswitch/libnss-winbind.so")]) + plantestsuite("samba4.nss.test using winbind(%s)" % env, env, [os.path.join(bbdir, "nsstest.sh"), nsstest4, os.path.join(samba4bindir, "shared/libnss_wrapper_winbind.so.2")]) else: skiptestsuite("samba4.nss.test using winbind(%s)" % env, "nsstest not available") diff --git a/source4/setup/named.conf.dlz b/source4/setup/named.conf.dlz index be20a57a63..bf47076305 100644 --- a/source4/setup/named.conf.dlz +++ b/source4/setup/named.conf.dlz @@ -10,10 +10,13 @@ # Uncomment only single database line, depending on your BIND version # dlz "AD DNS Zone" { - # For BIND 9.8.0 + # For BIND 9.8.x database "dlopen ${MODULESDIR}/bind9/dlz_bind9.so"; - # For BIND 9.9.0 + # For BIND 9.9.x # database "dlopen ${MODULESDIR}/bind9/dlz_bind9_9.so"; + + # For BIND 9.10.x + # database "dlopen ${MODULESDIR}/bind9/dlz_bind9_10.so"; }; diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 94aedb099d..22f0bc13d0 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -197,6 +197,7 @@ #Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1 #Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20 #Allocated: DSDB_CONTROL_SEC_DESC_PROPAGATION_OID 1.3.6.1.4.1.7165.4.3.21 +#Allocated: DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID 1.3.6.1.4.1.7165.4.3.23 # Extended 1.3.6.1.4.1.7165.4.4.x #Allocated: DSDB_EXTENDED_REPLICATED_OBJECTS_OID 1.3.6.1.4.1.7165.4.4.1 diff --git a/source4/torture/dns/dlz_bind9.c b/source4/torture/dns/dlz_bind9.c index fa6967dc76..1b4bca4a99 100644 --- a/source4/torture/dns/dlz_bind9.c +++ b/source4/torture/dns/dlz_bind9.c @@ -353,7 +353,7 @@ static bool test_dlz_bind9_lookup(struct torture_context *tctx) expected1->records[0].type = "soa"; expected1->records[0].ttl = 3600; expected1->records[0].data = talloc_asprintf(expected1->records, - "%s.%s hostmaster.%s 1 900 600 86400 3600", + "%s.%s. hostmaster.%s. 1 900 600 86400 3600", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx), lpcfg_dnsdomain(tctx->lp_ctx)); @@ -362,7 +362,7 @@ static bool test_dlz_bind9_lookup(struct torture_context *tctx) expected1->records[1].name = expected1->query_name; expected1->records[1].type = "ns"; expected1->records[1].ttl = 900; - expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s", + expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed"); @@ -471,40 +471,44 @@ static bool test_dlz_bind9_zonedump(struct torture_context *tctx) expected1->num_records); torture_assert(tctx, expected1->records != NULL, "talloc failed"); - expected1->records[0].name = lpcfg_dnsdomain(tctx->lp_ctx); + expected1->records[0].name = talloc_asprintf(expected1->records, + "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[0].type = "soa"; expected1->records[0].ttl = 3600; expected1->records[0].data = talloc_asprintf(expected1->records, - "%s.%s hostmaster.%s 1 900 600 86400 3600", + "%s.%s. hostmaster.%s. 1 900 600 86400 3600", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed"); - expected1->records[1].name = lpcfg_dnsdomain(tctx->lp_ctx); + expected1->records[1].name = talloc_asprintf(expected1->records, + "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[1].type = "ns"; expected1->records[1].ttl = 900; - expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s", + expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed"); - expected1->records[2].name = lpcfg_dnsdomain(tctx->lp_ctx); + expected1->records[2].name = talloc_asprintf(expected1->records, + "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[2].type = "aaaa"; expected1->records[2].ttl = 900; - expected1->records[3].name = lpcfg_dnsdomain(tctx->lp_ctx); + expected1->records[3].name = talloc_asprintf(expected1->records, + "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[3].type = "a"; expected1->records[3].ttl = 900; - expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s", + expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[4].name != NULL, "unknown host"); expected1->records[4].type = "aaaa"; expected1->records[4].ttl = 900; - expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s", + expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[5].name != NULL, "unknown host"); diff --git a/source4/torture/drs/rpc/dssync.c b/source4/torture/drs/rpc/dssync.c index f6cc0f1026..525c9f0acb 100644 --- a/source4/torture/drs/rpc/dssync.c +++ b/source4/torture/drs/rpc/dssync.c @@ -238,9 +238,28 @@ static bool _test_DsBind(struct torture_context *tctx, b->peer_bind_info28.repl_epoch = info48->repl_epoch; break; } - case 28: + case 28: { b->peer_bind_info28 = b->req.out.bind_info->info.info28; break; + } + case 32: { + struct drsuapi_DsBindInfo32 *info32; + info32 = &b->req.out.bind_info->info.info32; + b->peer_bind_info28.supported_extensions= info32->supported_extensions; + b->peer_bind_info28.site_guid = info32->site_guid; + b->peer_bind_info28.pid = info32->pid; + b->peer_bind_info28.repl_epoch = info32->repl_epoch; + break; + } + case 52: { + struct drsuapi_DsBindInfo52 *info52; + info52 = &b->req.out.bind_info->info.info52; + b->peer_bind_info28.supported_extensions= info52->supported_extensions; + b->peer_bind_info28.site_guid = info52->site_guid; + b->peer_bind_info28.pid = info52->pid; + b->peer_bind_info28.repl_epoch = info52->repl_epoch; + break; + } default: printf("DsBind - warning: unknown BindInfo length: %u\n", b->req.out.bind_info->length); diff --git a/source4/torture/drs/rpc/msds_intid.c b/source4/torture/drs/rpc/msds_intid.c index c866c2181b..a74f52b9f9 100644 --- a/source4/torture/drs/rpc/msds_intid.c +++ b/source4/torture/drs/rpc/msds_intid.c @@ -237,9 +237,28 @@ static bool _test_DsaBind(struct torture_context *tctx, bi->srv_info48.repl_epoch = info28->repl_epoch; break; } - case 48: + case 48: { bi->srv_info48 = r.out.bind_info->info.info48; break; + } + case 32: { + struct drsuapi_DsBindInfo32 *info32; + info32 = &r.out.bind_info->info.info32; + bi->srv_info48.supported_extensions = info32->supported_extensions; + bi->srv_info48.site_guid = info32->site_guid; + bi->srv_info48.pid = info32->pid; + bi->srv_info48.repl_epoch = info32->repl_epoch; + break; + } + case 52: { + struct drsuapi_DsBindInfo52 *info52; + info52 = &r.out.bind_info->info.info52; + bi->srv_info48.supported_extensions = info52->supported_extensions; + bi->srv_info48.site_guid = info52->site_guid; + bi->srv_info48.pid = info52->pid; + bi->srv_info48.repl_epoch = info52->repl_epoch; + break; + } default: torture_result(tctx, TORTURE_FAIL, "DsBind: unknown BindInfo length: %u", diff --git a/source4/torture/rpc/dsgetinfo.c b/source4/torture/rpc/dsgetinfo.c index a0360e8404..179b0101fd 100644 --- a/source4/torture/rpc/dsgetinfo.c +++ b/source4/torture/rpc/dsgetinfo.c @@ -200,9 +200,28 @@ static bool _test_DsBind(struct torture_context *tctx, b->peer_bind_info28.repl_epoch = info48->repl_epoch; break; } - case 28: + case 28: { b->peer_bind_info28 = b->req.out.bind_info->info.info28; break; + } + case 32: { + struct drsuapi_DsBindInfo32 *info32; + info32 = &b->req.out.bind_info->info.info32; + b->peer_bind_info28.supported_extensions= info32->supported_extensions; + b->peer_bind_info28.site_guid = info32->site_guid; + b->peer_bind_info28.pid = info32->pid; + b->peer_bind_info28.repl_epoch = info32->repl_epoch; + break; + } + case 52: { + struct drsuapi_DsBindInfo52 *info52; + info52 = &b->req.out.bind_info->info.info52; + b->peer_bind_info28.supported_extensions= info52->supported_extensions; + b->peer_bind_info28.site_guid = info52->site_guid; + b->peer_bind_info28.pid = info52->pid; + b->peer_bind_info28.repl_epoch = info52->repl_epoch; + break; + } default: printf("DsBind - warning: unknown BindInfo length: %u\n", b->req.out.bind_info->length); diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 432e9d5350..6b9666b4e8 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -2623,7 +2623,7 @@ static bool rap_get_servername(struct torture_context *tctx, static bool find_printers(struct torture_context *tctx, struct dcerpc_pipe *p, const char ***printers, - int *num_printers) + size_t *num_printers) { struct srvsvc_NetShareEnum r; struct srvsvc_NetShareInfoCtr info_ctr; @@ -2760,7 +2760,7 @@ static bool torture_samba3_rpc_spoolss(struct torture_context *torture) struct dcerpc_binding_handle *b; struct policy_handle server_handle, printer_handle; const char **printers; - int num_printers; + size_t num_printers; struct spoolss_UserLevel1 userlevel1; char *servername; diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index cdfa2b8a8a..e7e98a5a27 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -6938,7 +6938,7 @@ static bool test_GroupList(struct dcerpc_binding_handle *b, uint32_t returned_size; union samr_DispInfo info; - int num_names = 0; + size_t num_names = 0; const char **names = NULL; bool builtin_domain = dom_sid_compare(domain_sid, diff --git a/source4/torture/rpc/wkssvc.c b/source4/torture/rpc/wkssvc.c index 5bf64afa26..09272004ef 100644 --- a/source4/torture/rpc/wkssvc.c +++ b/source4/torture/rpc/wkssvc.c @@ -530,7 +530,7 @@ static bool test_NetrEnumerateComputerNames_level(struct torture_context *tctx, struct dcerpc_pipe *p, uint16_t level, const char ***names, - int *num_names) + size_t *num_names) { NTSTATUS status; struct wkssvc_NetrEnumerateComputerNames r; @@ -666,7 +666,7 @@ static bool test_NetrAddAlternateComputerName(struct torture_context *tctx, NTSTATUS status; struct wkssvc_NetrAddAlternateComputerName r; const char **names = NULL; - int num_names = 0; + size_t num_names = 0; int i; struct dcerpc_binding_handle *b = p->binding_handle; @@ -708,7 +708,7 @@ static bool test_NetrRemoveAlternateComputerName(struct torture_context *tctx, NTSTATUS status; struct wkssvc_NetrRemoveAlternateComputerName r; const char **names = NULL; - int num_names = 0; + size_t num_names = 0; int i; struct dcerpc_binding_handle *b = p->binding_handle; @@ -781,7 +781,7 @@ static bool test_NetrSetPrimaryComputername(struct torture_context *tctx, */ const char **names_o = NULL, **names = NULL; - int num_names_o = 0, num_names = 0; + size_t num_names_o = 0, num_names = 0; torture_comment(tctx, "Testing NetrSetPrimaryComputername\n"); @@ -887,7 +887,7 @@ static bool test_NetrRenameMachineInDomain2(struct torture_context *tctx, struct dcerpc_pipe *p) { const char **names_o = NULL, **names = NULL; - int num_names_o = 0, num_names = 0; + size_t num_names_o = 0, num_names = 0; torture_comment(tctx, "Testing NetrRenameMachineInDomain2\n"); |