summaryrefslogtreecommitdiff
path: root/src/providers/ldap
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/ldap')
-rw-r--r--src/providers/ldap/ldap_common.c10
-rw-r--r--src/providers/ldap/ldap_id.c2
-rw-r--r--src/providers/ldap/sdap.c84
-rw-r--r--src/providers/ldap/sdap.h17
-rw-r--r--src/providers/ldap/sdap_async.c1
-rw-r--r--src/providers/ldap/sdap_async.h6
-rw-r--r--src/providers/ldap/sdap_async_connection.c28
-rw-r--r--src/providers/ldap/sdap_id_op.c9
8 files changed, 133 insertions, 24 deletions
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 4242a7e4..5e2572b8 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -81,17 +81,17 @@ struct dp_option default_basic_opts[] = {
struct sdap_attr_map generic_attr_map[] = {
{ "ldap_entry_usn", NULL, SYSDB_USN, NULL },
- { "ldap_rootdse_last_usn", NULL, SYSDB_USN, NULL }
+ { "ldap_rootdse_last_usn", NULL, SYSDB_HIGH_USN, NULL }
};
struct sdap_attr_map gen_ipa_attr_map[] = {
- { "ldap_entry_usn", "entryUSN", SYSDB_USN, NULL },
- { "ldap_rootdse_last_usn", "lastUSN", SYSDB_HIGH_USN, NULL }
+ { "ldap_entry_usn", SDAP_IPA_USN, SYSDB_USN, NULL },
+ { "ldap_rootdse_last_usn", SDAP_IPA_LAST_USN, SYSDB_HIGH_USN, NULL }
};
struct sdap_attr_map gen_ad_attr_map[] = {
- { "ldap_entry_usn", "uSNChanged", SYSDB_USN, NULL },
- { "ldap_rootdse_last_usn", "highestCommittedUSN", SYSDB_HIGH_USN, NULL }
+ { "ldap_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL },
+ { "ldap_rootdse_last_usn", SDAP_AD_LAST_USN, SYSDB_HIGH_USN, NULL }
};
struct sdap_attr_map rfc2307_user_map[] = {
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 9121a3e9..ce94731c 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -673,7 +673,7 @@ static void sdap_check_online_done(struct tevent_req *req)
int dp_err = DP_ERR_FATAL;
bool can_retry;
- ret = sdap_cli_connect_recv_ext(req, NULL, &can_retry, NULL);
+ ret = sdap_cli_connect_recv(req, NULL, &can_retry, NULL, NULL);
talloc_zfree(req);
if (ret != EOK) {
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 1a065cc8..ffe625b3 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -495,7 +495,6 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
-1 };
size_t c;
-
for (c = 0; search_base_options[c] != -1; c++) {
if (dp_opt_get_string(opts->basic, search_base_options[c]) == NULL) {
if (naming_context == NULL) {
@@ -526,6 +525,89 @@ done:
return ret;
}
+int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
+ const char *server,
+ struct sysdb_attrs *rootdse,
+ struct sdap_options *opts,
+ struct sdap_server_opts **srv_opts)
+{
+ struct sdap_server_opts *so;
+ struct {
+ const char *last_name;
+ const char *entry_name;
+ } usn_attrs[] = { { SDAP_IPA_LAST_USN, SDAP_IPA_USN },
+ { SDAP_AD_LAST_USN, SDAP_AD_USN },
+ { NULL, NULL } };
+ const char *last_usn_name;
+ const char *last_usn_value;
+ int ret;
+ int i;
+
+ so = talloc_zero(memctx, struct sdap_server_opts);
+ if (!so) {
+ return ENOMEM;
+ }
+ so->server_id = talloc_strdup(so, server);
+ if (!so->server_id) {
+ talloc_zfree(so);
+ return ENOMEM;
+ }
+
+ last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name;
+ if (last_usn_name) {
+ ret = sysdb_attrs_get_string(rootdse,
+ last_usn_name, &last_usn_value);
+ if (ret != EOK) {
+ switch (ret) {
+ case ENOENT:
+ DEBUG(1, ("%s configured but not found in rootdse!\n",
+ opts->gen_map[SDAP_AT_LAST_USN].opt_name));
+ break;
+ case ERANGE:
+ DEBUG(1, ("Multiple values of %s found in rootdse!\n",
+ opts->gen_map[SDAP_AT_LAST_USN].opt_name));
+ break;
+ default:
+ DEBUG(1, ("Unkown error (%d) checking rootdse!\n", ret));
+ }
+ } else {
+ const char *entry_usn_name;
+ entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name;
+ if (!entry_usn_name) {
+ DEBUG(1, ("%s found in rootdse but %s is not set!\n",
+ last_usn_name,
+ opts->gen_map[SDAP_AT_ENTRY_USN].opt_name));
+ } else {
+ so->supports_usn = true;
+ }
+ }
+ } else {
+ /* no usn option configure, let's try to autodetect. */
+ for (i = 0; usn_attrs[i].last_name; i++) {
+ ret = sysdb_attrs_get_string(rootdse,
+ usn_attrs[i].last_name,
+ &last_usn_value);
+ if (ret == EOK) {
+ /* Fixate discovered configuration */
+ opts->gen_map[SDAP_AT_LAST_USN].name =
+ talloc_strdup(opts->gen_map, usn_attrs[i].last_name);
+ opts->gen_map[SDAP_AT_ENTRY_USN].name =
+ talloc_strdup(opts->gen_map, usn_attrs[i].entry_name);
+ so->supports_usn = true;
+ last_usn_name = usn_attrs[i].last_name;
+ break;
+ }
+ }
+ }
+
+ if (!last_usn_name) {
+ DEBUG(5, ("No known USN scheme is supported by this server\n!"));
+ }
+
+ *srv_opts = so;
+ return EOK;
+}
+
int build_attrs_from_map(TALLOC_CTX *memctx,
struct sdap_attr_map *map,
size_t size, const char ***_attrs)
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 5c4f4a54..68242f1a 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -130,6 +130,11 @@ struct sdap_ppolicy_data {
#define SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS "namingContexts"
#define SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT "defaultNamingContext"
+#define SDAP_IPA_USN "entryUSN"
+#define SDAP_IPA_LAST_USN "lastUSN"
+#define SDAP_AD_USN "uSNChanged"
+#define SDAP_AD_LAST_USN "highestCommittedUSN"
+
enum sdap_result {
SDAP_SUCCESS,
SDAP_NOT_FOUND,
@@ -280,6 +285,13 @@ struct sdap_options {
struct ldb_dn *groups_base;
};
+struct sdap_server_opts {
+ char *server_id;
+ bool supports_usn;
+ char *max_user_value;
+ char *max_group_value;
+};
+
int sdap_get_map(TALLOC_CTX *memctx,
struct confdb_ctx *cdb,
const char *conf_path,
@@ -328,4 +340,9 @@ int sdap_control_create(struct sdap_handle *sh, const char *oid, int iscritical,
errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
struct sdap_handle *sh,
struct sdap_options *opts);
+int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
+ const char *server,
+ struct sysdb_attrs *rootdse,
+ struct sdap_options *opts,
+ struct sdap_server_opts **srv_opts);
#endif /* _SDAP_H_ */
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 6808ceaa..6929b293 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -655,6 +655,7 @@ struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx,
"supportedLDAPVersion",
"supportedSASLMechanisms",
SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT,
+ SDAP_IPA_LAST_USN, SDAP_AD_LAST_USN,
NULL
};
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index bf54bbd1..10d0c307 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -129,11 +129,9 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
bool skip_rootdse);
int sdap_cli_connect_recv(struct tevent_req *req,
TALLOC_CTX *memctx,
- struct sdap_handle **gsh);
-int sdap_cli_connect_recv_ext(struct tevent_req *req,
- TALLOC_CTX *memctx,
bool *can_retry,
- struct sdap_handle **gsh);
+ struct sdap_handle **gsh,
+ struct sdap_server_opts **srv_opts);
struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index f143a013..2ad9639d 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1063,6 +1063,8 @@ struct sdap_cli_connect_state {
struct sdap_handle *sh;
struct fo_server *srv;
+
+ struct sdap_server_opts *srv_opts;
};
static int sdap_cli_resolve_next(struct tevent_req *req);
@@ -1094,6 +1096,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
state->service = service;
state->be = be;
state->srv = NULL;
+ state->srv_opts = NULL;
state->be = be;
state->use_rootdse = !skip_rootdse;
@@ -1286,6 +1289,15 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq)
return;
}
+ ret = sdap_get_server_opts_from_rootdse(state,
+ state->service->uri, rootdse,
+ state->opts, &state->srv_opts);
+ if (ret) {
+ DEBUG(1, ("sdap_get_server_opts_from_rootdse failed.\n"));
+ tevent_req_error(req, ret);
+ return;
+ }
+
sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
if (sasl_mech && state->use_rootdse) {
@@ -1416,15 +1428,9 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
int sdap_cli_connect_recv(struct tevent_req *req,
TALLOC_CTX *memctx,
- struct sdap_handle **gsh)
-{
- return sdap_cli_connect_recv_ext(req, memctx, NULL, gsh);
-}
-
-int sdap_cli_connect_recv_ext(struct tevent_req *req,
- TALLOC_CTX *memctx,
- bool *can_retry,
- struct sdap_handle **gsh)
+ bool *can_retry,
+ struct sdap_handle **gsh,
+ struct sdap_server_opts **srv_opts)
{
struct sdap_cli_connect_state *state = tevent_req_data(req,
struct sdap_cli_connect_state);
@@ -1464,6 +1470,10 @@ int sdap_cli_connect_recv_ext(struct tevent_req *req,
talloc_zfree(state->sh);
}
+ if (srv_opts) {
+ *srv_opts = talloc_steal(memctx, state->srv_opts);
+ }
+
return EOK;
}
diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c
index a79c64b9..c4194efb 100644
--- a/src/providers/ldap/sdap_id_op.c
+++ b/src/providers/ldap/sdap_id_op.c
@@ -494,15 +494,16 @@ done:
/* Subrequest callback for connection completion */
static void sdap_id_op_connect_done(struct tevent_req *subreq)
{
- struct sdap_id_conn_data *conn_data = tevent_req_callback_data(subreq,
- struct sdap_id_conn_data);
+ struct sdap_id_conn_data *conn_data =
+ tevent_req_callback_data(subreq, struct sdap_id_conn_data);
struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache;
+ struct sdap_server_opts *srv_opts;
bool can_retry = false;
bool is_offline = false;
int ret;
- ret = sdap_cli_connect_recv_ext(subreq, conn_data, &can_retry,
- &conn_data->sh);
+ ret = sdap_cli_connect_recv(subreq, conn_data, &can_retry,
+ &conn_data->sh, &srv_opts);
conn_data->connect_req = NULL;
talloc_zfree(subreq);