summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/idmap/idmapd/adutils.c25
-rw-r--r--usr/src/cmd/idmap/idmapd/dbutils.c318
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_config.c465
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_config.h35
-rw-r--r--usr/src/cmd/idmap/idmapd/idmapd.h6
-rw-r--r--usr/src/cmd/idmap/idmapd/init.c142
-rw-r--r--usr/src/cmd/idmap/idmapd/server.c22
-rw-r--r--usr/src/lib/libadutils/common/adutils.c98
-rw-r--r--usr/src/lib/libadutils/common/adutils_impl.h19
-rw-r--r--usr/src/lib/libadutils/common/libadutils.h9
-rw-r--r--usr/src/lib/libadutils/common/mapfile-vers3
-rw-r--r--usr/src/lib/libidmap/common/addisc.c1506
-rw-r--r--usr/src/lib/libidmap/common/addisc.h137
-rw-r--r--usr/src/lib/libidmap/common/idmap_api.c27
-rw-r--r--usr/src/lib/libidmap/common/mapfile-vers4
-rw-r--r--usr/src/lib/libidmap/common/namemaps.c4
-rw-r--r--usr/src/lib/nsswitch/ad/common/ad_common.c3
-rw-r--r--usr/src/uts/common/sys/idmap.h4
18 files changed, 2143 insertions, 684 deletions
diff --git a/usr/src/cmd/idmap/idmapd/adutils.c b/usr/src/cmd/idmap/idmapd/adutils.c
index f19706822e..a8fefb2f01 100644
--- a/usr/src/cmd/idmap/idmapd/adutils.c
+++ b/usr/src/cmd/idmap/idmapd/adutils.c
@@ -99,8 +99,8 @@ typedef struct idmap_q {
/* Batch context structure; typedef is in header file */
struct idmap_query_state {
adutils_query_state_t *qs;
- int qcount; /* how many queries */
- uint32_t qlastsent;
+ int qsize; /* Queue size */
+ uint32_t qcount; /* Number of queued requests */
const char *ad_unixuser_attr;
const char *ad_unixgroup_attr;
idmap_q_t queries[1]; /* array of query results */
@@ -192,8 +192,7 @@ idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries,
*state = NULL;
- if (ad == NULL)
- return (IDMAP_ERR_INTERNAL);
+ assert(ad != NULL);
new_state = calloc(1, sizeof (idmap_query_state_t) +
(nqueries - 1) * sizeof (idmap_q_t));
@@ -207,7 +206,7 @@ idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries,
return (map_adrc2idmaprc(rc));
}
- new_state->qcount = nqueries;
+ new_state->qsize = nqueries;
*state = new_state;
return (IDMAP_SUCCESS);
}
@@ -626,9 +625,11 @@ idmap_batch_add1(idmap_query_state_t *state, const char *filter,
NULL
};
- qid = atomic_inc_32_nv(&state->qlastsent) - 1;
+ qid = atomic_inc_32_nv(&state->qcount) - 1;
q = &(state->queries[qid]);
+ assert(qid < state->qsize);
+
/*
* Remember the expected canonname, domainname and unix type
* so we can check the results * against it
@@ -745,8 +746,7 @@ idmap_name2sid_batch_add1(idmap_query_state_t *state,
*strchr(ecanonname, '@') = '\0';
} else {
/* 'name' not qualified and dname not given */
- dname = adutils_lookup_batch_getdefdomain(
- state->qs);
+ dname = adutils_lookup_batch_getdefdomain(state->qs);
assert(dname != NULL);
if (*dname == '\0') {
free(ecanonname);
@@ -765,6 +765,12 @@ idmap_name2sid_batch_add1(idmap_query_state_t *state,
}
}
+ if (!adutils_lookup_check_domain(state->qs, dname)) {
+ free(ecanonname);
+ free(edomain);
+ return (IDMAP_ERR_DOMAIN_NOTFOUND);
+ }
+
s_name = sanitize_for_ldap_filter(name);
if (s_name == NULL) {
free(ecanonname);
@@ -814,6 +820,9 @@ idmap_sid2name_batch_add1(idmap_query_state_t *state,
* computer.
*/
+ if (!adutils_lookup_check_sid_prefix(state->qs, sid))
+ return (IDMAP_ERR_DOMAIN_NOTFOUND);
+
ret = adutils_txtsid2hexbinsid(sid, rid, &cbinsid[0], sizeof (cbinsid));
if (ret != 0)
return (IDMAP_ERR_SID);
diff --git a/usr/src/cmd/idmap/idmapd/dbutils.c b/usr/src/cmd/idmap/idmapd/dbutils.c
index 771eaf8250..4e3db282eb 100644
--- a/usr/src/cmd/idmap/idmapd/dbutils.c
+++ b/usr/src/cmd/idmap/idmapd/dbutils.c
@@ -1801,15 +1801,15 @@ out:
return (retcode);
}
-/*
- * Batch AD lookups
- */
-idmap_retcode
-ad_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
- idmap_ids_res *result)
+
+
+static int
+ad_lookup_batch_int(lookup_state_t *state, idmap_mapping_batch *batch,
+ idmap_ids_res *result, int index, int *num_processed)
{
idmap_retcode retcode;
- int i, add, type, is_wuser, is_user;
+ int i, num_queued, type, is_wuser, is_user;
+ int next_request;
int retries = 0, eunixtype;
char **unixname;
idmap_mapping *req;
@@ -1818,6 +1818,8 @@ ad_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
idmap_how *how;
char **dn, **attr, **value;
+ *num_processed = 0;
+
/*
* Since req->id2.idtype is unused, we will use it here
* to retrieve the value of sid_type. But it needs to be
@@ -1829,42 +1831,33 @@ ad_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
* be an option if req->id2.idtype cannot be re-used in
* future.
*/
-
- if (state->ad_nqueries == 0)
- return (IDMAP_SUCCESS);
-
- for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
- req = &batch->idmap_mapping_batch_val[i];
- res = &result->ids.ids_val[i];
-
- /* Skip if not marked for AD lookup or already in error. */
- if (!(req->direction & _IDMAP_F_LOOKUP_AD) ||
- res->retcode != IDMAP_SUCCESS)
- continue;
-
- /* Init status */
- res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR;
- }
-
retry:
- RDLOCK_CONFIG();
- retcode = idmap_lookup_batch_start(_idmapdstate.ad, state->ad_nqueries,
- &qs);
- UNLOCK_CONFIG();
+ retcode = idmap_lookup_batch_start(_idmapdstate.ads[index],
+ state->ad_nqueries, &qs);
if (retcode != IDMAP_SUCCESS) {
if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR &&
retries++ < ADUTILS_DEF_NUM_RETRIES)
goto retry;
degrade_svc(1, "failed to create batch for AD lookup");
- goto out;
+ goto out;
}
+ num_queued = 0;
restore_svc();
- idmap_lookup_batch_set_unixattr(qs, state->ad_unixuser_attr,
- state->ad_unixgroup_attr);
+ if (index == 0) {
+ /*
+ * Directory based name mapping is only performed within the
+ * joined forest (index == 0). We don't trust other "trusted"
+ * forests to provide DS-based name mapping information because
+ * AD's definition of "cross-forest trust" does not encompass
+ * this sort of behavior.
+ */
+ idmap_lookup_batch_set_unixattr(qs,
+ state->ad_unixuser_attr, state->ad_unixgroup_attr);
+ }
- for (i = 0, add = 0; i < batch->idmap_mapping_batch_len; i++) {
+ for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
req = &batch->idmap_mapping_batch_val[i];
res = &result->ids.ids_val[i];
how = &res->info.how;
@@ -1872,8 +1865,9 @@ retry:
retcode = IDMAP_SUCCESS;
req->id2.idtype = IDMAP_NONE;
- /* Skip if not marked for AD lookup */
- if (!(req->direction & _IDMAP_F_LOOKUP_AD))
+ /* Skip if not marked for this AD lookup */
+ if (!(req->direction & _IDMAP_F_LOOKUP_AD) ||
+ (req->direction & _IDMAP_F_LOOKUP_OTHER_AD))
continue;
if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR)
@@ -1899,7 +1893,7 @@ retry:
unixname = &req->id2name;
}
}
- add = 1;
+
if (unixname != NULL) {
/*
* Get how info for DS-based name
@@ -1925,6 +1919,8 @@ retry:
&req->id1domain : NULL,
(int *)&req->id2.idtype, unixname,
&res->retcode);
+ if (retcode == IDMAP_SUCCESS)
+ num_queued++;
} else {
/* Lookup AD by winname */
assert(req->id1name != NULL);
@@ -1937,6 +1933,8 @@ retry:
&req->id1.idmap_id_u.sid.rid,
(int *)&req->id2.idtype, unixname,
&res->retcode);
+ if (retcode == IDMAP_SUCCESS)
+ num_queued++;
}
} else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) {
@@ -1945,7 +1943,7 @@ retry:
if (res->id.idmap_id_u.sid.prefix != NULL &&
req->id2name != NULL) {
- /* Already have SID and winname -- done */
+ /* Already have SID and winname. done */
res->retcode = IDMAP_SUCCESS;
continue;
}
@@ -1958,7 +1956,7 @@ retry:
* we are not retrieving unixname from
* AD.
*/
- add = 1;
+
retcode = idmap_sid2name_batch_add1(
qs, res->id.idmap_id_u.sid.prefix,
&res->id.idmap_id_u.sid.rid,
@@ -1967,6 +1965,8 @@ retry:
&req->id2name,
&req->id2domain, (int *)&req->id2.idtype,
NULL, &res->retcode);
+ if (retcode == IDMAP_SUCCESS)
+ num_queued++;
} else if (req->id2name != NULL) {
/*
* winname but no SID -- lookup AD by
@@ -1975,7 +1975,6 @@ retry:
* we are not retrieving unixname from
* AD.
*/
- add = 1;
retcode = idmap_name2sid_batch_add1(
qs, req->id2name, req->id2domain,
_IDMAP_T_UNDEF,
@@ -1984,10 +1983,12 @@ retry:
&res->id.idmap_id_u.sid.rid,
(int *)&req->id2.idtype, NULL,
&res->retcode);
+ if (retcode == IDMAP_SUCCESS)
+ num_queued++;
} else if (req->id1name != NULL) {
/*
- * No SID and no winname but we've unixname --
- * lookup AD by unixname to get SID.
+ * No SID and no winname but we've unixname.
+ * Lookup AD by unixname to get SID.
*/
is_user = (IS_REQUEST_UID(*req)) ? 1 : 0;
if (res->id.idtype == IDMAP_USID)
@@ -1996,7 +1997,7 @@ retry:
is_wuser = 0;
else
is_wuser = is_user;
- add = 1;
+
idmap_info_free(&res->info);
res->info.src = IDMAP_MAP_SRC_NEW;
how->map_type = IDMAP_MAP_TYPE_DS_AD;
@@ -2009,17 +2010,25 @@ retry:
&res->id.idmap_id_u.sid.rid,
&req->id2name, &req->id2domain,
(int *)&req->id2.idtype, &res->retcode);
+ if (retcode == IDMAP_SUCCESS)
+ num_queued++;
}
}
- if (retcode != IDMAP_SUCCESS) {
+
+ if (retcode == IDMAP_ERR_DOMAIN_NOTFOUND) {
+ req->direction |= _IDMAP_F_LOOKUP_OTHER_AD;
+ retcode = IDMAP_SUCCESS;
+ } else if (retcode != IDMAP_SUCCESS) {
idmap_lookup_release_batch(&qs);
+ num_queued = 0;
+ next_request = i + 1;
break;
}
- }
+ } /* End of for loop */
if (retcode == IDMAP_SUCCESS) {
/* add keeps track if we added an entry to the batch */
- if (add)
+ if (num_queued > 0)
retcode = idmap_lookup_batch_end(&qs);
else
idmap_lookup_release_batch(&qs);
@@ -2031,6 +2040,16 @@ retry:
else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR)
degrade_svc(1, "some AD lookups timed out repeatedly");
+ if (retcode != IDMAP_SUCCESS) {
+ /* Mark any unproccessed requests for an other AD */
+ for (i = next_request; i < batch->idmap_mapping_batch_len;
+ i++) {
+ req = &batch->idmap_mapping_batch_val[i];
+ req->direction |= _IDMAP_F_LOOKUP_OTHER_AD;
+
+ }
+ }
+
if (retcode != IDMAP_SUCCESS)
idmapdlog(LOG_NOTICE, "Failed to batch AD lookup requests");
@@ -2041,8 +2060,8 @@ out:
* 2. Reset req->id2.idtype to IDMAP_NONE
* 3. If batch_start or batch_add failed then set the status
* of each request marked for AD lookup to that error.
- * 4. Evaluate the type of the AD object (i.e. user or group) and
- * update the idtype in request.
+ * 4. Evaluate the type of the AD object (i.e. user or group)
+ * and update the idtype in request.
*/
for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
req = &batch->idmap_mapping_batch_val[i];
@@ -2050,24 +2069,26 @@ out:
req->id2.idtype = IDMAP_NONE;
res = &result->ids.ids_val[i];
how = &res->info.how;
- if (!(req->direction & _IDMAP_F_LOOKUP_AD))
+ if (!(req->direction & _IDMAP_F_LOOKUP_AD) ||
+ (req->direction & _IDMAP_F_LOOKUP_OTHER_AD))
continue;
+ /* Count number processed */
+ (*num_processed)++;
+
/* Reset AD lookup flag */
req->direction &= ~(_IDMAP_F_LOOKUP_AD);
/*
- * If batch_start or batch_add failed then set the status
- * of each request marked for AD lookup to that error.
+ * If batch_start or batch_add failed then set the
+ * status of each request marked for AD lookup to
+ * that error.
*/
if (retcode != IDMAP_SUCCESS) {
res->retcode = retcode;
continue;
}
- if (!add)
- continue;
-
if (res->retcode == IDMAP_ERR_NOTFOUND) {
/* Nothing found - remove the preset info */
idmap_info_free(&res->info);
@@ -2083,11 +2104,13 @@ out:
res->id.idtype = IDMAP_UID;
req->id1.idtype = IDMAP_USID;
break;
+
case _IDMAP_T_GROUP:
if (res->id.idtype == IDMAP_POSIXID)
res->id.idtype = IDMAP_GID;
req->id1.idtype = IDMAP_GSID;
break;
+
default:
res->retcode = IDMAP_ERR_SID;
break;
@@ -2107,11 +2130,12 @@ out:
req->id2name == NULL && /* no winname */
req->id1name != NULL) /* unixname */
/*
- * If AD lookup by unixname failed
- * with non fatal error then clear
- * the error (i.e set res->retcode
- * to success). This allows the next
- * pass to process other mapping
+ * If AD lookup by unixname
+ * failed with non fatal error
+ * then clear the error (ie set
+ * res->retcode to success).
+ * This allows the next pass to
+ * process other mapping
* mechanisms for this request.
*/
res->retcode = IDMAP_SUCCESS;
@@ -2123,10 +2147,12 @@ out:
if (res->id.idtype == IDMAP_SID)
res->id.idtype = IDMAP_USID;
break;
+
case _IDMAP_T_GROUP:
if (res->id.idtype == IDMAP_SID)
res->id.idtype = IDMAP_GSID;
break;
+
default:
res->retcode = IDMAP_ERR_SID;
break;
@@ -2134,6 +2160,92 @@ out:
}
}
+ return (retcode);
+}
+
+
+
+/*
+ * Batch AD lookups
+ */
+idmap_retcode
+ad_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
+ idmap_ids_res *result)
+{
+ idmap_retcode retcode;
+ int i, j;
+ idmap_mapping *req;
+ idmap_id_res *res;
+ int num_queries;
+ int num_processed;
+
+ if (state->ad_nqueries == 0)
+ return (IDMAP_SUCCESS);
+
+ for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
+ req = &batch->idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
+
+ /* Skip if not marked for AD lookup or already in error. */
+ if (!(req->direction & _IDMAP_F_LOOKUP_AD) ||
+ res->retcode != IDMAP_SUCCESS)
+ continue;
+
+ /* Init status */
+ res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR;
+ }
+
+ RDLOCK_CONFIG();
+ num_queries = state->ad_nqueries;
+ if (_idmapdstate.num_ads > 0) {
+ for (i = 0; i < _idmapdstate.num_ads && num_queries > 0; i++) {
+
+ retcode = ad_lookup_batch_int(state, batch, result, i,
+ &num_processed);
+ num_queries -= num_processed;
+
+ if (num_queries > 0) {
+ for (j = 0; j < batch->idmap_mapping_batch_len;
+ j++) {
+ req =
+ &batch->idmap_mapping_batch_val[j];
+ res = &result->ids.ids_val[j];
+ if (!(req->direction &
+ _IDMAP_F_LOOKUP_AD))
+ continue;
+ /*
+ * Reset the other AD lookup flag so
+ * that we can try the next AD
+ */
+ req->direction &=
+ ~(_IDMAP_F_LOOKUP_OTHER_AD);
+
+ if ((i + 1) >= _idmapdstate.num_ads) {
+ /*
+ * There are no more ADs to try
+ */
+ req->direction &=
+ ~(_IDMAP_F_LOOKUP_AD);
+ res->retcode =
+ IDMAP_ERR_DOMAIN_NOTFOUND;
+ }
+ }
+ }
+ }
+ } else {
+ /* Case of no ADs */
+ retcode = IDMAP_ERR_NO_ACTIVEDIRECTORY;
+ for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
+ req = &batch->idmap_mapping_batch_val[i];
+ res = &result->ids.ids_val[i];
+ if (!(req->direction & _IDMAP_F_LOOKUP_AD))
+ continue;
+ req->direction &= ~(_IDMAP_F_LOOKUP_AD);
+ res->retcode = IDMAP_ERR_NO_ACTIVEDIRECTORY;
+ }
+ }
+ UNLOCK_CONFIG();
+
/* AD lookups done. Reset state->ad_nqueries and return */
state->ad_nqueries = 0;
return (retcode);
@@ -2238,7 +2350,7 @@ sid2pid_first_pass(lookup_state_t *state, idmap_mapping *req,
goto out;
if (ALLOW_WK_OR_LOCAL_SIDS_ONLY(req)) {
- retcode = IDMAP_ERR_NONEGENERATED;
+ retcode = IDMAP_ERR_NONE_GENERATED;
goto out;
}
}
@@ -2249,7 +2361,7 @@ sid2pid_first_pass(lookup_state_t *state, idmap_mapping *req,
goto out;
if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) {
- retcode = IDMAP_ERR_NONEGENERATED;
+ retcode = IDMAP_ERR_NONE_GENERATED;
goto out;
}
@@ -3588,42 +3700,70 @@ ad_lookup_by_winname(lookup_state_t *state,
char **sidprefix, idmap_rid_t *rid, int *wintype,
char **unixname)
{
- int retries = 0;
+ int retries;
idmap_query_state_t *qs = NULL;
idmap_retcode rc, retcode;
+ int i;
+ int found_ad = 0;
-retry:
RDLOCK_CONFIG();
- retcode = idmap_lookup_batch_start(_idmapdstate.ad, 1, &qs);
- UNLOCK_CONFIG();
- if (retcode != IDMAP_SUCCESS) {
- if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR &&
- retries++ < ADUTILS_DEF_NUM_RETRIES)
- goto retry;
- degrade_svc(1, "failed to create request for AD lookup "
- "by winname");
- return (retcode);
- }
-
- restore_svc();
-
- if (state != NULL)
- idmap_lookup_batch_set_unixattr(qs, state->ad_unixuser_attr,
- state->ad_unixgroup_attr);
+ if (_idmapdstate.num_ads > 0) {
+ for (i = 0; i < _idmapdstate.num_ads && !found_ad; i++) {
+ retries = 0;
+retry:
+ retcode = idmap_lookup_batch_start(_idmapdstate.ads[i],
+ 1, &qs);
+ if (retcode != IDMAP_SUCCESS) {
+ if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR &&
+ retries++ < ADUTILS_DEF_NUM_RETRIES)
+ goto retry;
+ degrade_svc(1, "failed to create request for "
+ "AD lookup by winname");
+ return (retcode);
+ }
- retcode = idmap_name2sid_batch_add1(qs, name, domain, eunixtype,
- dn, attr, value, canonname, sidprefix, rid, wintype, unixname, &rc);
+ restore_svc();
- if (retcode != IDMAP_SUCCESS)
- idmap_lookup_release_batch(&qs);
- else
- retcode = idmap_lookup_batch_end(&qs);
+ if (state != NULL && i == 0) {
+ /*
+ * Directory based name mapping is only
+ * performed within the joined forest (i == 0).
+ * We don't trust other "trusted" forests to
+ * provide DS-based name mapping information
+ * because AD's definition of "cross-forest
+ * trust" does not encompass this sort of
+ * behavior.
+ */
+ idmap_lookup_batch_set_unixattr(qs,
+ state->ad_unixuser_attr,
+ state->ad_unixgroup_attr);
+ }
- if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR &&
- retries++ < ADUTILS_DEF_NUM_RETRIES)
- goto retry;
- else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR)
- degrade_svc(1, "some AD lookups timed out repeatedly");
+ retcode = idmap_name2sid_batch_add1(qs, name, domain,
+ eunixtype, dn, attr, value, canonname, sidprefix,
+ rid, wintype, unixname, &rc);
+ if (retcode == IDMAP_ERR_DOMAIN_NOTFOUND) {
+ idmap_lookup_release_batch(&qs);
+ continue;
+ }
+ found_ad = 1;
+ if (retcode != IDMAP_SUCCESS)
+ idmap_lookup_release_batch(&qs);
+ else
+ retcode = idmap_lookup_batch_end(&qs);
+
+ if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR &&
+ retries++ < ADUTILS_DEF_NUM_RETRIES)
+ goto retry;
+ else if (retcode == IDMAP_ERR_RETRIABLE_NET_ERR)
+ degrade_svc(1,
+ "some AD lookups timed out repeatedly");
+ }
+ } else {
+ /* No AD case */
+ retcode = IDMAP_ERR_NO_ACTIVEDIRECTORY;
+ }
+ UNLOCK_CONFIG();
if (retcode != IDMAP_SUCCESS) {
idmapdlog(LOG_NOTICE, "AD lookup by winname failed");
@@ -3989,7 +4129,7 @@ pid2sid_first_pass(lookup_state_t *state, idmap_mapping *req,
}
if (DO_NOT_ALLOC_NEW_ID_MAPPING(req)) {
- retcode = IDMAP_ERR_NONEGENERATED;
+ retcode = IDMAP_ERR_NONE_GENERATED;
goto out;
}
diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.c b/usr/src/cmd/idmap/idmapd/idmap_config.c
index 16d9c2b2ea..fb000d5f0d 100644
--- a/usr/src/cmd/idmap/idmapd/idmap_config.c
+++ b/usr/src/cmd/idmap/idmapd/idmap_config.c
@@ -23,7 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Config routines common to idmap(1M) and idmapd(1M)
@@ -41,6 +40,7 @@
#include <pthread.h>
#include <port.h>
#include <net/route.h>
+#include <sys/u8_textprep.h>
#include "addisc.h"
#define MACHINE_SID_LEN (9 + 3 * 11)
@@ -507,6 +507,12 @@ destruction:
return (rc);
}
+
+
+/*
+ * This function updates a boolean value.
+ * If nothing has changed it returns 0 else 1
+ */
static int
update_bool(bool_t *value, bool_t *new, char *name)
{
@@ -518,6 +524,11 @@ update_bool(bool_t *value, bool_t *new, char *name)
return (1);
}
+
+/*
+ * This function updates a string value.
+ * If nothing has changed it returns 0 else 1
+ */
static int
update_string(char **value, char **new, char *name)
{
@@ -538,6 +549,11 @@ update_string(char **value, char **new, char *name)
return (1);
}
+
+/*
+ * This function updates a directory service structure.
+ * If nothing has changed it returns 0 else 1
+ */
static int
update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
{
@@ -554,7 +570,7 @@ update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
return (0);
}
- if (*value)
+ if (*value != NULL)
free(*value);
*value = *new;
@@ -573,6 +589,221 @@ update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
return (1);
}
+/*
+ * This function updates a trusted domains structure.
+ * If nothing has changed it returns 0 else 1
+ */
+static int
+update_trusted_domains(ad_disc_trusteddomains_t **value,
+ ad_disc_trusteddomains_t **new, char *name)
+{
+ int i;
+
+ if (*value == *new)
+ /* Nothing to do */
+ return (0);
+
+ if (*value != NULL && *new != NULL &&
+ ad_disc_compare_trusteddomains(*value, *new) == 0) {
+ free(*new);
+ *new = NULL;
+ return (0);
+ }
+
+ if (*value != NULL)
+ free(*value);
+
+ *value = *new;
+ *new = NULL;
+
+ if (*value == NULL) {
+ /* We're unsetting this DS property */
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
+ return (1);
+ }
+
+ /* List all the new domains */
+ for (i = 0; (*value)[i].domain[0] != '\0'; i++)
+ idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
+ (*value)[i].domain,
+ (*value)[i].direction == 3 ? "bi-directional" : "inbound");
+ return (1);
+}
+
+
+/*
+ * This function updates a domains in a forest structure.
+ * If nothing has changed it returns 0 else 1
+ */
+static int
+update_domains_in_forest(ad_disc_domainsinforest_t **value,
+ ad_disc_domainsinforest_t **new, char *name)
+{
+ int i;
+
+ if (*value == *new)
+ /* Nothing to do */
+ return (0);
+
+ if (*value != NULL && *new != NULL &&
+ ad_disc_compare_domainsinforest(*value, *new) == 0) {
+ free(*new);
+ *new = NULL;
+ return (0);
+ }
+
+ if (*value != NULL)
+ free(*value);
+
+ *value = *new;
+ *new = NULL;
+
+ if (*value == NULL) {
+ /* We're unsetting this DS property */
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
+ return (1);
+ }
+
+ /* List all the new domains */
+ for (i = 0; (*value)[i].domain[0] != '\0'; i++)
+ idmapdlog(LOG_INFO, "change %s=%s", name,
+ (*value)[i].domain);
+ return (1);
+}
+
+
+static void
+free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
+{
+ int i;
+
+ for (i = 0; i < *num_values; i++) {
+ free((*value)[i].forest_name);
+ free((*value)[i].global_catalog);
+ free((*value)[i].domains_in_forest);
+ }
+ free(*value);
+ *value = NULL;
+ *num_values = 0;
+}
+
+
+static int
+compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
+ ad_disc_domainsinforest_t *df2)
+{
+ int i, j;
+ int num_df1 = 0;
+ int num_df2 = 0;
+ int match;
+ int err;
+
+ for (i = 0; df1[i].domain[0] != '\0'; i++)
+ if (df1[i].trusted)
+ num_df1++;
+
+ for (j = 0; df2[j].domain[0] != '\0'; j++)
+ if (df2[j].trusted)
+ num_df2++;
+
+ if (num_df1 != num_df2)
+ return (1);
+
+ for (i = 0; df1[i].domain[0] != '\0'; i++) {
+ if (df1[i].trusted) {
+ match = FALSE;
+ for (j = 0; df2[j].domain[0] != '\0'; j++) {
+ if (df2[j].trusted &&
+ u8_strcmp(df1[i].domain, df2[i].domain, 0,
+ U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err)
+ == 0 && err == 0 &&
+ strcmp(df1[i].sid, df2[i].sid) == 0) {
+ match = TRUE;
+ break;
+ }
+ }
+ if (!match)
+ return (1);
+ }
+ }
+ return (0);
+}
+
+
+
+/*
+ * This function updates trusted forest structure.
+ * If nothing has changed it returns 0 else 1
+ */
+static int
+update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
+ idmap_trustedforest_t **new, int *num_new, char *name)
+{
+ int i, j;
+ int match;
+
+ if (*value == *new)
+ /* Nothing to do */
+ return (0);
+
+ if (*value != NULL && *new != NULL) {
+ if (*num_value != *num_new)
+ goto not_equal;
+ for (i = 0; i < *num_value; i++) {
+ match = FALSE;
+ for (j = 0; j < *num_new; j++) {
+ if (strcmp((*value)[i].forest_name,
+ (*new)[j].forest_name) == 0 &&
+ ad_disc_compare_ds(
+ (*value)[i].global_catalog,
+ (*new)[i].global_catalog) == 0 &&
+ compare_trusteddomainsinforest(
+ (*value)[i].domains_in_forest,
+ (*new)[i].domains_in_forest) == 0) {
+ match = TRUE;
+ break;
+ }
+ }
+ if (!match)
+ goto not_equal;
+ }
+ free_trusted_forests(new, num_new);
+ return (0);
+ }
+not_equal:
+ if (*value != NULL)
+ free_trusted_forests(value, num_value);
+ *value = *new;
+ *num_value = *num_new;
+ *new = NULL;
+ *num_new = 0;
+
+ if (*value == NULL) {
+ /* We're unsetting this DS property */
+ idmapdlog(LOG_INFO, "change %s=<none>", name);
+ return (1);
+ }
+
+ /* List all the trusted forests */
+ for (i = 0; i < *num_value; i++) {
+ for (j = 0; (*value)[i].domains_in_forest[j].domain[0] != '\0';
+ j++) {
+ /* List trusted Domains in the forest. */
+ if ((*value)[i].domains_in_forest[j].trusted)
+ idmapdlog(LOG_INFO, "change %s=%s domain=%s",
+ name, (*value)[i].forest_name,
+ (*value)[i].domains_in_forest[j].domain);
+ }
+ /* List the hosts */
+ for (j = 0; (*value)[i].global_catalog[j].host[0] != '\0'; j++)
+ idmapdlog(LOG_INFO, "change %s=%s host=%s port=%d",
+ name, (*value)[i].forest_name,
+ (*value)[i].global_catalog[j].host,
+ (*value)[i].global_catalog[j].port);
+ }
+ return (1);
+}
+
#define MAX_CHECK_TIME (20 * 60)
@@ -863,9 +1094,11 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
&pgcfg->domain_name);
if (rc != 0)
errors++;
- else
+ else {
(void) ad_disc_set_DomainName(handles->ad_ctx,
pgcfg->domain_name);
+ pgcfg->domain_name_auto_disc = FALSE;
+ }
rc = get_val_astring(handles, "default_domain",
&pgcfg->default_domain);
@@ -932,16 +1165,20 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
&pgcfg->domain_controller);
if (rc != 0)
errors++;
- else
+ else {
(void) ad_disc_set_DomainController(handles->ad_ctx,
pgcfg->domain_controller);
+ pgcfg->domain_controller_auto_disc = FALSE;
+ }
rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
if (rc != 0)
errors++;
- else
+ else {
(void) ad_disc_set_ForestName(handles->ad_ctx,
pgcfg->forest_name);
+ pgcfg->forest_name_auto_disc = FALSE;
+ }
rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
if (rc != 0)
@@ -954,9 +1191,11 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
&pgcfg->global_catalog);
if (rc != 0)
errors++;
- else
+ else {
(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
pgcfg->global_catalog);
+ pgcfg->global_catalog_auto_disc = FALSE;
+ }
/*
* Read directory-based name mappings related SMF properties
@@ -1017,6 +1256,7 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
}
+
/*
* This is the half of idmap_cfg_load() that auto-discovers values of
* discoverable properties that weren't already set via SMF properties.
@@ -1029,28 +1269,173 @@ void
idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
{
ad_disc_t ad_ctx = handles->ad_ctx;
+ ad_disc_t trusted_ctx;
+ int i, j, k, l;
+ char *forestname;
+ int num_trusteddomains;
+ int new_forest;
+ int err;
+ char *trusteddomain;
+ idmap_ad_disc_ds_t *globalcatalog;
+ idmap_trustedforest_t *trustedforests;
+ ad_disc_domainsinforest_t *domainsinforest;
ad_disc_refresh(ad_ctx);
if (pgcfg->default_domain == NULL)
- pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx);
+ pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx,
+ NULL);
if (pgcfg->domain_name == NULL)
- pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx);
+ pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx,
+ &pgcfg->domain_name_auto_disc);
if (pgcfg->domain_controller == NULL)
pgcfg->domain_controller =
- ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE);
+ ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE,
+ &pgcfg->domain_controller_auto_disc);
if (pgcfg->forest_name == NULL)
- pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx);
+ pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
+ &pgcfg->forest_name_auto_disc);
if (pgcfg->site_name == NULL)
- pgcfg->site_name = ad_disc_get_SiteName(ad_ctx);
+ pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
+ &pgcfg->site_name_auto_disc);
if (pgcfg->global_catalog == NULL)
pgcfg->global_catalog =
- ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE);
+ ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE,
+ &pgcfg->global_catalog_auto_disc);
+
+ pgcfg->domains_in_forest =
+ ad_disc_get_DomainsInForest(ad_ctx, NULL);
+
+ pgcfg->trusted_domains =
+ ad_disc_get_TrustedDomains(ad_ctx, NULL);
+
+ if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
+ pgcfg->trusted_domains[0].domain[0] != '\0') {
+ /*
+ * We have trusted domains. We need to go through every
+ * one and find its forest. If it is a new forest we then need
+ * to find its Global Catalog and the domains in the forest
+ */
+ for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
+ continue;
+ num_trusteddomains = i;
+
+ trustedforests = calloc(num_trusteddomains,
+ sizeof (idmap_trustedforest_t));
+ j = 0;
+ for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
+ trusteddomain = pgcfg->trusted_domains[i].domain;
+ trusted_ctx = ad_disc_init();
+ ad_disc_set_DomainName(trusted_ctx,
+ trusteddomain);
+ forestname =
+ ad_disc_get_ForestName(trusted_ctx, NULL);
+ if (forestname == NULL) {
+ idmapdlog(LOG_DEBUG, "unable to discover "
+ "Forest Name for the trusted domain %s",
+ trusteddomain);
+ ad_disc_fini(trusted_ctx);
+ continue;
+ }
+
+ if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
+ /*
+ * Ignore the domain as it is part of
+ * the primary forest
+ */
+ free(forestname);
+ ad_disc_fini(trusted_ctx);
+ continue;
+ }
+
+ /* Is this a new forest? */
+ new_forest = TRUE;
+ for (k = 0; k < j; k++) {
+ if (strcasecmp(forestname,
+ trustedforests[k].forest_name) == 0) {
+ new_forest = FALSE;
+ domainsinforest =
+ trustedforests[k].domains_in_forest;
+ break;
+ }
+ }
+ if (!new_forest) {
+ /* Mark the domain as trusted */
+ for (l = 0;
+ domainsinforest[l].domain[0] != '\0'; l++) {
+ if (u8_strcmp(trusteddomain,
+ domainsinforest[l].domain, 0,
+ U8_STRCMP_CI_LOWER,
+ U8_UNICODE_LATEST, &err) == 0 &&
+ err == 0) {
+ domainsinforest[l].trusted =
+ TRUE;
+ break;
+ }
+ }
+ free(forestname);
+ ad_disc_fini(trusted_ctx);
+ continue;
+ }
+
+ /*
+ * Get the Global Catalog and the domains in
+ * this new forest.
+ */
+ globalcatalog =
+ ad_disc_get_GlobalCatalog(trusted_ctx,
+ AD_DISC_PREFER_SITE, NULL);
+ if (globalcatalog == NULL) {
+ idmapdlog(LOG_DEBUG,
+ "unable to discover Global "
+ "Catalog for the trusted domain %s",
+ trusteddomain);
+ free(forestname);
+ ad_disc_fini(trusted_ctx);
+ continue;
+ }
+ domainsinforest =
+ ad_disc_get_DomainsInForest(trusted_ctx,
+ NULL);
+ if (domainsinforest == NULL) {
+ idmapdlog(LOG_DEBUG,
+ "unable to discover Domains in the Forest "
+ "for the trusted domain %s",
+ trusteddomain);
+ free(globalcatalog);
+ free(forestname);
+ ad_disc_fini(trusted_ctx);
+ continue;
+ }
+
+ trustedforests[j].forest_name = forestname;
+ trustedforests[j].global_catalog = globalcatalog;
+ trustedforests[j].domains_in_forest = domainsinforest;
+ j++;
+ /* Mark the domain as trusted */
+ for (l = 0; domainsinforest[l].domain[0] != '\0';
+ l++) {
+ if (u8_strcmp(trusteddomain,
+ domainsinforest[l].domain, 0,
+ U8_STRCMP_CI_LOWER,
+ U8_UNICODE_LATEST, &err) == 0 &&
+ err == 0) {
+ domainsinforest[l].trusted = TRUE;
+ break;
+ }
+ }
+ ad_disc_fini(trusted_ctx);
+ }
+ if (j > 0) {
+ pgcfg->num_trusted_forests = j;
+ pgcfg->trusted_forests = trustedforests;
+ }
+ }
if (pgcfg->domain_name == NULL)
idmapdlog(LOG_DEBUG, "unable to discover Domain Name");
@@ -1062,8 +1447,14 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
idmapdlog(LOG_DEBUG, "unable to discover Site Name");
if (pgcfg->global_catalog == NULL)
idmapdlog(LOG_DEBUG, "unable to discover Global Catalog");
+ if (pgcfg->domains_in_forest == NULL)
+ idmapdlog(LOG_DEBUG,
+ "unable to discover Domains in the Forest");
+ if (pgcfg->trusted_domains == NULL)
+ idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains");
}
+
/*
* idmap_cfg_load() is called at startup, and periodically via the
* update thread when the auto-discovery TTLs expire, as well as part of
@@ -1093,6 +1484,7 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags)
int rc = 0;
int errors = 0;
int changed = 0;
+ int ad_reload_required = 0;
idmap_pg_config_t new_pgcfg, *live_pgcfg;
live_pgcfg = &cfg->pgcfg;
@@ -1141,30 +1533,55 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags)
changed += update_string(&live_pgcfg->domain_name,
&new_pgcfg.domain_name, "domain_name");
+ live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
changed += update_dirs(&live_pgcfg->domain_controller,
&new_pgcfg.domain_controller, "domain_controller");
+ live_pgcfg->domain_controller_auto_disc =
+ new_pgcfg.domain_controller_auto_disc;
changed += update_string(&live_pgcfg->forest_name,
&new_pgcfg.forest_name, "forest_name");
+ live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
changed += update_string(&live_pgcfg->site_name,
&new_pgcfg.site_name, "site_name");
+ live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
if (update_dirs(&live_pgcfg->global_catalog,
&new_pgcfg.global_catalog, "global_catalog")) {
changed++;
- /*
- * Right now we only update the ad_t used for AD lookups
- * when the GC list is updated. When we add mixed
- * ds-based mapping we'll also need to update the ad_t
- * used to talk to the domain, not just the one used to
- * talk to the GC.
- */
if (live_pgcfg->global_catalog != NULL &&
live_pgcfg->global_catalog[0].host[0] != '\0')
- reload_ad();
+ ad_reload_required = TRUE;
}
+ live_pgcfg->global_catalog_auto_disc =
+ new_pgcfg.global_catalog_auto_disc;
+
+ if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
+ &new_pgcfg.domains_in_forest, "domains_in_forest")) {
+ changed++;
+ ad_reload_required = TRUE;
+ }
+
+ if (update_trusted_domains(&live_pgcfg->trusted_domains,
+ &new_pgcfg.trusted_domains, "trusted_domains")) {
+ changed++;
+ if (live_pgcfg->trusted_domains != NULL &&
+ live_pgcfg->trusted_domains[0].domain[0] != '\0')
+ ad_reload_required = TRUE;
+ }
+
+ if (update_trusted_forest(&live_pgcfg->trusted_forests,
+ &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
+ &new_pgcfg.num_trusted_forests, "trusted_forest")) {
+ changed++;
+ if (live_pgcfg->trusted_forests != NULL)
+ ad_reload_required = TRUE;
+ }
+
+ if (ad_reload_required)
+ reload_ad();
idmap_cfg_unload(&new_pgcfg);
@@ -1292,6 +1709,14 @@ idmap_cfg_unload(idmap_pg_config_t *pgcfg)
free(pgcfg->global_catalog);
pgcfg->global_catalog = NULL;
}
+ if (pgcfg->trusted_domains) {
+ free(pgcfg->trusted_domains);
+ pgcfg->trusted_domains = NULL;
+ }
+ if (pgcfg->trusted_forests)
+ free_trusted_forests(&pgcfg->trusted_forests,
+ &pgcfg->num_trusted_forests);
+
if (pgcfg->ad_unixuser_attr) {
free(pgcfg->ad_unixuser_attr);
pgcfg->ad_unixuser_attr = NULL;
diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.h b/usr/src/cmd/idmap/idmapd/idmap_config.h
index b088184105..3ca051facd 100644
--- a/usr/src/cmd/idmap/idmapd/idmap_config.h
+++ b/usr/src/cmd/idmap/idmapd/idmap_config.h
@@ -26,7 +26,6 @@
#ifndef _IDMAP_CONFIG_H
#define _IDMAP_CONFIG_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include "idmap.h"
#include "addisc.h"
@@ -53,6 +52,15 @@ typedef struct idmap_cfg_handles {
/*
* This structure stores AD and AD-related configuration
*/
+typedef struct idmap_trustedforest {
+ char *forest_name;
+ idmap_ad_disc_ds_t
+ *global_catalog; /* global catalog hosts */
+ ad_disc_domainsinforest_t
+ *domains_in_forest;
+} idmap_trustedforest_t;
+
+
typedef struct idmap_pg_config {
uint64_t list_size_limit;
/*
@@ -65,16 +73,29 @@ typedef struct idmap_pg_config {
* track its procedence separately. The dflt_dom_set_in_smf
* field does just that.
*/
- bool_t dflt_dom_set_in_smf;
+ char *machine_sid; /* machine sid */
char *default_domain; /* default domain name */
+ bool_t dflt_dom_set_in_smf;
char *domain_name; /* AD domain name */
- char *machine_sid; /* machine sid */
- idmap_ad_disc_ds_t *domain_controller;
- /* domain controller hosts */
+ int domain_name_auto_disc;
+ idmap_ad_disc_ds_t
+ *domain_controller; /* domain controller hosts */
+ int domain_controller_auto_disc;
char *forest_name; /* forest name */
+ int forest_name_auto_disc;
char *site_name; /* site name */
- idmap_ad_disc_ds_t *global_catalog;
- /* global catalog hosts */
+ int site_name_auto_disc;
+ idmap_ad_disc_ds_t
+ *global_catalog; /* global catalog hosts */
+ int global_catalog_auto_disc;
+ ad_disc_domainsinforest_t
+ *domains_in_forest;
+ ad_disc_trusteddomains_t
+ *trusted_domains; /* Trusted Domains */
+ int num_trusted_forests;
+ idmap_trustedforest_t
+ *trusted_forests; /* Array of trusted forests */
+
/*
* Following properties are associated with directory-based
* name-mappings.
diff --git a/usr/src/cmd/idmap/idmapd/idmapd.h b/usr/src/cmd/idmap/idmapd/idmapd.h
index b4cab338c4..035212a15b 100644
--- a/usr/src/cmd/idmap/idmapd/idmapd.h
+++ b/usr/src/cmd/idmap/idmapd/idmapd.h
@@ -79,7 +79,8 @@ typedef struct idmapd_state {
gid_t limit_gid;
int new_eph_db; /* was the ephem ID db [re-]created? */
bool_t eph_map_unres_sids;
- adutils_ad_t *ad;
+ int num_ads;
+ adutils_ad_t **ads;
} idmapd_state_t;
extern idmapd_state_t _idmapdstate;
@@ -178,6 +179,9 @@ typedef struct msg_table {
#define _IDMAP_F_EXP_EPH_UID 0x00000010
/* Same as above. Used for sid2gid request */
#define _IDMAP_F_EXP_EPH_GID 0x00000020
+/* This request is not valid for the current forest */
+#define _IDMAP_F_LOOKUP_OTHER_AD 0x00000040
+
/*
* Check if we are done. If so, subsequent passes can be skipped
diff --git a/usr/src/cmd/idmap/idmapd/init.c b/usr/src/cmd/idmap/idmapd/init.c
index f1eb9d9aaf..0a6d1ef046 100644
--- a/usr/src/cmd/idmap/idmapd/init.c
+++ b/usr/src/cmd/idmap/idmapd/init.c
@@ -103,11 +103,15 @@ load_config()
void
reload_ad()
{
- int i;
- adutils_ad_t *old;
- adutils_ad_t *new;
-
+ int i, j;
+ adutils_ad_t **new_ads = NULL;
+ adutils_ad_t **old_ads;
+ int new_num_ads;
+ int old_num_ads;
idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
+ idmap_trustedforest_t *trustfor = pgcfg->trusted_forests;
+ int num_trustfor = pgcfg->num_trusted_forests;
+ ad_disc_domainsinforest_t *domain_in_forest;
if (pgcfg->global_catalog == NULL ||
pgcfg->global_catalog[0].host[0] == '\0') {
@@ -122,36 +126,109 @@ reload_ad()
return;
}
- old = _idmapdstate.ad;
+ old_ads = _idmapdstate.ads;
+ old_num_ads = _idmapdstate.num_ads;
+
+ new_num_ads = 1 + num_trustfor;
+ new_ads = calloc(new_num_ads, sizeof (adutils_ad_t *));
+ if (new_ads == NULL) {
+ degrade_svc(0, "could not allocate AD context array "
+ "(out of memory)");
+ return;
+ }
- if (adutils_ad_alloc(&new, pgcfg->default_domain,
+ if (adutils_ad_alloc(&new_ads[0], pgcfg->default_domain,
ADUTILS_AD_GLOBAL_CATALOG) != ADUTILS_SUCCESS) {
- degrade_svc(0, "could not initialize AD context");
+ free(new_ads);
+ degrade_svc(0, "could not initialize AD context "
+ "(out of memory)");
return;
}
for (i = 0; pgcfg->global_catalog[i].host[0] != '\0'; i++) {
- if (idmap_add_ds(new,
+ if (idmap_add_ds(new_ads[0],
pgcfg->global_catalog[i].host,
pgcfg->global_catalog[i].port) != 0) {
- adutils_ad_free(&new);
- degrade_svc(0, "could not initialize AD GC context");
+ adutils_ad_free(&new_ads[0]);
+ free(new_ads);
+ degrade_svc(0, "could not set AD hosts "
+ "(out of memory)");
return;
}
}
- _idmapdstate.ad = new;
+ if (pgcfg->domains_in_forest != NULL) {
+ for (i = 0; pgcfg->domains_in_forest[i].domain[0] != '\0';
+ i++) {
+ if (adutils_add_domain(new_ads[0],
+ pgcfg->domains_in_forest[i].domain,
+ pgcfg->domains_in_forest[i].sid) != 0) {
+ adutils_ad_free(&new_ads[0]);
+ free(new_ads);
+ degrade_svc(0, "could not set AD domains "
+ "(out of memory)");
+ return;
+ }
+ }
+ }
+
+ for (i = 0; i < num_trustfor; i++) {
+ if (adutils_ad_alloc(&new_ads[i + 1], NULL,
+ ADUTILS_AD_GLOBAL_CATALOG) != ADUTILS_SUCCESS) {
+ degrade_svc(0, "could not initialize trusted AD "
+ "context (out of memory)");
+ new_num_ads = i + 1;
+ goto out;
+ }
+ for (j = 0; trustfor[i].global_catalog[j].host[0] != '\0';
+ j++) {
+ if (idmap_add_ds(new_ads[i + 1],
+ trustfor[i].global_catalog[j].host,
+ trustfor[i].global_catalog[j].port) != 0) {
+ adutils_ad_free(&new_ads[i + 1]);
+ degrade_svc(0, "could not set trusted "
+ "AD hosts (out of memory)");
+ new_num_ads = i + 1;
+ goto out;
+ }
+ }
+ for (j = 0; trustfor[i].domains_in_forest[j].domain[0] != '\0';
+ j++) {
+ domain_in_forest = &trustfor[i].domains_in_forest[j];
+ /* Only add domains which are marked */
+ if (domain_in_forest->trusted) {
+ if (adutils_add_domain(new_ads[i + 1],
+ domain_in_forest->domain,
+ domain_in_forest->sid) != 0) {
+ adutils_ad_free(&new_ads[i + 1]);
+ degrade_svc(0, "could not set trusted "
+ "AD domains (out of memory)");
+ new_num_ads = i + 1;
+ goto out;
+ }
+ }
+ }
+ }
+
+out:
+ _idmapdstate.ads = new_ads;
+ _idmapdstate.num_ads = new_num_ads;
+
- if (old != NULL)
- adutils_ad_free(&old);
+ if (old_ads != NULL) {
+ for (i = 0; i < old_num_ads; i++)
+ adutils_ad_free(&old_ads[i]);
+ free(old_ads);
+ }
}
void
print_idmapdstate()
{
- int i;
+ int i, j;
idmap_pg_config_t *pgcfg;
+ idmap_trustedforest_t *tf;
RDLOCK_CONFIG();
@@ -188,6 +265,43 @@ print_idmapdstate()
pgcfg->global_catalog[i].host,
pgcfg->global_catalog[i].port);
}
+ if (pgcfg->domains_in_forest == NULL ||
+ pgcfg->domains_in_forest[0].domain[0] == '\0') {
+ idmapdlog(LOG_DEBUG, "No domains in forest %s known",
+ CHECK_NULL(pgcfg->forest_name));
+ } else {
+ for (i = 0; pgcfg->domains_in_forest[i].domain[0] != '\0'; i++)
+ idmapdlog(LOG_DEBUG, "domains in forest %s = %s",
+ CHECK_NULL(pgcfg->forest_name),
+ pgcfg->domains_in_forest[i].domain);
+ }
+ if (pgcfg->trusted_domains == NULL ||
+ pgcfg->trusted_domains[0].domain[0] == '\0') {
+ idmapdlog(LOG_DEBUG, "No trusted domains known");
+ } else {
+ for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
+ idmapdlog(LOG_DEBUG, "trusted domain = %s",
+ pgcfg->trusted_domains[i].domain);
+ }
+
+ for (i = 0; i < pgcfg->num_trusted_forests; i++) {
+ tf = &pgcfg->trusted_forests[i];
+ for (j = 0; tf->global_catalog[j].host[0] != '\0'; j++)
+ idmapdlog(LOG_DEBUG,
+ "trusted forest %s global_catalog=%s port=%d",
+ tf->forest_name,
+ tf->global_catalog[j].host,
+ tf->global_catalog[j].port);
+ for (j = 0; tf->domains_in_forest[j].domain[0] != '\0'; j++) {
+ if (tf->domains_in_forest[j].trusted) {
+ idmapdlog(LOG_DEBUG,
+ "trusted forest %s domain=%s",
+ tf->forest_name,
+ tf->domains_in_forest[j].domain);
+ }
+ }
+ }
+
idmapdlog(LOG_DEBUG, "ds_name_mapping_enabled=%s",
(pgcfg->ds_name_mapping_enabled == TRUE) ? "true" : "false");
idmapdlog(LOG_DEBUG, "ad_unixuser_attr=%s",
diff --git a/usr/src/cmd/idmap/idmapd/server.c b/usr/src/cmd/idmap/idmapd/server.c
index 46c7fa4232..22fb63f122 100644
--- a/usr/src/cmd/idmap/idmapd/server.c
+++ b/usr/src/cmd/idmap/idmapd/server.c
@@ -23,7 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Service routines
@@ -996,7 +995,6 @@ idmap_get_prop_1_svc(idmap_prop_type request,
idmap_prop_res *result, struct svc_req *rqstp)
{
idmap_pg_config_t *pgcfg;
- ad_disc_t ad_ctx;
/* Init */
(void) memset(result, 0, sizeof (*result));
@@ -1007,7 +1005,7 @@ idmap_get_prop_1_svc(idmap_prop_type request,
/* Just shortcuts: */
pgcfg = &_idmapdstate.cfg->pgcfg;
- ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
+
switch (request) {
case PROP_LIST_SIZE_LIMIT:
@@ -1023,7 +1021,7 @@ idmap_get_prop_1_svc(idmap_prop_type request,
STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
pgcfg->domain_name);
result->auto_discovered =
- ad_ctx->domain_name.type == AD_TYPE_AUTO ? TRUE : FALSE;
+ pgcfg->domain_name_auto_disc;
break;
case PROP_MACHINE_SID:
result->auto_discovered = FALSE;
@@ -1036,32 +1034,24 @@ idmap_get_prop_1_svc(idmap_prop_type request,
pgcfg->domain_controller,
sizeof (idmap_ad_disc_ds_t));
}
- result->auto_discovered =
- ad_ctx->domain_controller.type == AD_TYPE_AUTO
- ? TRUE : FALSE;
+ result->auto_discovered = pgcfg->domain_controller_auto_disc;
break;
case PROP_FOREST_NAME:
STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
pgcfg->forest_name);
- result->auto_discovered =
- ad_ctx->forest_name.type == AD_TYPE_AUTO
- ? TRUE : FALSE;
+ result->auto_discovered = pgcfg->forest_name_auto_disc;
break;
case PROP_SITE_NAME:
STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
pgcfg->site_name);
- result->auto_discovered =
- ad_ctx->site_name.type == AD_TYPE_AUTO
- ? TRUE : FALSE;
+ result->auto_discovered = pgcfg->site_name_auto_disc;
break;
case PROP_GLOBAL_CATALOG:
if (pgcfg->global_catalog != NULL) {
(void) memcpy(&result->value.idmap_prop_val_u.dsval,
pgcfg->global_catalog, sizeof (idmap_ad_disc_ds_t));
}
- result->auto_discovered =
- ad_ctx->global_catalog.type == AD_TYPE_AUTO
- ? TRUE : FALSE;
+ result->auto_discovered = pgcfg->global_catalog_auto_disc;
break;
case PROP_AD_UNIXUSER_ATTR:
STRDUP_CHECK(result->value.idmap_prop_val_u.utf8val,
diff --git a/usr/src/lib/libadutils/common/adutils.c b/usr/src/lib/libadutils/common/adutils.c
index d838858671..d914f109d2 100644
--- a/usr/src/lib/libadutils/common/adutils.c
+++ b/usr/src/lib/libadutils/common/adutils.c
@@ -66,6 +66,7 @@ static binary_attrs_t binattrs[] = {
{NULL, NULL}
};
+
void
adutils_set_log(int pri, bool_t syslog, bool_t degraded)
{
@@ -74,6 +75,7 @@ adutils_set_log(int pri, bool_t syslog, bool_t degraded)
idmap_log_degraded(degraded);
}
+
/*
* Turn "foo.bar.com" into "dc=foo,dc=bar,dc=com"
*/
@@ -85,6 +87,7 @@ adutils_dns2dn(const char *dns)
return (ldap_dns_to_dn((char *)dns, &nameparts));
}
+
/*
* Turn "dc=foo,dc=bar,dc=com" into "foo.bar.com"; ignores any other
* attributes (CN, etc...).
@@ -632,6 +635,8 @@ adutils_ad_free(adutils_ad_t **ad)
(void) pthread_mutex_unlock(&(*ad)->lock);
(void) pthread_mutex_destroy(&(*ad)->lock);
+ if ((*ad)->known_domains)
+ free((*ad)->known_domains);
free((*ad)->dflt_w2k_dom);
free(*ad);
@@ -761,7 +766,8 @@ retry:
* around the wrong number of times.
*/
for (;;) {
- if (adh != NULL && adh->ld != NULL && !adh->dead)
+ if (adh != NULL && adh->owner == ad && adh->ld != NULL &&
+ !adh->dead)
break;
if (adh == NULL || (adh = adh->next) == NULL)
adh = host_head;
@@ -919,6 +925,88 @@ delete_ds(adutils_ad_t *ad, const char *host, int port)
}
}
+/*
+ * Add known domain name and domain SID to AD configuration.
+ */
+
+adutils_rc
+adutils_add_domain(adutils_ad_t *ad, const char *domain, const char *sid)
+{
+ struct known_domain *new;
+ int num = ad->num_known_domains;
+
+ ad->num_known_domains++;
+ new = realloc(ad->known_domains,
+ sizeof (struct known_domain) * ad->num_known_domains);
+ if (new != NULL) {
+ ad->known_domains = new;
+ (void) strlcpy(ad->known_domains[num].name, domain,
+ sizeof (ad->known_domains[num].name));
+ (void) strlcpy(ad->known_domains[num].sid, sid,
+ sizeof (ad->known_domains[num].sid));
+ return (ADUTILS_SUCCESS);
+ } else {
+ if (ad->known_domains != NULL) {
+ free(ad->known_domains);
+ ad->known_domains = NULL;
+ }
+ ad->num_known_domains = 0;
+ return (ADUTILS_ERR_MEMORY);
+ }
+}
+
+
+/*
+ * Check that this AD supports this domain.
+ * If there are no known domains assume that the
+ * domain is supported by this AD.
+ *
+ * Returns 1 if this domain is supported by this AD
+ * else returns 0;
+ */
+
+int
+adutils_lookup_check_domain(adutils_query_state_t *qs, const char *domain)
+{
+ adutils_ad_t *ad = qs->qadh->owner;
+ int i, err;
+
+ for (i = 0; i < ad->num_known_domains; i++) {
+ if (u8_strcmp(domain, ad->known_domains[i].name, 0,
+ U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) == 0 &&
+ err == 0)
+ return (1);
+ }
+
+ return ((i == 0) ? 1 : 0);
+}
+
+
+/*
+ * Check that this AD supports the SID prefix.
+ * The SID prefix should match the domain SID.
+ * If there are no known domains assume that the
+ * SID prefix is supported by this AD.
+ *
+ * Returns 1 if this sid prefix is supported by this AD
+ * else returns 0;
+ */
+
+int
+adutils_lookup_check_sid_prefix(adutils_query_state_t *qs, const char *sid)
+{
+ adutils_ad_t *ad = qs->qadh->owner;
+ int i;
+
+
+ for (i = 0; i < ad->num_known_domains; i++) {
+ if (strcmp(sid, ad->known_domains[i].sid) == 0)
+ return (1);
+ }
+
+ return ((i == 0) ? 1 : 0);
+}
+
adutils_rc
adutils_lookup_batch_start(adutils_ad_t *ad, int nqueries,
@@ -964,9 +1052,9 @@ adutils_lookup_batch_start(adutils_ad_t *ad, int nqueries,
new_state->ref_cnt = 1;
new_state->qadh = adh;
- new_state->qcount = nqueries;
+ new_state->qsize = nqueries;
new_state->qadh_gen = adh->generation;
- new_state->qlastsent = 0;
+ new_state->qcount = 0;
new_state->ldap_res_search_cb = ldap_res_search_cb;
new_state->ldap_res_search_argp = ldap_res_search_argp;
(void) pthread_cond_init(&new_state->cv, NULL);
@@ -1588,9 +1676,11 @@ adutils_lookup_batch_add(adutils_query_state_t *state,
struct timeval tv;
adutils_q_t *q;
- qid = atomic_inc_32_nv(&state->qlastsent) - 1;
+ qid = atomic_inc_32_nv(&state->qcount) - 1;
q = &(state->queries[qid]);
+ assert(qid < state->qsize);
+
/*
* Remember the expected domain so we can check the results
* against it
diff --git a/usr/src/lib/libadutils/common/adutils_impl.h b/usr/src/lib/libadutils/common/adutils_impl.h
index 847d5e384d..530e3a2ca3 100644
--- a/usr/src/lib/libadutils/common/adutils_impl.h
+++ b/usr/src/lib/libadutils/common/adutils_impl.h
@@ -43,6 +43,14 @@ extern "C" {
#define ADUTILS_SEARCH_TIMEOUT 3
#define ADUTILS_LDAP_OPEN_TIMEOUT 1
+/*
+ * Maximum string SID size. 4 bytes for "S-1-", 15 for 2^48 (max authority),
+ * another '-', and ridcount (max 15) 10-digit RIDs plus '-' in between, plus
+ * a null.
+ */
+#define MAXSID 185
+#define MAXDOMAINNAME 256
+
typedef struct adutils_sid {
uchar_t version;
uchar_t sub_authority_count;
@@ -52,10 +60,17 @@ typedef struct adutils_sid {
struct adutils_host;
+struct known_domain {
+ char name[MAXDOMAINNAME];
+ char sid[MAXSID];
+};
+
/* A set of DSs for a given AD partition */
struct adutils_ad {
char *dflt_w2k_dom; /* used to qualify bare names */
+ int num_known_domains;
+ struct known_domain *known_domains;
pthread_mutex_t lock;
uint32_t ref;
struct adutils_host *last_adh;
@@ -124,10 +139,10 @@ typedef struct adutils_q {
/* Batch context structure */
struct adutils_query_state {
struct adutils_query_state *next;
- int qcount; /* how many queries */
+ int qsize; /* Size of queries */
int ref_cnt; /* reference count */
pthread_cond_t cv; /* Condition wait variable */
- uint32_t qlastsent;
+ uint32_t qcount; /* Number of items queued */
uint32_t qinflight; /* how many queries in flight */
uint16_t qdead; /* oops, lost LDAP connection */
adutils_host_t *qadh; /* LDAP connection */
diff --git a/usr/src/lib/libadutils/common/libadutils.h b/usr/src/lib/libadutils/common/libadutils.h
index 9a6d82a0b2..8f88e2d27a 100644
--- a/usr/src/lib/libadutils/common/libadutils.h
+++ b/usr/src/lib/libadutils/common/libadutils.h
@@ -135,6 +135,9 @@ extern adutils_rc adutils_ad_alloc(adutils_ad_t **new_ad,
extern void adutils_ad_free(adutils_ad_t **ad);
extern adutils_rc adutils_add_ds(adutils_ad_t *ad,
const char *host, int port);
+extern adutils_rc adutils_add_domain(adutils_ad_t *ad,
+ const char *domain_name,
+ const char *domain_sid);
extern void adutils_set_log(int pri, bool_t syslog,
bool_t degraded);
extern void adutils_freeresult(adutils_result_t **result);
@@ -169,6 +172,12 @@ extern void adutils_lookup_batch_release(
adutils_query_state_t **state);
extern const char *adutils_lookup_batch_getdefdomain(
adutils_query_state_t *state);
+extern int adutils_lookup_check_domain(
+ adutils_query_state_t *state,
+ const char *domain);
+extern int adutils_lookup_check_sid_prefix(
+ adutils_query_state_t *state,
+ const char *sid);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libadutils/common/mapfile-vers b/usr/src/lib/libadutils/common/mapfile-vers
index 07d0065906..da06606624 100644
--- a/usr/src/lib/libadutils/common/mapfile-vers
+++ b/usr/src/lib/libadutils/common/mapfile-vers
@@ -37,11 +37,14 @@ SUNWprivate {
adutils_lookup_batch_end;
adutils_lookup_batch_release;
adutils_lookup_batch_getdefdomain;
+ adutils_lookup_check_domain;
+ adutils_lookup_check_sid_prefix;
adutils_dn2dns;
adutils_reap_idle_connections;
adutils_ad_alloc;
adutils_ad_free;
adutils_add_ds;
+ adutils_add_domain;
adutils_set_log;
local:
*;
diff --git a/usr/src/lib/libidmap/common/addisc.c b/usr/src/lib/libidmap/common/addisc.c
index 45a74f07fb..be49e53f41 100644
--- a/usr/src/lib/libidmap/common/addisc.c
+++ b/usr/src/lib/libidmap/common/addisc.c
@@ -24,7 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Active Directory Auto-Discovery.
@@ -83,6 +82,7 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
+#include <assert.h>
#include <stdlib.h>
#include <net/if.h>
#include <net/if.h>
@@ -99,12 +99,70 @@
#include <errno.h>
#include <ldap.h>
#include <sasl/sasl.h>
+#include <sys/u8_textprep.h>
#include "addisc.h"
+enum ad_item_state {
+ AD_STATE_INVALID = 0, /* The value is not valid */
+ AD_STATE_FIXED, /* The value was fixed by caller */
+ AD_STATE_AUTO /* The value is auto discovered */
+ };
+
+enum ad_data_type {
+ AD_STRING = 123,
+ AD_DIRECTORY,
+ AD_DOMAINS_IN_FOREST,
+ AD_TRUSTED_DOMAINS
+ };
+
+
+typedef struct ad_subnet {
+ char subnet[24];
+} ad_subnet_t;
+
+
+typedef struct ad_item {
+ enum ad_item_state state;
+ enum ad_data_type type;
+ void *value;
+ time_t ttl;
+ unsigned int version; /* Version is only changed */
+ /* if the value changes */
+#define PARAM1 0
+#define PARAM2 1
+ int param_version[2];
+ /* These holds the version of */
+ /* dependents so that a dependent */
+ /* change can be detected */
+} ad_item_t;
+
+typedef struct ad_disc {
+ struct __res_state res_state;
+ int res_ninitted;
+ ad_subnet_t *subnets;
+ int subnets_changed;
+ time_t subnets_last_check;
+ ad_item_t domain_name; /* DNS hostname string */
+ ad_item_t domain_controller; /* Directory hostname and */
+ /* port array */
+ ad_item_t site_name; /* String */
+ ad_item_t forest_name; /* DNS forestname string */
+ ad_item_t global_catalog; /* Directory hostname and */
+ /* port array */
+ ad_item_t domains_in_forest; /* DNS domainname and SID */
+ /* array */
+ ad_item_t trusted_domains; /* DNS domainname and trust */
+ /* direction array */
+ /* Site specfic versions */
+ ad_item_t site_domain_controller; /* Directory hostname and */
+ /* port array */
+ ad_item_t site_global_catalog; /* Directory hostname and */
+ /* port array */
+} ad_disc;
+
#define DNS_MAX_NAME NS_MAXDNAME
-#define DN_MAX_NAME (DNS_MAX_NAME + 512)
/* SRV RR names for various queries */
@@ -124,25 +182,22 @@
* idmapd is running before the network is up!
*/
#define DO_RES_NINIT(ctx) if (!(ctx)->res_ninitted) \
- (ctx)->res_ninitted = res_ninit(&ctx->state) != -1
+ (ctx)->res_ninitted = (res_ninit(&ctx->res_state) != -1)
#define is_fixed(item) \
- ((item)->type == AD_TYPE_FIXED)
+ ((item)->state == AD_STATE_FIXED)
#define is_changed(item, num, param) \
((item)->param_version[num] != (param)->version)
-#define is_valid(item) \
- ((item)->type != AD_TYPE_INVALID && (item)->value.str != NULL)
-
/*LINTLIBRARY*/
/*
* Function definitions
*/
-static void validate_SiteName(ad_disc_t ctx);
+static ad_item_t *
+validate_SiteName(ad_disc_t ctx);
-static idmap_ad_disc_ds_t *dsdup(const idmap_ad_disc_ds_t *);
static void
@@ -152,33 +207,43 @@ update_version(ad_item_t *item, int num, ad_item_t *param)
}
+
static int
-is_expired(ad_item_t *item)
+is_valid(ad_item_t *item)
{
- if (item->type == AD_TYPE_FIXED)
- return (FALSE);
- if (item->type == AD_TYPE_AUTO &&
- (item->ttl == 0 || item->ttl > time(NULL)))
- return (FALSE);
- return (TRUE);
+ if (item->value != NULL) {
+ if (item->state == AD_STATE_FIXED)
+ return (TRUE);
+ if (item->state == AD_STATE_AUTO &&
+ (item->ttl == 0 || item->ttl > time(NULL)))
+ return (TRUE);
+ }
+ return (FALSE);
}
static void
-update_string(ad_item_t *item, char *value, enum ad_item_type type,
+update_item(ad_item_t *item, void *value, enum ad_item_state state,
uint32_t ttl)
{
- if (item->value.str != NULL && value != NULL) {
- if (strcmp(item->value.str, value) != 0)
+ if (item->value != NULL && value != NULL) {
+ if ((item->type == AD_STRING &&
+ strcmp(item->value, value) != 0) ||
+ (item->type == AD_DIRECTORY &&
+ ad_disc_compare_ds(item->value, value) != 0)||
+ (item->type == AD_DOMAINS_IN_FOREST &&
+ ad_disc_compare_domainsinforest(item->value, value) != 0) ||
+ (item->type == AD_TRUSTED_DOMAINS &&
+ ad_disc_compare_trusteddomains(item->value, value) != 0))
item->version++;
- } else if (item->value.str != value)
+ } else if (item->value != value)
item->version++;
- if (item->value.str != NULL)
- free(item->value.str);
+ if (item->value != NULL)
+ free(item->value);
- item->value.str = value;
- item->type = type;
+ item->value = value;
+ item->state = state;
if (ttl == 0)
item->ttl = 0;
@@ -187,53 +252,180 @@ update_string(ad_item_t *item, char *value, enum ad_item_type type,
}
-static void
-update_ds(ad_item_t *item, idmap_ad_disc_ds_t *value, enum ad_item_type type,
- uint32_t ttl)
+/* Compare DS lists */
+int
+ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2)
{
- if (item->value.ds != NULL && value != NULL) {
- if (ad_disc_compare_ds(item->value.ds, value) != 0)
- item->version++;
- } else if (item->value.ds != value)
- item->version++;
+ int i, j;
+ int num_ds1;
+ int num_ds2;
+ int match;
+
+ for (i = 0; ds1[i].host[0] != '\0'; i++)
+ continue;
+ num_ds1 = i;
+ for (j = 0; ds2[j].host[0] != '\0'; j++)
+ continue;
+ num_ds2 = j;
+ if (num_ds1 != num_ds2)
+ return (1);
+
+ for (i = 0; i < num_ds1; i++) {
+ match = FALSE;
+ for (j = 0; j < num_ds2; j++) {
+ if (strcmp(ds1[i].host, ds2[i].host) == 0 &&
+ ds1[i].port == ds2[i].port) {
+ match = TRUE;
+ break;
+ }
+ }
+ if (!match)
+ return (1);
+ }
+ return (0);
+}
- if (item->value.ds != NULL)
- free(item->value.ds);
- item->value.ds = value;
- item->type = type;
+/* Copy a list of DSs */
+static idmap_ad_disc_ds_t *
+ds_dup(const idmap_ad_disc_ds_t *srv)
+{
+ int i;
+ int size;
+ idmap_ad_disc_ds_t *new = NULL;
- if (ttl == 0)
- item->ttl = 0;
- else
- item->ttl = time(NULL) + ttl;
+ for (i = 0; srv[i].host[0] != '\0'; i++)
+ continue;
+
+ size = (i + 1) * sizeof (idmap_ad_disc_ds_t);
+ new = malloc(size);
+ if (new != NULL)
+ memcpy(new, srv, size);
+ return (new);
}
-static ad_item_t *
-get_item(ad_item_t *global, ad_item_t *site, enum ad_disc_req req)
+int
+ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t *td1,
+ ad_disc_trusteddomains_t *td2)
{
- ad_item_t *item;
- if (is_fixed(global))
- return (global);
+ int i, j;
+ int num_td1;
+ int num_td2;
+ int match;
+ int err;
- if (req == AD_DISC_GLOBAL)
- item = global;
- else if (req == AD_DISC_SITE_SPECIFIC)
- item = site;
- else if (is_valid(site))
- item = site;
- else
- item = global;
+ for (i = 0; td1[i].domain[0] != '\0'; i++)
+ continue;
+ num_td1 = i;
- if (!is_valid(item))
- return (NULL);
+ for (j = 0; td2[j].domain[0] != '\0'; j++)
+ continue;
+ num_td2 = j;
+
+ if (num_td1 != num_td2)
+ return (1);
- return (item);
+ for (i = 0; i < num_td1; i++) {
+ match = FALSE;
+ for (j = 0; j < num_td2; j++) {
+ if (u8_strcmp(td1[i].domain, td2[i].domain, 0,
+ U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) == 0 &&
+ err == 0) {
+ match = TRUE;
+ break;
+ }
+ }
+ if (!match)
+ return (1);
+ }
+ return (0);
}
+/* Copy a list of Trusted Domains */
+static ad_disc_trusteddomains_t *
+td_dup(const ad_disc_trusteddomains_t *td)
+{
+ int i;
+ int size;
+ ad_disc_trusteddomains_t *new = NULL;
+
+ for (i = 0; td[i].domain[0] != '\0'; i++)
+ continue;
+
+ size = (i + 1) * sizeof (ad_disc_trusteddomains_t);
+ new = malloc(size);
+ if (new != NULL)
+ memcpy(new, td, size);
+ return (new);
+}
+
+
+
+int
+ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t *df1,
+ ad_disc_domainsinforest_t *df2)
+{
+ int i, j;
+ int num_df1;
+ int num_df2;
+ int match;
+ int err;
+
+ for (i = 0; df1[i].domain[0] != '\0'; i++)
+ continue;
+ num_df1 = i;
+
+ for (j = 0; df2[j].domain[0] != '\0'; j++)
+ continue;
+ num_df2 = j;
+
+ if (num_df1 != num_df2)
+ return (1);
+
+ for (i = 0; i < num_df1; i++) {
+ match = FALSE;
+ for (j = 0; j < num_df2; j++) {
+ if (u8_strcmp(df1[i].domain, df2[i].domain, 0,
+ U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err) == 0 &&
+ err == 0 &&
+ strcmp(df1[i].sid, df2[i].sid) == 0) {
+ match = TRUE;
+ break;
+ }
+ }
+ if (!match)
+ return (1);
+ }
+ return (0);
+}
+
+
+
+/* Copy a list of Trusted Domains */
+static ad_disc_domainsinforest_t *
+df_dup(const ad_disc_domainsinforest_t *df)
+{
+ int i;
+ int size;
+ ad_disc_domainsinforest_t *new = NULL;
+
+ for (i = 0; df[i].domain[0] != '\0'; i++)
+ continue;
+
+ size = (i + 1) * sizeof (ad_disc_domainsinforest_t);
+ new = malloc(size);
+ if (new != NULL)
+ memcpy(new, df, size);
+ return (new);
+}
+
+
+
+
+
/*
* Returns an array of IPv4 address/prefix length
* The last subnet is NULL
@@ -334,11 +526,11 @@ cmpsubnets(ad_subnet_t *subnets1, ad_subnet_t *subnets2)
int i, j;
for (i = 0; subnets1[i].subnet[0] != '\0'; i++)
- ;
+ continue;
num_subnets1 = i;
for (i = 0; subnets2[i].subnet[0] != '\0'; i++)
- ;
+ continue;
num_subnets2 = i;
if (num_subnets1 != num_subnets2)
@@ -374,27 +566,29 @@ DN_to_DNS(const char *dn_name)
j = 0;
i = 0;
+ if (dn_name == NULL)
+ return (NULL);
/*
* Find all DC=<value> and form DNS name of the
* form <value1>.<value2>...
*/
- while (dn_name[i] != NULL) {
+ while (dn_name[i] != '\0') {
if (strncasecmp(&dn_name[i], "DC=", 3) == 0) {
i += 3;
- if (dn_name[i] != NULL && num > 0)
+ if (dn_name[i] != '\0' && num > 0)
dns[j++] = '.';
- while (dn_name[i] != NULL &&
+ while (dn_name[i] != '\0' &&
dn_name[i] != ',' && dn_name[i] != '+')
dns[j++] = dn_name[i++];
num++;
} else {
/* Skip attr=value as it is not DC= */
- while (dn_name[i] != NULL &&
+ while (dn_name[i] != '\0' &&
dn_name[i] != ',' && dn_name[i] != '+')
i++;
}
/* Skip over separator ',' or '+' */
- if (dn_name[i] != NULL) i++;
+ if (dn_name[i] != '\0') i++;
}
dns[j] = '\0';
dns_name = malloc(j + 1);
@@ -432,7 +626,7 @@ subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn)
int i, j;
for (i = 0; subnets[i].subnet[0] != '\0'; i++)
- ;
+ continue;
results = calloc(i + 1, sizeof (char *));
if (results == NULL)
@@ -451,57 +645,6 @@ subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn)
return (results);
}
-/* Compare DS lists */
-int
-ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2)
-{
- int i, j;
- int num_ds1;
- int num_ds2;
- int match;
-
- for (i = 0; ds1[i].host[0] != '\0'; i++)
- ;
- num_ds1 = i;
- for (j = 0; ds2[j].host[0] != '\0'; j++)
- ;
- num_ds2 = j;
- if (num_ds1 != num_ds2)
- return (1);
-
- for (i = 0; i < num_ds1; i++) {
- match = FALSE;
- for (j = 0; j < num_ds1; j++) {
- if (strcmp(ds1[i].host, ds2[i].host) == 0) {
- match = TRUE;
- break;
- }
- }
- if (!match)
- return (1);
- }
- return (0);
-}
-
-
-/* Copy a list of DSs */
-static idmap_ad_disc_ds_t *
-dsdup(const idmap_ad_disc_ds_t *srv)
-{
- int i;
- int size;
- idmap_ad_disc_ds_t *new = NULL;
-
- for (i = 0; srv[i].host[0] != '\0'; i++)
- ;
-
- size = (i + 1) * sizeof (idmap_ad_disc_ds_t);
- new = malloc(size);
- if (new != NULL)
- memcpy(new, srv, size);
- return (new);
-}
-
/* Compare SRC RRs; used with qsort() */
static int
@@ -678,6 +821,59 @@ saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts)
return (LDAP_SUCCESS);
}
+/*
+ * A utility function to bind to a Directory server
+ */
+
+static LDAP*
+ldap_lookup_init(idmap_ad_disc_ds_t *ds)
+{
+ int i;
+ int rc, ldversion;
+ int zero = 0;
+ int timeoutms = 5 * 1000;
+ char *saslmech = "GSSAPI";
+ uint32_t saslflags = LDAP_SASL_INTERACTIVE;
+ LDAP *ld = NULL;
+
+ for (i = 0; ds[i].host[0] != '\0'; i++) {
+ ld = ldap_init(ds[i].host, ds[i].port);
+ if (ld == NULL) {
+ idmapdlog(LOG_DEBUG, "Couldn't connect to "
+ "AD DC %s:%d (%s)",
+ ds[i].host, ds[i].port,
+ strerror(errno));
+ continue;
+ }
+
+ ldversion = LDAP_VERSION3;
+ (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+ &ldversion);
+
+ (void) ldap_set_option(ld, LDAP_OPT_REFERRALS,
+ LDAP_OPT_OFF);
+ (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero);
+ (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero);
+ /* setup TCP/IP connect timeout */
+ (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT,
+ &timeoutms);
+ (void) ldap_set_option(ld, LDAP_OPT_RESTART,
+ LDAP_OPT_ON);
+
+ rc = ldap_sasl_interactive_bind_s(ld, "" /* binddn */,
+ saslmech, NULL, NULL, saslflags, &saslcallback,
+ NULL /* defaults */);
+ if (rc == LDAP_SUCCESS)
+ break;
+
+ idmapdlog(LOG_INFO, "LDAP SASL bind to %s:%d failed (%s)",
+ ds[i].host, ds[i].port, ldap_err2string(rc));
+ (void) ldap_unbind(ld);
+ ld = NULL;
+ }
+ return (ld);
+}
+
/*
* A utility function to get the value of some attribute of one of one
@@ -688,11 +884,7 @@ ldap_lookup_entry_attr(LDAP **ld, idmap_ad_disc_ds_t *domainControllers,
char **dn_list, char *attr)
{
int i;
- int rc, ldversion;
- int zero = 0;
- int timeoutms = 5 * 1000;
- char *saslmech = "GSSAPI";
- uint32_t saslflags = LDAP_SASL_INTERACTIVE;
+ int rc;
int scope = LDAP_SCOPE_BASE;
char *attrs[2];
LDAPMessage *results = NULL;
@@ -703,55 +895,11 @@ ldap_lookup_entry_attr(LDAP **ld, idmap_ad_disc_ds_t *domainControllers,
attrs[0] = attr;
attrs[1] = NULL;
- rc = LDAP_INVALID_CREDENTIALS;
+ if (*ld == NULL)
+ *ld = ldap_lookup_init(domainControllers);
- if (*ld == NULL) {
- for (i = 0; domainControllers[i].host[0] != '\0'; i++) {
- *ld = ldap_init(domainControllers[i].host,
- domainControllers[i].port);
- if (*ld == NULL) {
- idmapdlog(LOG_INFO, "Couldn't connect to "
- "AD DC %s:%d (%s)",
- domainControllers[i].host,
- domainControllers[i].port,
- strerror(errno));
- continue;
- }
-
- ldversion = LDAP_VERSION3;
- (void) ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION,
- &ldversion);
-
- (void) ldap_set_option(*ld, LDAP_OPT_REFERRALS,
- LDAP_OPT_OFF);
- (void) ldap_set_option(*ld, LDAP_OPT_TIMELIMIT, &zero);
- (void) ldap_set_option(*ld, LDAP_OPT_SIZELIMIT, &zero);
- /* setup TCP/IP connect timeout */
- (void) ldap_set_option(*ld, LDAP_X_OPT_CONNECT_TIMEOUT,
- &timeoutms);
- (void) ldap_set_option(*ld, LDAP_OPT_RESTART,
- LDAP_OPT_ON);
-
- rc = ldap_sasl_interactive_bind_s(*ld, "" /* binddn */,
- saslmech, NULL, NULL, saslflags, &saslcallback,
- NULL /* defaults */);
-
- if (rc == LDAP_SUCCESS)
- break;
- idmapdlog(LOG_INFO, "LDAP SASL bind to %s:%d "
- "failed (%s)", domainControllers[i].host,
- domainControllers[i].port, ldap_err2string(rc));
- (void) ldap_unbind(*ld);
- *ld = NULL;
- }
- }
-
- if (*ld == NULL) {
- idmapdlog(LOG_NOTICE, "Couldn't open and SASL bind LDAP "
- "connections to any domain controllers; discovery of "
- "some items will fail");
+ if (*ld == NULL)
return (NULL);
- }
for (i = 0; dn_list[i] != NULL; i++) {
rc = ldap_search_s(*ld, dn_list[i], scope,
@@ -776,13 +924,271 @@ ldap_lookup_entry_attr(LDAP **ld, idmap_ad_disc_ds_t *domainControllers,
results = NULL;
}
}
- (void) ldap_unbind(*ld);
- *ld = NULL;
return (NULL);
}
+/*
+ * Lookup the trusted domains in the global catalog.
+ *
+ * Returns:
+ * array of trusted domains which is terminated by
+ * an empty trusted domain.
+ * NULL an error occured
+ */
+ad_disc_trusteddomains_t *
+ldap_lookup_trusted_domains(LDAP **ld, idmap_ad_disc_ds_t *globalCatalog,
+ char *base_dn)
+{
+ int scope = LDAP_SCOPE_SUBTREE;
+ char *attrs[3];
+ int rc;
+ LDAPMessage *results = NULL;
+ LDAPMessage *entry;
+ char *filter;
+ char **partner = NULL;
+ char **direction = NULL;
+ int num = 0;
+ ad_disc_trusteddomains_t *trusted_domains = NULL;
+
+
+ if (*ld == NULL)
+ *ld = ldap_lookup_init(globalCatalog);
+
+ if (*ld == NULL)
+ return (NULL);
+
+ attrs[0] = "trustPartner";
+ attrs[1] = "trustDirection";
+ attrs[2] = NULL;
+
+ /* trustDirection values - inbound = 1 and bidirectional = 3 */
+ filter = "(&(objectclass=trustedDomain)"
+ "(|(trustDirection=3)(trustDirection=1)))";
+
+ rc = ldap_search_s(*ld, base_dn, scope, filter, attrs, 0, &results);
+ if (rc == LDAP_SUCCESS) {
+ for (entry = ldap_first_entry(*ld, results);
+ entry != NULL; entry = ldap_next_entry(*ld, entry)) {
+ partner = ldap_get_values(*ld, entry, "trustPartner");
+ direction = ldap_get_values(
+ *ld, entry, "trustDirection");
+
+ if (partner != NULL && direction != NULL) {
+ num++;
+ trusted_domains = realloc(trusted_domains,
+ (num + 1) *
+ sizeof (ad_disc_trusteddomains_t));
+ if (trusted_domains == NULL) {
+ ldap_value_free(partner);
+ ldap_value_free(direction);
+ ldap_msgfree(results);
+ return (NULL);
+ }
+ /* Last element should be zero */
+ memset(&trusted_domains[num], 0,
+ sizeof (ad_disc_trusteddomains_t));
+ strcpy(trusted_domains[num - 1].domain,
+ partner[0]);
+ trusted_domains[num - 1].direction =
+ atoi(direction[0]);
+ }
+ if (partner != NULL)
+ ldap_value_free(partner);
+ if (direction != NULL)
+ ldap_value_free(direction);
+ }
+ } else if (rc == LDAP_NO_RESULTS_RETURNED) {
+ /* This is not an error - return empty trusted domain */
+ trusted_domains = calloc(1, sizeof (ad_disc_trusteddomains_t));
+ }
+ if (results != NULL)
+ ldap_msgfree(results);
+
+ return (trusted_domains);
+}
+
+static int
+decode_sid(BerValue *bval, char *sid_txt)
+{
+ int i, j;
+ uchar_t *v;
+ uint32_t a;
+ struct sid {
+ uchar_t version;
+ uchar_t sub_authority_count;
+ uint64_t authority; /* really, 48-bits */
+ uint32_t sub_authorities[16];
+ } sid;
+ char *ptr;
+ int len;
+ int rlen;
+
+
+ /*
+ * The binary format of a SID is as follows:
+ *
+ * byte #0: version, always 0x01
+ * byte #1: RID count, always <= 0x0f
+ * bytes #2-#7: SID authority, big-endian 48-bit unsigned int
+ *
+ * followed by RID count RIDs, each a little-endian, unsigned
+ * 32-bit int.
+ */
+ /*
+ * Sanity checks: must have at least one RID, version must be
+ * 0x01, and the length must be 8 + rid count * 4
+ */
+ if (bval->bv_len > 8 && bval->bv_val[0] == 0x01 &&
+ bval->bv_len == 1 + 1 + 6 + bval->bv_val[1] * 4) {
+ v = (uchar_t *)bval->bv_val;
+ sid.version = v[0];
+ sid.sub_authority_count = v[1];
+ sid.authority =
+ /* big endian -- so start from the left */
+ ((u_longlong_t)v[2] << 40) |
+ ((u_longlong_t)v[3] << 32) |
+ ((u_longlong_t)v[4] << 24) |
+ ((u_longlong_t)v[5] << 16) |
+ ((u_longlong_t)v[6] << 8) |
+ (u_longlong_t)v[7];
+ for (i = 0; i < sid.sub_authority_count; i++) {
+ j = 8 + (i * 4);
+ /* little endian -- so start from the right */
+ a = (v[j + 3] << 24) | (v[j + 2] << 16) |
+ (v[j + 1] << 8) | (v[j]);
+ sid.sub_authorities[i] = a;
+ }
+
+ ptr = sid_txt;
+ len = AD_DISC_MAXSID;
+ rlen = snprintf(ptr, len, "S-1-%llu", sid.authority);
+
+ ptr += rlen;
+ len -= rlen;
+
+ for (i = 0; i < sid.sub_authority_count; i++) {
+ assert(len > 0);
+ rlen = snprintf(
+ ptr, len, "-%u", sid.sub_authorities[i]);
+ ptr += rlen;
+ len -= rlen;
+ }
+ assert(len > 0);
+ return (0);
+ }
+ return (-1);
+}
+
+/*
+ * This functions finds all the domains in a forest.
+ * It first finds all the naming contexts by finding the
+ * root DSE attribute namingContext. For each naming context
+ * it performes an entry search looking for Domain object class
+ * returning the attribute objectSid.
+ */
+ad_disc_domainsinforest_t *
+ldap_lookup_domains_in_forest(LDAP **ld, idmap_ad_disc_ds_t *globalCatalogs)
+{
+ int scope = LDAP_SCOPE_BASE;
+ char *attrs[2];
+ char *root_attrs[2];
+ int rc;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry;
+ char *filter;
+ char **nc = NULL;
+ struct berval **sid_ber;
+ int num = 0;
+ ad_disc_domainsinforest_t *domains = NULL;
+ int i;
+ char *name;
+
+
+ if (*ld == NULL)
+ *ld = ldap_lookup_init(globalCatalogs);
+
+ if (*ld == NULL) {
+ idmapdlog(LOG_NOTICE, "Couldn't open and SASL bind LDAP "
+ "connections to any domain controllers; discovery of "
+ "some items will fail");
+ return (NULL);
+ }
+
+ root_attrs[0] = "namingContexts";
+ root_attrs[1] = NULL;
+
+ attrs[0] = "objectSid";
+ attrs[1] = NULL;
+
+ filter = "(objectclass=Domain)";
+
+ /* Find naming contexts */
+ rc = ldap_search_s(*ld, LDAP_ROOT_DSE, scope, "(objectClass=*)",
+ root_attrs, 0, &result);
+ if (rc == LDAP_SUCCESS) {
+ entry = ldap_first_entry(*ld, result);
+ if (entry != NULL) {
+ nc = ldap_get_values(*ld, entry, "namingContexts");
+ }
+ }
+ if (result != NULL)
+ ldap_msgfree(result);
+ if (nc == NULL)
+ return (NULL);
+
+ /* Find domains */
+ for (i = 0; nc[i] != NULL; i++) {
+ rc = ldap_search_s(*ld, nc[i], scope, filter, attrs, 0,
+ &result);
+ if (rc == LDAP_SUCCESS) {
+ entry = ldap_first_entry(*ld, result);
+ if (entry != NULL) {
+ sid_ber = ldap_get_values_len(*ld, entry,
+ "objectSid");
+ if (sid_ber != NULL) {
+ num++;
+ domains = realloc(domains,
+ (num + 1) *
+ sizeof (ad_disc_domainsinforest_t));
+ if (domains == NULL) {
+ ldap_value_free_len(sid_ber);
+ ldap_msgfree(result);
+ ldap_value_free(nc);
+ return (NULL);
+ }
+ memset(&domains[num], 0,
+ sizeof (ad_disc_domainsinforest_t));
+ if (decode_sid(sid_ber[0],
+ domains[num - 1].sid) < 0) {
+ ldap_value_free_len(sid_ber);
+ ldap_msgfree(result);
+ ldap_value_free(nc);
+ return (NULL);
+ }
+ ldap_value_free_len(sid_ber);
+
+ name = DN_to_DNS(nc[i]);
+ if (name == NULL) {
+ free(domains);
+ ldap_msgfree(result);
+ ldap_value_free(nc);
+ return (NULL);
+ }
+ strcpy(domains[num - 1].domain, name);
+ free(name);
+ }
+ }
+ }
+ if (result != NULL)
+ ldap_msgfree(result);
+ }
+ ldap_value_free(nc);
+
+ return (domains);
+}
+
ad_disc_t
ad_disc_init(void)
@@ -791,6 +1197,17 @@ ad_disc_init(void)
ctx = calloc(1, sizeof (struct ad_disc));
if (ctx != NULL)
DO_RES_NINIT(ctx);
+
+ ctx->domain_name.type = AD_STRING;
+ ctx->domain_controller.type = AD_DIRECTORY;
+ ctx->site_name.type = AD_STRING;
+ ctx->forest_name.type = AD_STRING;
+ ctx->global_catalog.type = AD_DIRECTORY;
+ ctx->domains_in_forest.type = AD_DOMAINS_IN_FOREST;
+ ctx->trusted_domains.type = AD_TRUSTED_DOMAINS;
+ /* Site specific versions */
+ ctx->site_domain_controller.type = AD_DIRECTORY;
+ ctx->site_global_catalog.type = AD_DIRECTORY;
return (ctx);
}
@@ -802,31 +1219,38 @@ ad_disc_fini(ad_disc_t ctx)
return;
if (ctx->res_ninitted)
- res_ndestroy(&ctx->state);
+ res_ndestroy(&ctx->res_state);
if (ctx->subnets != NULL)
free(ctx->subnets);
- if (ctx->domain_name.value.str != NULL)
- free(ctx->domain_name.value.str);
+ if (ctx->domain_name.value != NULL)
+ free(ctx->domain_name.value);
+
+ if (ctx->domain_controller.value != NULL)
+ free(ctx->domain_controller.value);
+
+ if (ctx->site_name.value != NULL)
+ free(ctx->site_name.value);
- if (ctx->domain_controller.value.str != NULL)
- free(ctx->domain_controller.value.str);
+ if (ctx->forest_name.value != NULL)
+ free(ctx->forest_name.value);
- if (ctx->site_name.value.str != NULL)
- free(ctx->site_name.value.str);
+ if (ctx->global_catalog.value != NULL)
+ free(ctx->global_catalog.value);
- if (ctx->forest_name.value.str != NULL)
- free(ctx->forest_name.value.str);
+ if (ctx->domains_in_forest.value != NULL)
+ free(ctx->domains_in_forest.value);
- if (ctx->global_catalog.value.str != NULL)
- free(ctx->global_catalog.value.str);
+ if (ctx->trusted_domains.value != NULL)
+ free(ctx->trusted_domains.value);
- if (ctx->site_domain_controller.value.str != NULL)
- free(ctx->site_domain_controller.value.str);
+ /* Site specific versions */
+ if (ctx->site_domain_controller.value != NULL)
+ free(ctx->site_domain_controller.value);
- if (ctx->site_global_catalog.value.str != NULL)
- free(ctx->site_global_catalog.value.str);
+ if (ctx->site_global_catalog.value != NULL)
+ free(ctx->site_global_catalog.value);
free(ctx);
}
@@ -835,59 +1259,63 @@ void
ad_disc_refresh(ad_disc_t ctx)
{
if (ctx->res_ninitted)
- res_ndestroy(&ctx->state);
- (void) memset(&ctx->state, 0, sizeof (ctx->state));
- ctx->res_ninitted = res_ninit(&ctx->state) != -1;
+ res_ndestroy(&ctx->res_state);
+ (void) memset(&ctx->res_state, 0, sizeof (ctx->res_state));
+ ctx->res_ninitted = res_ninit(&ctx->res_state) != -1;
- if (ctx->domain_name.type == AD_TYPE_AUTO)
- ctx->domain_name.type = AD_TYPE_INVALID;
+ if (ctx->domain_name.state == AD_STATE_AUTO)
+ ctx->domain_name.state = AD_STATE_INVALID;
- if (ctx->domain_controller.type == AD_TYPE_AUTO)
- ctx->domain_controller.type = AD_TYPE_INVALID;
+ if (ctx->domain_controller.state == AD_STATE_AUTO)
+ ctx->domain_controller.state = AD_STATE_INVALID;
- if (ctx->site_name.type == AD_TYPE_AUTO)
- ctx->site_name.type = AD_TYPE_INVALID;
+ if (ctx->site_name.state == AD_STATE_AUTO)
+ ctx->site_name.state = AD_STATE_INVALID;
- if (ctx->forest_name.type == AD_TYPE_AUTO)
- ctx->forest_name.type = AD_TYPE_INVALID;
+ if (ctx->forest_name.state == AD_STATE_AUTO)
+ ctx->forest_name.state = AD_STATE_INVALID;
- if (ctx->global_catalog.type == AD_TYPE_AUTO)
- ctx->global_catalog.type = AD_TYPE_INVALID;
+ if (ctx->global_catalog.state == AD_STATE_AUTO)
+ ctx->global_catalog.state = AD_STATE_INVALID;
- if (ctx->site_domain_controller.type == AD_TYPE_AUTO)
- ctx->site_domain_controller.type = AD_TYPE_INVALID;
+ if (ctx->domains_in_forest.state == AD_STATE_AUTO)
+ ctx->domains_in_forest.state = AD_STATE_INVALID;
- if (ctx->site_global_catalog.type == AD_TYPE_AUTO)
- ctx->site_global_catalog.type = AD_TYPE_INVALID;
+ if (ctx->trusted_domains.state == AD_STATE_AUTO)
+ ctx->trusted_domains.state = AD_STATE_INVALID;
+
+ if (ctx->site_domain_controller.state == AD_STATE_AUTO)
+ ctx->site_domain_controller.state = AD_STATE_INVALID;
+
+ if (ctx->site_global_catalog.state == AD_STATE_AUTO)
+ ctx->site_global_catalog.state = AD_STATE_INVALID;
}
/* Discover joined Active Directory domainName */
-static void
+static ad_item_t *
validate_DomainName(ad_disc_t ctx)
{
idmap_ad_disc_ds_t *domain_controller = NULL;
char *dname, *srvname;
uint32_t ttl = 0;
- if (is_fixed(&ctx->domain_name))
- return;
+ if (is_valid(&ctx->domain_name))
+ return (&ctx->domain_name);
- if (!is_expired(&ctx->domain_name))
- return;
/* Try to find our domain by searching for DCs for it */
DO_RES_NINIT(ctx);
- domain_controller = srv_query(&ctx->state, LDAP_SRV_HEAD
- DC_SRV_TAIL, ctx->domain_name.value.str, &srvname, &ttl);
+ domain_controller = srv_query(&ctx->res_state, LDAP_SRV_HEAD
+ DC_SRV_TAIL, ctx->domain_name.value, &srvname, &ttl);
/*
* If we can't find DCs by via res_nsearch() then there's no
* point in trying anything else to discover the AD domain name.
*/
if (domain_controller == NULL)
- return;
+ return (NULL);
free(domain_controller);
/*
@@ -901,85 +1329,98 @@ validate_DomainName(ad_disc_t ctx)
if (dname == NULL) {
idmapdlog(LOG_ERR, "Out of memory");
- return;
+ return (NULL);
}
/* Eat any trailing dot */
if (*(dname + strlen(dname)) == '.')
*(dname + strlen(dname)) = '\0';
- update_string(&ctx->domain_name, dname, AD_TYPE_AUTO, 0);
+ update_item(&ctx->domain_name, dname, AD_STATE_AUTO, ttl);
+
+ return (&ctx->domain_name);
}
char *
-ad_disc_get_DomainName(ad_disc_t ctx)
+ad_disc_get_DomainName(ad_disc_t ctx, int *auto_discovered)
{
char *domain_name = NULL;
+ ad_item_t *domain_name_item;
- validate_DomainName(ctx);
+ domain_name_item = validate_DomainName(ctx);
+
+ if (domain_name_item) {
+ domain_name = strdup(domain_name_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (domain_name_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
- if (is_valid(&ctx->domain_name))
- domain_name = strdup(ctx->domain_name.value.str);
return (domain_name);
}
/* Discover domain controllers */
-static void
+static ad_item_t *
validate_DomainController(ad_disc_t ctx, enum ad_disc_req req)
{
uint32_t ttl = 0;
idmap_ad_disc_ds_t *domain_controller = NULL;
int validate_global = FALSE;
int validate_site = FALSE;
+ ad_item_t *domain_name_item;
+ ad_item_t *site_name_item = NULL;
+ /* If the values is fixed there will not be a site specific version */
if (is_fixed(&ctx->domain_controller))
- return;
+ return (&ctx->domain_controller);
+
+ domain_name_item = validate_DomainName(ctx);
+ if (domain_name_item == NULL)
+ return (NULL);
- validate_DomainName(ctx);
if (req == AD_DISC_GLOBAL)
validate_global = TRUE;
else {
- validate_SiteName(ctx);
- if (is_valid(&ctx->site_name))
+ site_name_item = validate_SiteName(ctx);
+ if (site_name_item != NULL)
validate_site = TRUE;
- if (req == AD_DISC_PREFER_SITE)
+ else if (req == AD_DISC_PREFER_SITE)
validate_global = TRUE;
}
- if (validate_global && (is_expired(&ctx->domain_controller) ||
- is_changed(&ctx->domain_controller, PARAM1, &ctx->domain_name))) {
-
- update_version(&ctx->domain_controller, PARAM1,
- &ctx->domain_name);
-
- if (is_valid(&ctx->domain_name)) {
+ if (validate_global) {
+ if (!is_valid(&ctx->domain_controller) ||
+ is_changed(&ctx->domain_controller, PARAM1,
+ domain_name_item)) {
/*
* Lookup DNS SRV RR named
* _ldap._tcp.dc._msdcs.<DomainName>
*/
DO_RES_NINIT(ctx);
- domain_controller = srv_query(&ctx->state,
+ domain_controller = srv_query(&ctx->res_state,
LDAP_SRV_HEAD DC_SRV_TAIL,
- ctx->domain_name.value.str, NULL, &ttl);
- }
- update_ds(&ctx->domain_controller, domain_controller,
- AD_TYPE_AUTO, ttl);
- }
+ domain_name_item->value, NULL, &ttl);
- if (validate_site && (is_expired(&ctx->site_domain_controller) ||
- is_changed(&ctx->site_domain_controller, PARAM1,
- &ctx->domain_name) ||
- is_changed(&ctx->site_domain_controller, PARAM2,
- &ctx->site_name))) {
+ if (domain_controller == NULL)
+ return (NULL);
- update_version(&ctx->site_domain_controller, PARAM1,
- &ctx->domain_name);
- update_version(&ctx->site_domain_controller, PARAM2,
- &ctx->site_name);
+ update_item(&ctx->domain_controller, domain_controller,
+ AD_STATE_AUTO, ttl);
+ update_version(&ctx->domain_controller, PARAM1,
+ domain_name_item);
+ }
+ return (&ctx->domain_controller);
+ }
- if (is_valid(&ctx->domain_name)) {
+ if (validate_site) {
+ if (!is_valid(&ctx->site_domain_controller) ||
+ is_changed(&ctx->site_domain_controller, PARAM1,
+ domain_name_item) ||
+ is_changed(&ctx->site_domain_controller, PARAM2,
+ site_name_item)) {
char rr_name[DNS_MAX_NAME];
/*
* Lookup DNS SRV RR named
@@ -987,33 +1428,48 @@ validate_DomainController(ad_disc_t ctx, enum ad_disc_req req)
*/
(void) snprintf(rr_name, sizeof (rr_name),
LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
- ctx->site_name.value.str);
+ site_name_item->value);
DO_RES_NINIT(ctx);
- domain_controller = srv_query(&ctx->state, rr_name,
- ctx->domain_name.value.str, NULL, &ttl);
+ domain_controller = srv_query(&ctx->res_state, rr_name,
+ domain_name_item->value, NULL, &ttl);
+ if (domain_controller == NULL)
+ return (NULL);
+
+ update_item(&ctx->site_domain_controller,
+ domain_controller, AD_STATE_AUTO, ttl);
+ update_version(&ctx->site_domain_controller, PARAM1,
+ domain_name_item);
+ update_version(&ctx->site_domain_controller, PARAM2,
+ site_name_item);
}
- update_ds(&ctx->site_domain_controller, domain_controller,
- AD_TYPE_AUTO, ttl);
+ return (&ctx->site_domain_controller);
}
+ return (NULL);
}
idmap_ad_disc_ds_t *
-ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req)
+ad_disc_get_DomainController(ad_disc_t ctx, enum ad_disc_req req,
+ int *auto_discovered)
{
+ ad_item_t *domain_controller_item;
idmap_ad_disc_ds_t *domain_controller = NULL;
- ad_item_t *item;
- validate_DomainController(ctx, req);
- item = get_item(&ctx->domain_controller,
- &ctx->site_domain_controller, req);
- if (item != NULL && is_valid(item))
- domain_controller = dsdup(item->value.ds);
+ domain_controller_item = validate_DomainController(ctx, req);
+
+ if (domain_controller_item != NULL) {
+ domain_controller = ds_dup(domain_controller_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (domain_controller_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
+
return (domain_controller);
}
/* Discover site name (for multi-homed systems the first one found wins) */
-static void
+static ad_item_t *
validate_SiteName(ad_disc_t ctx)
{
LDAP *ld = NULL;
@@ -1027,14 +1483,17 @@ validate_SiteName(ad_disc_t ctx)
int len;
int i;
int update_required = FALSE;
+ ad_item_t *domain_controller_item;
if (is_fixed(&ctx->site_name))
- return;
+ return (&ctx->site_name);
/* Can't rely on site-specific DCs */
- validate_DomainController(ctx, AD_DISC_GLOBAL);
+ domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
+ if (domain_controller_item == NULL)
+ return (NULL);
- if (is_expired(&ctx->site_name) ||
+ if (!is_valid(&ctx->site_name) ||
is_changed(&ctx->site_name, PARAM1, &ctx->domain_controller) ||
ctx->subnets == NULL || ctx->subnets_changed) {
subnets = find_subnets();
@@ -1049,86 +1508,77 @@ validate_SiteName(ad_disc_t ctx)
if (!update_required) {
free(subnets);
- return;
+ return (&ctx->site_name);
}
- update_version(&ctx->site_name, PARAM1, &ctx->domain_controller);
+ if (subnets == NULL)
+ return (NULL);
- if (is_valid(&ctx->domain_name) &&
- is_valid(&ctx->domain_controller) &&
- subnets != NULL) {
- dn_root[0] = "";
- dn_root[1] = NULL;
+ dn_root[0] = "";
+ dn_root[1] = NULL;
- config_naming_context = ldap_lookup_entry_attr(
- &ld, ctx->domain_controller.value.ds,
- dn_root, "configurationNamingContext");
- if (config_naming_context == NULL)
- goto out;
+ config_naming_context = ldap_lookup_entry_attr(
+ &ld, ctx->domain_controller.value,
+ dn_root, "configurationNamingContext");
+ if (config_naming_context == NULL)
+ goto out;
+ /*
+ * configurationNamingContext also provides the Forest
+ * Name.
+ */
+ if (!is_fixed(&ctx->forest_name)) {
/*
- * configurationNamingContext also provides the Forest
- * Name.
+ * The configurationNamingContext should be of
+ * form:
+ * CN=Configuration,<DNforestName>
+ * Remove the first part and convert to DNS form
+ * (replace ",DC=" with ".")
*/
- if (!is_fixed(&ctx->forest_name)) {
- /*
- * The configurationNamingContext should be of
- * form:
- * CN=Configuration,<DNforestName>
- * Remove the first part and convert to DNS form
- * (replace ",DC=" with ".")
- */
- char *str = "CN=Configuration,";
- int len = strlen(str);
- if (strncasecmp(config_naming_context, str, len) == 0) {
- forest_name = DN_to_DNS(
- config_naming_context + len);
- update_string(&ctx->forest_name,
- forest_name, AD_TYPE_AUTO, 0);
- }
+ char *str = "CN=Configuration,";
+ int len = strlen(str);
+ if (strncasecmp(config_naming_context, str, len) == 0) {
+ forest_name = DN_to_DNS(config_naming_context + len);
+ update_item(&ctx->forest_name, forest_name,
+ AD_STATE_AUTO, 0);
}
- dn_subnets = subnets_to_DNs(subnets, config_naming_context);
- if (dn_subnets == NULL)
- goto out;
-
- site_object = ldap_lookup_entry_attr(
- &ld, ctx->domain_controller.value.ds,
- dn_subnets, "siteobject");
- if (site_object != NULL) {
- /*
- * The site object should be of the form
- * CN=<site>,CN=Sites,CN=Configuration,
- * <DN Domain>
- */
- if (strncasecmp(site_object, "CN=", 3) == 0) {
- for (len = 0;
- site_object[len + 3] != ','; len++)
+ }
+
+ dn_subnets = subnets_to_DNs(subnets, config_naming_context);
+ if (dn_subnets == NULL)
+ goto out;
+
+ site_object = ldap_lookup_entry_attr(
+ &ld, domain_controller_item->value,
+ dn_subnets, "siteobject");
+ if (site_object != NULL) {
+ /*
+ * The site object should be of the form
+ * CN=<site>,CN=Sites,CN=Configuration,
+ * <DN Domain>
+ */
+ if (strncasecmp(site_object, "CN=", 3) == 0) {
+ for (len = 0; site_object[len + 3] != ','; len++)
;
- site_name = malloc(len + 1);
- (void) strncpy(site_name, &site_object[3], len);
- site_name[len] = '\0';
- }
+ site_name = malloc(len + 1);
+ (void) strncpy(site_name, &site_object[3], len);
+ site_name[len] = '\0';
+ update_item(&ctx->site_name, site_name,
+ AD_STATE_AUTO, 0);
}
+ }
- if (ctx->subnets != NULL) {
- free(ctx->subnets);
- ctx->subnets = NULL;
- }
- ctx->subnets = subnets;
- subnets = NULL;
- ctx->subnets_changed = FALSE;
+ if (ctx->subnets != NULL) {
+ free(ctx->subnets);
+ ctx->subnets = NULL;
}
+ ctx->subnets = subnets;
+ subnets = NULL;
+ ctx->subnets_changed = FALSE;
+
out:
if (ld != NULL)
(void) ldap_unbind(ld);
- update_string(&ctx->site_name, site_name, AD_TYPE_AUTO, 0);
-
- if (site_name == NULL || *site_name == '\0') {
- /* No site name -> no site-specific DSs */
- update_ds(&ctx->site_domain_controller, NULL, AD_TYPE_AUTO, 0);
- update_ds(&ctx->site_global_catalog, NULL, AD_TYPE_AUTO, 0);
- }
-
if (dn_subnets != NULL) {
for (i = 0; dn_subnets[i] != NULL; i++)
free(dn_subnets[i]);
@@ -1140,144 +1590,174 @@ out:
free(site_object);
free(subnets);
+ if (site_name == NULL)
+ return (NULL);
+ return (&ctx->site_name);
}
char *
-ad_disc_get_SiteName(ad_disc_t ctx)
+ad_disc_get_SiteName(ad_disc_t ctx, int *auto_discovered)
{
+ ad_item_t *site_name_item;
char *site_name = NULL;
- validate_SiteName(ctx);
- if (is_valid(&ctx->site_name))
- site_name = strdup(ctx->site_name.value.str);
+ site_name_item = validate_SiteName(ctx);
+ if (site_name_item != NULL) {
+ site_name = strdup(site_name_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (site_name_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
+
return (site_name);
}
/* Discover forest name */
-static void
+static ad_item_t *
validate_ForestName(ad_disc_t ctx)
{
LDAP *ld = NULL;
char *config_naming_context;
char *forest_name = NULL;
char *dn_list[2];
+ ad_item_t *domain_controller_item;
if (is_fixed(&ctx->forest_name))
- return;
+ return (&ctx->forest_name);
/*
* We may not have a site name yet, so we won't rely on
* site-specific DCs. (But maybe we could replace
* validate_ForestName() with validate_siteName()?)
*/
- validate_DomainController(ctx, AD_DISC_GLOBAL);
- if (is_expired(&ctx->forest_name) ||
- is_changed(&ctx->forest_name, PARAM1, &ctx->domain_controller)) {
+ domain_controller_item = validate_DomainController(ctx, AD_DISC_GLOBAL);
+ if (domain_controller_item == NULL)
+ return (NULL);
- update_version(&ctx->forest_name, PARAM1,
- &ctx->domain_controller);
-
- if (is_valid(&ctx->domain_controller)) {
- dn_list[0] = "";
- dn_list[1] = NULL;
- config_naming_context = ldap_lookup_entry_attr(
- &ld, ctx->domain_controller.value.ds,
- dn_list,
- "configurationNamingContext");
- if (config_naming_context != NULL) {
- /*
- * The configurationNamingContext should be of
- * form:
- * CN=Configuration,<DNforestName>
- * Remove the first part and convert to DNS form
- * (replace ",DC=" with ".")
- */
- char *str = "CN=Configuration,";
- int len = strlen(str);
- if (strncasecmp(config_naming_context,
- str, len) == 0) {
- forest_name = DN_to_DNS(
- config_naming_context + len);
- }
- free(config_naming_context);
+ if (!is_valid(&ctx->forest_name) ||
+ is_changed(&ctx->forest_name, PARAM1, domain_controller_item)) {
+
+ dn_list[0] = "";
+ dn_list[1] = NULL;
+ config_naming_context = ldap_lookup_entry_attr(
+ &ld, ctx->domain_controller.value,
+ dn_list, "configurationNamingContext");
+ if (config_naming_context != NULL) {
+ /*
+ * The configurationNamingContext should be of
+ * form:
+ * CN=Configuration,<DNforestName>
+ * Remove the first part and convert to DNS form
+ * (replace ",DC=" with ".")
+ */
+ char *str = "CN=Configuration,";
+ int len = strlen(str);
+ if (strncasecmp(config_naming_context, str, len) == 0) {
+ forest_name = DN_to_DNS(
+ config_naming_context + len);
}
- if (ld != NULL)
- (void) ldap_unbind(ld);
+ free(config_naming_context);
}
- update_string(&ctx->forest_name, forest_name, AD_TYPE_AUTO, 0);
+ if (ld != NULL)
+ (void) ldap_unbind(ld);
+
+ if (forest_name == NULL)
+ return (NULL);
+
+ update_item(&ctx->forest_name, forest_name, AD_STATE_AUTO, 0);
+ update_version(&ctx->forest_name, PARAM1,
+ domain_controller_item);
}
+ return (&ctx->forest_name);
}
char *
-ad_disc_get_ForestName(ad_disc_t ctx)
+ad_disc_get_ForestName(ad_disc_t ctx, int *auto_discovered)
{
+ ad_item_t *forest_name_item;
char *forest_name = NULL;
- validate_ForestName(ctx);
+ forest_name_item = validate_ForestName(ctx);
+
+ if (forest_name_item != NULL) {
+ forest_name = strdup(forest_name_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (forest_name_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
- if (is_valid(&ctx->forest_name))
- forest_name = strdup(ctx->forest_name.value.str);
return (forest_name);
}
/* Discover global catalog servers */
-static void
+static ad_item_t *
validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
{
idmap_ad_disc_ds_t *global_catalog = NULL;
uint32_t ttl = 0;
int validate_global = FALSE;
int validate_site = FALSE;
+ ad_item_t *forest_name_item;
+ ad_item_t *site_name_item;
+ /* If the values is fixed there will not be a site specific version */
if (is_fixed(&ctx->global_catalog))
- return;
+ return (&ctx->global_catalog);
+
+ forest_name_item = validate_ForestName(ctx);
+ if (forest_name_item == NULL)
+ return (NULL);
- validate_ForestName(ctx);
if (req == AD_DISC_GLOBAL)
validate_global = TRUE;
else {
- validate_SiteName(ctx);
- if (is_valid(&ctx->site_name))
+ site_name_item = validate_SiteName(ctx);
+ if (site_name_item != NULL)
validate_site = TRUE;
- if (req == AD_DISC_PREFER_SITE)
+ else if (req == AD_DISC_PREFER_SITE)
validate_global = TRUE;
}
- if (validate_global && (is_expired(&ctx->global_catalog) ||
- is_changed(&ctx->global_catalog, PARAM1, &ctx->forest_name))) {
-
- update_version(&ctx->global_catalog, PARAM1, &ctx->forest_name);
-
- if (is_valid(&ctx->forest_name)) {
+ if (validate_global) {
+ if (!is_valid(&ctx->global_catalog) ||
+ is_changed(&ctx->global_catalog, PARAM1,
+ forest_name_item)) {
/*
* Lookup DNS SRV RR named
* _ldap._tcp.gc._msdcs.<ForestName>
*/
DO_RES_NINIT(ctx);
global_catalog =
- srv_query(&ctx->state, LDAP_SRV_HEAD GC_SRV_TAIL,
- ctx->forest_name.value.str, NULL, &ttl);
- }
- update_ds(&ctx->global_catalog, global_catalog,
- AD_TYPE_AUTO, ttl);
- }
+ srv_query(&ctx->res_state,
+ LDAP_SRV_HEAD GC_SRV_TAIL,
+ ctx->forest_name.value, NULL, &ttl);
- if (validate_site && (is_expired(&ctx->site_global_catalog) ||
- is_changed(&ctx->site_global_catalog, PARAM1, &ctx->forest_name) ||
- is_changed(&ctx->site_global_catalog, PARAM2, &ctx->site_name))) {
+ if (global_catalog == NULL)
+ return (NULL);
- update_version(&ctx->site_global_catalog, PARAM1,
- &ctx->forest_name);
- update_version(&ctx->site_global_catalog, PARAM2,
- &ctx->site_name);
+ update_item(&ctx->global_catalog, global_catalog,
+ AD_STATE_AUTO, ttl);
+ update_version(&ctx->global_catalog, PARAM1,
+ forest_name_item);
+ }
+ return (&ctx->global_catalog);
+ }
- if (is_valid(&ctx->forest_name) && is_valid(&ctx->site_name)) {
+ if (validate_site) {
+ if (!is_valid(&ctx->site_global_catalog) ||
+ is_changed(&ctx->site_global_catalog, PARAM1,
+ forest_name_item) ||
+ is_changed(&ctx->site_global_catalog, PARAM2,
+ site_name_item)) {
char rr_name[DNS_MAX_NAME];
+
/*
* Lookup DNS SRV RR named:
* _ldap._tcp.<siteName>._sites.gc.
@@ -1286,33 +1766,187 @@ validate_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
(void) snprintf(rr_name,
sizeof (rr_name),
LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
- ctx->site_name.value.str);
+ ctx->site_name.value);
DO_RES_NINIT(ctx);
- global_catalog =
- srv_query(&ctx->state, rr_name,
- ctx->forest_name.value.str, NULL, &ttl);
+ global_catalog = srv_query(&ctx->res_state, rr_name,
+ ctx->forest_name.value, NULL, &ttl);
+
+ if (global_catalog == NULL)
+ return (NULL);
+ update_item(&ctx->site_global_catalog, global_catalog,
+ AD_STATE_AUTO, ttl);
+ update_version(&ctx->site_global_catalog, PARAM1,
+ forest_name_item);
+ update_version(&ctx->site_global_catalog, PARAM2,
+ site_name_item);
}
- update_ds(&ctx->site_global_catalog, global_catalog,
- AD_TYPE_AUTO, ttl);
+ return (&ctx->site_global_catalog);
}
+ return (NULL);
}
idmap_ad_disc_ds_t *
-ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req)
+ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req req,
+ int *auto_discovered)
{
idmap_ad_disc_ds_t *global_catalog = NULL;
- ad_item_t *item;
+ ad_item_t *global_catalog_item;
+
+ global_catalog_item = validate_GlobalCatalog(ctx, req);
- validate_GlobalCatalog(ctx, req);
+ if (global_catalog_item != NULL) {
+ global_catalog = ds_dup(global_catalog_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (global_catalog_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
- item = get_item(&ctx->global_catalog, &ctx->site_global_catalog, req);
- if (item != NULL && is_valid(item))
- global_catalog = dsdup(item->value.ds);
return (global_catalog);
}
+static ad_item_t *
+validate_TrustedDomains(ad_disc_t ctx)
+{
+ LDAP *ld = NULL;
+ ad_item_t *global_catalog_item;
+ ad_item_t *forest_name_item;
+ ad_disc_trusteddomains_t *trusted_domains;
+ char *dn = NULL;
+ char *forest_name_dn;
+ int len;
+ int num_parts;
+
+ if (is_fixed(&ctx->trusted_domains))
+ return (&ctx->trusted_domains);
+
+ global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL);
+ if (global_catalog_item == NULL)
+ return (NULL);
+
+ forest_name_item = validate_ForestName(ctx);
+ if (forest_name_item == NULL)
+ return (NULL);
+
+ if (!is_valid(&ctx->trusted_domains) ||
+ is_changed(&ctx->trusted_domains, PARAM1, global_catalog_item) ||
+ is_changed(&ctx->trusted_domains, PARAM2, forest_name_item)) {
+
+ forest_name_dn = ldap_dns_to_dn(forest_name_item->value,
+ &num_parts);
+ if (forest_name_dn == NULL)
+ return (NULL);
+
+ len = snprintf(NULL, 0, "CN=System,%s", forest_name_dn) + 1;
+ dn = malloc(len);
+ if (dn == NULL) {
+ free(forest_name_dn);
+ return (NULL);
+ }
+ (void) snprintf(dn, len, "CN=System,%s", forest_name_dn);
+ free(forest_name_dn);
+
+ trusted_domains = ldap_lookup_trusted_domains(
+ &ld, global_catalog_item->value, dn);
+
+ if (ld != NULL)
+ (void) ldap_unbind(ld);
+ free(dn);
+
+ if (trusted_domains == NULL)
+ return (NULL);
+
+ update_item(&ctx->trusted_domains, trusted_domains,
+ AD_STATE_AUTO, 0);
+ update_version(&ctx->trusted_domains, PARAM1,
+ global_catalog_item);
+ update_version(&ctx->trusted_domains, PARAM2,
+ forest_name_item);
+ }
+
+ return (&ctx->trusted_domains);
+}
+
+
+ad_disc_trusteddomains_t *
+ad_disc_get_TrustedDomains(ad_disc_t ctx, int *auto_discovered)
+{
+ ad_disc_trusteddomains_t *trusted_domains = NULL;
+ ad_item_t *trusted_domains_item;
+
+ trusted_domains_item = validate_TrustedDomains(ctx);
+
+ if (trusted_domains_item != NULL) {
+ trusted_domains = td_dup(trusted_domains_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (trusted_domains_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
+
+ return (trusted_domains);
+}
+
+
+static ad_item_t *
+validate_DomainsInForest(ad_disc_t ctx)
+{
+ ad_item_t *global_catalog_item;
+ LDAP *ld = NULL;
+ ad_disc_domainsinforest_t *domains_in_forest;
+
+ if (is_fixed(&ctx->domains_in_forest))
+ return (&ctx->domains_in_forest);
+
+ global_catalog_item = validate_GlobalCatalog(ctx, AD_DISC_GLOBAL);
+ if (global_catalog_item == NULL)
+ return (NULL);
+
+ if (!is_valid(&ctx->domains_in_forest) ||
+ is_changed(&ctx->domains_in_forest, PARAM1, global_catalog_item)) {
+
+ domains_in_forest = ldap_lookup_domains_in_forest(
+ &ld, global_catalog_item->value);
+
+ if (ld != NULL)
+ (void) ldap_unbind(ld);
+
+ if (domains_in_forest == NULL)
+ return (NULL);
+
+ update_item(&ctx->domains_in_forest, domains_in_forest,
+ AD_STATE_AUTO, 0);
+ update_version(&ctx->domains_in_forest, PARAM1,
+ global_catalog_item);
+ }
+ return (&ctx->domains_in_forest);
+}
+
+
+ad_disc_domainsinforest_t *
+ad_disc_get_DomainsInForest(ad_disc_t ctx, int *auto_discovered)
+{
+ ad_disc_domainsinforest_t *domains_in_forest = NULL;
+ ad_item_t *domains_in_forest_item;
+
+ domains_in_forest_item = validate_DomainsInForest(ctx);
+
+ if (domains_in_forest_item != NULL) {
+ domains_in_forest = df_dup(domains_in_forest_item->value);
+ if (auto_discovered != NULL)
+ *auto_discovered =
+ (domains_in_forest_item->state == AD_STATE_AUTO);
+ } else if (auto_discovered != NULL)
+ *auto_discovered = FALSE;
+
+ return (domains_in_forest);
+}
+
+
+
+
int
ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName)
{
@@ -1321,10 +1955,10 @@ ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName)
domain_name = strdup(domainName);
if (domain_name == NULL)
return (-1);
- update_string(&ctx->domain_name, domain_name,
- AD_TYPE_FIXED, 0);
- } else if (ctx->domain_name.type == AD_TYPE_FIXED)
- ctx->domain_name.type = AD_TYPE_INVALID;
+ update_item(&ctx->domain_name, domain_name,
+ AD_STATE_FIXED, 0);
+ } else if (ctx->domain_name.state == AD_STATE_FIXED)
+ ctx->domain_name.state = AD_STATE_INVALID;
return (0);
}
@@ -1335,13 +1969,13 @@ ad_disc_set_DomainController(ad_disc_t ctx,
{
idmap_ad_disc_ds_t *domain_controller = NULL;
if (domainController != NULL) {
- domain_controller = dsdup(domainController);
+ domain_controller = ds_dup(domainController);
if (domain_controller == NULL)
return (-1);
- update_ds(&ctx->domain_controller, domain_controller,
- AD_TYPE_FIXED, 0);
- } else if (ctx->domain_controller.type == AD_TYPE_FIXED)
- ctx->domain_controller.type = AD_TYPE_INVALID;
+ update_item(&ctx->domain_controller, domain_controller,
+ AD_STATE_FIXED, 0);
+ } else if (ctx->domain_controller.state == AD_STATE_FIXED)
+ ctx->domain_controller.state = AD_STATE_INVALID;
return (0);
}
@@ -1354,9 +1988,9 @@ ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName)
site_name = strdup(siteName);
if (site_name == NULL)
return (-1);
- update_string(&ctx->site_name, site_name, AD_TYPE_FIXED, 0);
- } else if (ctx->site_name.type == AD_TYPE_FIXED)
- ctx->site_name.type = AD_TYPE_INVALID;
+ update_item(&ctx->site_name, site_name, AD_STATE_FIXED, 0);
+ } else if (ctx->site_name.state == AD_STATE_FIXED)
+ ctx->site_name.state = AD_STATE_INVALID;
return (0);
}
@@ -1368,10 +2002,10 @@ ad_disc_set_ForestName(ad_disc_t ctx, const char *forestName)
forest_name = strdup(forestName);
if (forest_name == NULL)
return (-1);
- update_string(&ctx->forest_name, forest_name,
- AD_TYPE_FIXED, 0);
- } else if (ctx->forest_name.type == AD_TYPE_FIXED)
- ctx->forest_name.type = AD_TYPE_INVALID;
+ update_item(&ctx->forest_name, forest_name,
+ AD_STATE_FIXED, 0);
+ } else if (ctx->forest_name.state == AD_STATE_FIXED)
+ ctx->forest_name.state = AD_STATE_INVALID;
return (0);
}
@@ -1381,13 +2015,13 @@ ad_disc_set_GlobalCatalog(ad_disc_t ctx,
{
idmap_ad_disc_ds_t *global_catalog = NULL;
if (globalCatalog != NULL) {
- global_catalog = dsdup(globalCatalog);
+ global_catalog = ds_dup(globalCatalog);
if (global_catalog == NULL)
return (-1);
- update_ds(&ctx->global_catalog, global_catalog,
- AD_TYPE_FIXED, 0);
- } else if (ctx->global_catalog.type == AD_TYPE_FIXED)
- ctx->global_catalog.type = AD_TYPE_INVALID;
+ update_item(&ctx->global_catalog, global_catalog,
+ AD_STATE_FIXED, 0);
+ } else if (ctx->global_catalog.state == AD_STATE_FIXED)
+ ctx->global_catalog.state = AD_STATE_INVALID;
return (0);
}
@@ -1395,20 +2029,20 @@ ad_disc_set_GlobalCatalog(ad_disc_t ctx,
int
ad_disc_unset(ad_disc_t ctx)
{
- if (ctx->domain_name.type == AD_TYPE_FIXED)
- ctx->domain_name.type = AD_TYPE_INVALID;
+ if (ctx->domain_name.state == AD_STATE_FIXED)
+ ctx->domain_name.state = AD_STATE_INVALID;
- if (ctx->domain_controller.type == AD_TYPE_FIXED)
- ctx->domain_controller.type = AD_TYPE_INVALID;
+ if (ctx->domain_controller.state == AD_STATE_FIXED)
+ ctx->domain_controller.state = AD_STATE_INVALID;
- if (ctx->site_name.type == AD_TYPE_FIXED)
- ctx->site_name.type = AD_TYPE_INVALID;
+ if (ctx->site_name.state == AD_STATE_FIXED)
+ ctx->site_name.state = AD_STATE_INVALID;
- if (ctx->forest_name.type == AD_TYPE_FIXED)
- ctx->forest_name.type = AD_TYPE_INVALID;
+ if (ctx->forest_name.state == AD_STATE_FIXED)
+ ctx->forest_name.state = AD_STATE_INVALID;
- if (ctx->global_catalog.type == AD_TYPE_FIXED)
- ctx->global_catalog.type = AD_TYPE_INVALID;
+ if (ctx->global_catalog.state == AD_STATE_FIXED)
+ ctx->global_catalog.state = AD_STATE_INVALID;
return (0);
}
diff --git a/usr/src/lib/libidmap/common/addisc.h b/usr/src/lib/libidmap/common/addisc.h
index fd89f2c853..6622965e23 100644
--- a/usr/src/lib/libidmap/common/addisc.h
+++ b/usr/src/lib/libidmap/common/addisc.h
@@ -27,8 +27,6 @@
#ifndef _ADINFO_H
#define _ADINFO_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "idmap_priv.h"
#include "idmap_prot.h"
#include "idmap_impl.h"
@@ -37,55 +35,32 @@
extern "C" {
#endif
+/*
+ * Maximum string SID size. 4 bytes for "S-1-", 15 for 2^48 (max authority),
+ * another '-', and ridcount (max 15) 10-digit RIDs plus '-' in between, plus
+ * a null.
+ */
-enum ad_item_type {
- AD_TYPE_INVALID = 0, /* The value is not valid */
- AD_TYPE_FIXED, /* The value was fixed by caller */
- AD_TYPE_AUTO /* The value is auto discovered */
- };
-
-
-typedef struct ad_subnet {
- char subnet[24];
-} ad_subnet_t;
-
-
-typedef struct ad_item {
- enum ad_item_type type;
- union {
- char *str;
- idmap_ad_disc_ds_t *ds;
- } value;
- time_t ttl;
- unsigned int version; /* Version is only changed if the */
- /* value changes */
-#define PARAM1 0
-#define PARAM2 1
- int param_version[2];
- /* These holds the version of */
- /* dependents so that a dependent */
- /* change can be detected */
-} ad_item_t;
-
-typedef struct ad_disc {
- struct __res_state state;
- int res_ninitted;
- ad_subnet_t *subnets;
- int subnets_changed;
- time_t subnets_last_check;
- ad_item_t domain_name;
- ad_item_t domain_controller;
- ad_item_t site_name;
- ad_item_t forest_name;
- ad_item_t global_catalog;
- /* Site specfic versions */
- ad_item_t site_domain_controller;
- ad_item_t site_global_catalog;
-} ad_disc;
+#define AD_DISC_MAXSID 185
typedef struct ad_disc *ad_disc_t;
+typedef struct ad_disc_domains_in_forest {
+ char domain[AD_DISC_MAXHOSTNAME];
+ char sid[AD_DISC_MAXSID];
+ int trusted; /* This is not used by auto */
+ /* discovery. It is provided so that */
+ /* domains in a forest can be marked */
+ /* as trusted. */
+} ad_disc_domainsinforest_t;
+
+
+typedef struct ad_disc_trusted_domains {
+ char domain[AD_DISC_MAXHOSTNAME];
+ int direction;
+} ad_disc_trusteddomains_t;
+
enum ad_disc_req {
AD_DISC_PREFER_SITE = 0, /* Prefer Site specific version */
@@ -97,40 +72,78 @@ ad_disc_t ad_disc_init(void);
void ad_disc_fini(ad_disc_t);
-void ad_disc_refresh(ad_disc_t);
+/*
+ * The following routines auto discover the specific item
+ */
+char *
+ad_disc_get_DomainName(ad_disc_t ctx, int *auto_discovered);
-char *ad_disc_get_DomainName(ad_disc_t ctx);
+idmap_ad_disc_ds_t *
+ad_disc_get_DomainController(ad_disc_t ctx,
+ enum ad_disc_req req, int *auto_discovered);
-idmap_ad_disc_ds_t *ad_disc_get_DomainController(ad_disc_t ctx,
- enum ad_disc_req req);
+char *
+ad_disc_get_SiteName(ad_disc_t ctx, int *auto_discovered);
-char *ad_disc_get_SiteName(ad_disc_t ctx);
+char *
+ad_disc_get_ForestName(ad_disc_t ctx, int *auto_discovered);
-char *ad_disc_get_ForestName(ad_disc_t ctx);
+idmap_ad_disc_ds_t *
+ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req,
+ int *auto_discovered);
-idmap_ad_disc_ds_t *ad_disc_get_GlobalCatalog(ad_disc_t ctx, enum ad_disc_req);
+ad_disc_trusteddomains_t *
+ad_disc_get_TrustedDomains(ad_disc_t ctx, int *auto_discovered);
-int ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2);
+ad_disc_domainsinforest_t *
+ad_disc_get_DomainsInForest(ad_disc_t ctx, int *auto_discovered);
-int ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName);
-int ad_disc_set_DomainController(ad_disc_t ctx,
- const idmap_ad_disc_ds_t *domainController);
+/*
+ * The following routines over ride auto discovery with the
+ * specified values
+ */
+int
+ad_disc_set_DomainName(ad_disc_t ctx, const char *domainName);
-int ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName);
+int
+ad_disc_set_DomainController(ad_disc_t ctx,
+ const idmap_ad_disc_ds_t *domainController);
-int ad_disc_set_ForestName(ad_disc_t ctx, const char *ForestName);
+int
+ad_disc_set_SiteName(ad_disc_t ctx, const char *siteName);
-int ad_disc_set_GlobalCatalog(ad_disc_t ctx,
- const idmap_ad_disc_ds_t *GlobalCatalog);
+int
+ad_disc_set_ForestName(ad_disc_t ctx, const char *forestName);
+
+int
+ad_disc_set_GlobalCatalog(ad_disc_t ctx,
+ const idmap_ad_disc_ds_t *globalCatalog);
-int ad_disc_unset(ad_disc_t ctx);
+/*
+ * This routine forces all auto discovery item to be recomputed
+ * on request
+ */
+void ad_disc_refresh(ad_disc_t);
+/* This routine unsets all overridden values */
+int ad_disc_unset(ad_disc_t ctx);
+
+/* This routine test for subnet changes */
int ad_disc_SubnetChanged(ad_disc_t);
+/* This routine returns the Time To Live for auto discovered items */
int ad_disc_get_TTL(ad_disc_t);
+int ad_disc_compare_ds(idmap_ad_disc_ds_t *ds1, idmap_ad_disc_ds_t *ds2);
+
+int ad_disc_compare_trusteddomains(ad_disc_trusteddomains_t *td1,
+ ad_disc_trusteddomains_t *td2);
+
+int ad_disc_compare_domainsinforest(ad_disc_domainsinforest_t *td1,
+ ad_disc_domainsinforest_t *td2);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libidmap/common/idmap_api.c b/usr/src/lib/libidmap/common/idmap_api.c
index 69ed433d98..0fe0d8f418 100644
--- a/usr/src/lib/libidmap/common/idmap_api.c
+++ b/usr/src/lib/libidmap/common/idmap_api.c
@@ -224,7 +224,7 @@ idmap_fini(idmap_handle_t *handle)
}
-idmap_stat
+static idmap_stat
idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
{
CLIENT *clnt;
@@ -243,24 +243,9 @@ idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
}
return (res->retcode); /* This might not be IDMAP_SUCCESS! */
-
-#if 0
- (void) memset(&res, 0, sizeof (res));
- pr = PROP_DOMAIN_CONTROLLER;
-
- clntstat = clnt_call(clnt, IDMAP_GET_PROP,
- (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
- (xdrproc_t)xdr_idmap_prop_res, (caddr_t)&res, TIMEOUT);
-
- if (clntstat != RPC_SUCCESS) {
- fprintf(stderr, "clntstat != RPC_SUCCESS\n");
- rc = _idmap_rpc2stat(clnt);
- goto cleanup;
- }
-#endif
-
}
+
idmap_stat
idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
idmap_ad_disc_ds_t *dc)
@@ -2066,7 +2051,7 @@ static stat_table_t stattable[] = {
{IDMAP_ERR_BAD_UTF8,
gettext("Invalid or illegal UTF-8 sequence found in "
"a given Windows entity name or domain name"), EINVAL},
- {IDMAP_ERR_NONEGENERATED,
+ {IDMAP_ERR_NONE_GENERATED,
gettext("Mapping not found and none created (see -c option)"),
EINVAL},
{IDMAP_ERR_PROP_UNKNOWN,
@@ -2080,6 +2065,9 @@ static stat_table_t stattable[] = {
gettext("Native LDAP operation failed"), EINVAL},
{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
gettext("Improper winname form found in Native LDAP"), EINVAL},
+ {IDMAP_ERR_NO_ACTIVEDIRECTORY,
+ gettext("No AD servers"),
+ EINVAL},
{-1, NULL, 0}
};
#undef gettext
@@ -2167,12 +2155,13 @@ idmap_string2stat(const char *str)
return_cmp(W2U_NAMERULE_CONFLICT);
return_cmp(U2W_NAMERULE_CONFLICT);
return_cmp(BAD_UTF8);
- return_cmp(NONEGENERATED);
+ return_cmp(NONE_GENERATED);
return_cmp(PROP_UNKNOWN);
return_cmp(NS_LDAP_CFG);
return_cmp(NS_LDAP_PARTIAL);
return_cmp(NS_LDAP_OP_FAILED);
return_cmp(NS_LDAP_BAD_WINNAME);
+ return_cmp(NO_ACTIVEDIRECTORY);
#undef return_cmp
return (IDMAP_ERR_OTHER);
diff --git a/usr/src/lib/libidmap/common/mapfile-vers b/usr/src/lib/libidmap/common/mapfile-vers
index 7360322a8a..905cc8b64f 100644
--- a/usr/src/lib/libidmap/common/mapfile-vers
+++ b/usr/src/lib/libidmap/common/mapfile-vers
@@ -98,6 +98,8 @@ SUNWprivate {
ad_disc_get_DomainName;
ad_disc_set_DomainName;
ad_disc_compare_ds;
+ ad_disc_compare_trusteddomains;
+ ad_disc_compare_domainsinforest;
ad_disc_SubnetChanged;
ad_disc_get_GlobalCatalog;
ad_disc_set_GlobalCatalog;
@@ -109,6 +111,8 @@ SUNWprivate {
ad_disc_set_SiteName;
ad_disc_refresh;
ad_disc_get_SiteName;
+ ad_disc_get_TrustedDomains;
+ ad_disc_get_DomainsInForest;
local:
*;
};
diff --git a/usr/src/lib/libidmap/common/namemaps.c b/usr/src/lib/libidmap/common/namemaps.c
index a72a7e360b..ce43ece4ce 100644
--- a/usr/src/lib/libidmap/common/namemaps.c
+++ b/usr/src/lib/libidmap/common/namemaps.c
@@ -23,14 +23,12 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <errno.h>
#include <ldap.h>
#include <sasl/sasl.h>
#include <libintl.h>
#include <strings.h>
-#include <strings.h>
#include "idmap_impl.h"
#include "ns_sldap.h"
@@ -249,7 +247,7 @@ idmap_init_ad(idmap_nm_handle_t *p)
goto cleanup;
}
- dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL);
+ dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL, NULL);
if (dc == NULL) {
rc = IDMAP_ERR_ARG;
idmapdlog(LOG_ERR,
diff --git a/usr/src/lib/nsswitch/ad/common/ad_common.c b/usr/src/lib/nsswitch/ad/common/ad_common.c
index 9265defe13..749e269165 100644
--- a/usr/src/lib/nsswitch/ad/common/ad_common.c
+++ b/usr/src/lib/nsswitch/ad/common/ad_common.c
@@ -62,7 +62,8 @@ nssad_cfg_discover_props(const char *domain, ad_disc_t ad_ctx,
return (-1);
if (props->domain_controller == NULL)
props->domain_controller =
- ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE);
+ ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE,
+ NULL);
return (0);
}
diff --git a/usr/src/uts/common/sys/idmap.h b/usr/src/uts/common/sys/idmap.h
index 3a405e4097..d0f270e697 100644
--- a/usr/src/uts/common/sys/idmap.h
+++ b/usr/src/uts/common/sys/idmap.h
@@ -26,7 +26,6 @@
#ifndef _SYS_IDMAP_H
#define _SYS_IDMAP_H
-#pragma ident "%Z%%M% %I% %E% SMI"
/* Idmap status codes */
#define IDMAP_SUCCESS 0
@@ -64,12 +63,13 @@
#define IDMAP_ERR_W2U_NAMERULE_CONFLICT -9970
#define IDMAP_ERR_U2W_NAMERULE_CONFLICT -9969
#define IDMAP_ERR_BAD_UTF8 -9968
-#define IDMAP_ERR_NONEGENERATED -9967
+#define IDMAP_ERR_NONE_GENERATED -9967
#define IDMAP_ERR_PROP_UNKNOWN -9966
#define IDMAP_ERR_NS_LDAP_OP_FAILED -9965
#define IDMAP_ERR_NS_LDAP_PARTIAL -9964
#define IDMAP_ERR_NS_LDAP_CFG -9963
#define IDMAP_ERR_NS_LDAP_BAD_WINNAME -9962
+#define IDMAP_ERR_NO_ACTIVEDIRECTORY -9961
/* Reserved GIDs for some well-known SIDs */
#define IDMAP_WK_LOCAL_SYSTEM_GID 2147483648U /* 0x80000000 */