mirror of
https://github.com/samba-team/samba.git
synced 2025-01-10 01:18:15 +03:00
idmap_ad: Add "deny ous" and "allow ous" options
With these options, certain OUs can be denied or a list of OUs can be explicitly permitted for idmapping. Use case: Administration of OUs in AD has been delegated to people not 100% trusted by the unix server team, this can prevent arbitrary unix IDs to be assigned by these delegated admins. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
This commit is contained in:
parent
c9c709e39d
commit
3fdf8d15c0
@ -99,6 +99,37 @@
|
||||
<para>Default: no</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>deny ous</term>
|
||||
<listitem><para>This parameter is a list of OUs from
|
||||
which objects will not be mapped via the ad idmap
|
||||
module. If <parameter>deny ous</parameter> is set but
|
||||
<parameter>allow ous</parameter> is not set, every
|
||||
object outside the OUs listed in <parameter>deny
|
||||
ous</parameter> is allowed.
|
||||
</para>
|
||||
<para>Default: none</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>allow ous</term>
|
||||
<listitem><para>This parameter is a list of OUs from
|
||||
which objects will be mapped via the ad idmap
|
||||
module. If <parameter>allow ous</parameter> is set but
|
||||
<parameter>deny ous</parameter> is not set, every
|
||||
object outside the OUs <parameter>allow
|
||||
ous</parameter> is denied.
|
||||
</para>
|
||||
<para>
|
||||
If both <parameter>allow ous</parameter> and
|
||||
<parameter>deny ous</parameter> are set,
|
||||
<parameter>deny ous</parameter> is evaluated first,
|
||||
then <parameter>allow ous</parameter> is looked at. If
|
||||
an AD object matches neither, it is denied.
|
||||
</para>
|
||||
<para>Default: none</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "source3/libads/sitename_cache.h"
|
||||
#include "source3/libads/kerberos_proto.h"
|
||||
#include "source3/librpc/gen_ndr/ads.h"
|
||||
#include "source3/lib/global_contexts.h"
|
||||
#include <ldb.h>
|
||||
|
||||
struct idmap_ad_schema_names;
|
||||
|
||||
@ -45,6 +47,10 @@ struct idmap_ad_context {
|
||||
|
||||
bool unix_primary_group;
|
||||
bool unix_nss_info;
|
||||
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_dn **deny_ous;
|
||||
struct ldb_dn **allow_ous;
|
||||
};
|
||||
|
||||
static NTSTATUS idmap_ad_get_context(struct idmap_domain *dom,
|
||||
@ -434,6 +440,42 @@ static int idmap_ad_context_destructor(struct idmap_ad_context *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ldb_dn **str_list_to_dns(TALLOC_CTX *mem_ctx,
|
||||
const char *dbgmsg,
|
||||
struct ldb_context *ldb,
|
||||
const char **strlist)
|
||||
{
|
||||
size_t i, num_dns = str_list_length(strlist);
|
||||
char *dbgstr = NULL;
|
||||
struct ldb_dn **dns = NULL;
|
||||
|
||||
dns = talloc_array(mem_ctx, struct ldb_dn *, num_dns);
|
||||
if (dns == NULL) {
|
||||
TALLOC_FREE(dbgstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbgstr = talloc_strdup(talloc_tos(), "");
|
||||
|
||||
for (i = 0; i < num_dns; i++) {
|
||||
dns[i] = ldb_dn_new(dns, ldb, strlist[i]);
|
||||
if (dns[i] == NULL) {
|
||||
DBG_WARNING("ldb_dn_new(%s) failed\n", strlist[i]);
|
||||
TALLOC_FREE(dns);
|
||||
return NULL;
|
||||
}
|
||||
talloc_asprintf_addbuf(
|
||||
&dbgstr,
|
||||
"%s ",
|
||||
ldb_dn_get_extended_linearized(dbgstr, dns[i], 1));
|
||||
}
|
||||
|
||||
DBG_DEBUG("%s %s\n", dbgmsg, dbgstr);
|
||||
TALLOC_FREE(dbgstr);
|
||||
|
||||
return dns;
|
||||
}
|
||||
|
||||
static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx,
|
||||
struct idmap_domain *dom,
|
||||
const char *domname,
|
||||
@ -441,6 +483,8 @@ static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
struct idmap_ad_context *ctx;
|
||||
const char *schema_mode;
|
||||
const char **allow = NULL;
|
||||
const char **deny = NULL;
|
||||
NTSTATUS status;
|
||||
TLDAPRC rc;
|
||||
|
||||
@ -483,10 +527,120 @@ static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx,
|
||||
return NT_STATUS_LDAP(TLDAP_RC_V(rc));
|
||||
}
|
||||
|
||||
deny = idmap_config_string_list(domname, "deny ous", NULL);
|
||||
allow = idmap_config_string_list(domname, "allow ous", NULL);
|
||||
|
||||
if ((deny != NULL) || (allow != NULL)) {
|
||||
int ret = ldb_global_init();
|
||||
if (ret == -1) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
DBG_WARNING("ldb_global_init() failed: %s\n",
|
||||
strerror(errno));
|
||||
TALLOC_FREE(ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
ctx->ldb = ldb_init(ctx, global_event_context());
|
||||
if (ctx->ldb == NULL) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
DBG_WARNING("ldb_init() failed: %s\n", strerror(errno));
|
||||
TALLOC_FREE(ctx);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (deny != NULL) {
|
||||
ctx->deny_ous = str_list_to_dns(ctx, "Denying", ctx->ldb, deny);
|
||||
if (ctx->deny_ous == NULL) {
|
||||
DBG_DEBUG("str_list_to_dns failed\n");
|
||||
TALLOC_FREE(ctx);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (allow != NULL) {
|
||||
ctx->allow_ous =
|
||||
str_list_to_dns(ctx, "Allowing", ctx->ldb, allow);
|
||||
if (ctx->allow_ous == NULL) {
|
||||
DBG_DEBUG("str_list_to_dns failed\n");
|
||||
TALLOC_FREE(ctx);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
*pctx = ctx;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static bool check_dn(struct ldb_dn **dns, struct ldb_dn *dn)
|
||||
{
|
||||
size_t i, num_dns = talloc_array_length(dns);
|
||||
|
||||
for (i = 0; i < num_dns; i++) {
|
||||
struct ldb_dn *base = dns[i];
|
||||
int ret = ldb_dn_compare_base(base, dn);
|
||||
if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool idmap_ad_dn_filter(struct idmap_domain *dom, const char *dnstr)
|
||||
{
|
||||
struct idmap_ad_context *ctx = NULL;
|
||||
struct ldb_dn *dn = NULL;
|
||||
NTSTATUS status;
|
||||
bool result = false;
|
||||
|
||||
status = idmap_ad_get_context(dom, &ctx);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_DEBUG("idmap_ad_get_context failed: %s\n",
|
||||
nt_errstr(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ctx->allow_ous == NULL) && (ctx->deny_ous == NULL)) {
|
||||
/*
|
||||
* Nothing to check
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
dn = ldb_dn_new(talloc_tos(), ctx->ldb, dnstr);
|
||||
if (dn == NULL) {
|
||||
DBG_DEBUG("ldb_dn_new(%s) failed\n", dnstr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->deny_ous != NULL) {
|
||||
bool denied = check_dn(ctx->deny_ous, dn);
|
||||
if (denied) {
|
||||
DBG_WARNING("Denied %s\n", dnstr);
|
||||
TALLOC_FREE(dn);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->allow_ous == NULL) {
|
||||
/*
|
||||
* Only a few denied OUs around, allow by
|
||||
* default
|
||||
*/
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->allow_ous != NULL) {
|
||||
bool allowed = check_dn(ctx->allow_ous, dn);
|
||||
if (allowed) {
|
||||
return true;
|
||||
}
|
||||
DBG_WARNING("Did not allow %s\n", dnstr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static NTSTATUS idmap_ad_query_user(struct idmap_domain *domain,
|
||||
struct wbint_userinfo *info)
|
||||
{
|
||||
@ -538,13 +692,23 @@ static NTSTATUS idmap_ad_query_user(struct idmap_domain *domain,
|
||||
|
||||
for (i=0; i<num_msgs; i++) {
|
||||
struct tldap_message *msg = msgs[i];
|
||||
char *dn = NULL;
|
||||
bool ok;
|
||||
|
||||
if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
|
||||
continue;
|
||||
}
|
||||
ok = tldap_entry_dn(msg, &dn);
|
||||
if (!ok) {
|
||||
continue;
|
||||
}
|
||||
ok = idmap_ad_dn_filter(domain, dn);
|
||||
if (!ok) {
|
||||
DBG_DEBUG("%s filtered out\n", dn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->unix_primary_group) {
|
||||
bool ok;
|
||||
uint32_t gid;
|
||||
|
||||
ok = tldap_pull_uint32(msg, ctx->schema->gid, &gid);
|
||||
@ -783,6 +947,12 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom,
|
||||
continue;
|
||||
}
|
||||
|
||||
ok = idmap_ad_dn_filter(dom, dn);
|
||||
if (!ok) {
|
||||
DBG_DEBUG("%s filtered out\n", dn);
|
||||
continue;
|
||||
}
|
||||
|
||||
ok = tldap_pull_uint32(msg, "sAMAccountType", &atype);
|
||||
if (!ok) {
|
||||
DBG_DEBUG("No atype in object %s\n", dn);
|
||||
@ -941,6 +1111,12 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom,
|
||||
continue;
|
||||
}
|
||||
|
||||
ok = idmap_ad_dn_filter(dom, dn);
|
||||
if (!ok) {
|
||||
DBG_DEBUG("%s filtered out\n", dn);
|
||||
continue;
|
||||
}
|
||||
|
||||
ok = tldap_pull_binsid(msg, "objectSid", &sid);
|
||||
if (!ok) {
|
||||
DBG_DEBUG("No objectSid in object %s\n", dn);
|
||||
|
Loading…
Reference in New Issue
Block a user