>From 577cd6488530002836f15b43f562938632d0f2ff Mon Sep 17 00:00:00 2001
From: Simo Sorce <ssorce@redhat.com>
Date: Thu, 8 Oct 2009 16:50:07 -0400
Subject: [PATCH 1/3] Make options parser available to all providers

---
 server/Makefile.am                    |    1 +
 server/providers/data_provider.h      |   58 ++++++++
 server/providers/data_provider_opts.c |  209 +++++++++++++++++++++++++++
 server/providers/ldap/ldap_auth.c     |   15 +-
 server/providers/ldap/ldap_id.c       |   36 +++---
 server/providers/ldap/sdap.c          |  255 +++++++--------------------------
 server/providers/ldap/sdap.h          |   50 +------
 server/providers/ldap/sdap_async.c    |   34 +++---
 server/providers/ldap/sdap_async.h    |    2 +-
 9 files changed, 366 insertions(+), 294 deletions(-)
 create mode 100644 server/providers/data_provider_opts.c

diff --git a/server/Makefile.am b/server/Makefile.am
index a65c9fa..f2b2378 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -294,6 +294,7 @@ sssd_pam_LDADD = \
 
 sssd_be_SOURCES = \
     providers/data_provider_be.c \
+    providers/data_provider_opts.c \
     $(SSSD_UTIL_OBJ)
 sssd_be_LDADD = $(SSSD_LIBS)
 sssd_be_LDFLAGS = \
diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h
index cfb2ec9..7653f07 100644
--- a/server/providers/data_provider.h
+++ b/server/providers/data_provider.h
@@ -138,4 +138,62 @@ int dp_get_sbus_address(TALLOC_CTX *mem_ctx,
                         char **address, const char *domain_name);
 
 
+/* Helpers */
+
+#define NULL_STRING { .string = NULL }
+#define NULL_BLOB { .blob = { NULL, 0 } }
+#define NULL_NUMBER { .number = 0 }
+#define BOOL_FALSE { .boolean = false }
+#define BOOL_TRUE { .boolean = true }
+
+enum dp_opt_type {
+    DP_OPT_STRING,
+    DP_OPT_BLOB,
+    DP_OPT_NUMBER,
+    DP_OPT_BOOL
+};
+
+struct dp_opt_blob {
+    uint8_t *data;
+    size_t length;
+};
+
+union dp_opt_value {
+    const char *cstring;
+    char *string;
+    struct dp_opt_blob blob;
+    int number;
+    bool boolean;
+};
+
+struct dp_option {
+    const char *opt_name;
+    enum dp_opt_type type;
+    union dp_opt_value def_val;
+    union dp_opt_value val;
+};
+
+int dp_get_options(TALLOC_CTX *memctx,
+                   struct confdb_ctx *cdb,
+                   const char *conf_path,
+                   struct dp_option *def_opts,
+                   int num_opts,
+                   struct dp_option **_opts);
+
+const char *_dp_opt_get_cstring(struct dp_option *opts,
+                                    int id, const char *location);
+char *_dp_opt_get_string(struct dp_option *opts,
+                                    int id, const char *location);
+struct dp_opt_blob _dp_opt_get_blob(struct dp_option *opts,
+                                    int id, const char *location);
+int _dp_opt_get_int(struct dp_option *opts,
+                                    int id, const char *location);
+bool _dp_opt_get_bool(struct dp_option *opts,
+                                    int id, const char *location);
+#define dp_opt_get_cstring(o, i) _dp_opt_get_cstring(o, i, __FUNCTION__)
+#define dp_opt_get_string(o, i) _dp_opt_get_string(o, i, __FUNCTION__)
+#define dp_opt_get_blob(o, i) _dp_opt_get_blob(o, i, __FUNCTION__)
+#define dp_opt_get_int(o, i) _dp_opt_get_int(o, i, __FUNCTION__)
+#define dp_opt_get_bool(o, i) _dp_opt_get_bool(o, i, __FUNCTION__)
+
 #endif /* __DATA_PROVIDER_ */
diff --git a/server/providers/data_provider_opts.c b/server/providers/data_provider_opts.c
new file mode 100644
index 0000000..581b928
--- /dev/null
+++ b/server/providers/data_provider_opts.c
@@ -0,0 +1,209 @@
+/*
+    SSSD
+
+    Data Provider Helpers
+
+    Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "data_provider.h"
+
+/* =Retrieve-Options====================================================== */
+
+int dp_get_options(TALLOC_CTX *memctx,
+                   struct confdb_ctx *cdb,
+                   const char *conf_path,
+                   struct dp_option *def_opts,
+                   int num_opts,
+                   struct dp_option **_opts)
+{
+    struct dp_option *opts;
+    int i, ret;
+
+    opts = talloc_array(memctx, struct dp_option, num_opts);
+    if (!opts) return ENOMEM;
+
+    for (i = 0; i < num_opts; i++) {
+        char *tmp;
+
+        opts[i].opt_name = def_opts[i].opt_name;
+        opts[i].type = def_opts[i].type;
+        opts[i].def_val = def_opts[i].def_val;
+        ret = EOK;
+
+        switch (def_opts[i].type) {
+        case DP_OPT_STRING:
+            ret = confdb_get_string(cdb, opts, conf_path,
+                                    opts[i].opt_name,
+                                    opts[i].def_val.cstring,
+                                    &opts[i].val.string);
+            if (ret != EOK ||
+                ((opts[i].def_val.string != NULL) &&
+                 (opts[i].val.string == NULL))) {
+                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
+                          opts[i].opt_name));
+                if (ret == EOK) ret = EINVAL;
+                goto done;
+            }
+            DEBUG(6, ("Option %s has value %s\n",
+                  opts[i].opt_name, opts[i].val.cstring));
+            break;
+
+        case DP_OPT_BLOB:
+            ret = confdb_get_string(cdb, opts, conf_path,
+                                    opts[i].opt_name,
+                                    NULL, &tmp);
+            if (ret != EOK) {
+                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
+                          opts[i].opt_name));
+                goto done;
+            }
+
+            if (tmp) {
+                opts[i].val.blob.data = (uint8_t *)tmp;
+                opts[i].val.blob.length = strlen(tmp);
+            } else {
+                opts[i].val.blob.data = NULL;
+                opts[i].val.blob.length = 0;
+            }
+
+            DEBUG(6, ("Option %s has %s value\n",
+                      opts[i].opt_name,
+                      opts[i].val.blob.length?"a":"no"));
+            break;
+
+        case DP_OPT_NUMBER:
+            ret = confdb_get_int(cdb, opts, conf_path,
+                                 opts[i].opt_name,
+                                 opts[i].def_val.number,
+                                 &opts[i].val.number);
+            if (ret != EOK) {
+                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
+                          opts[i].opt_name));
+                goto done;
+            }
+            DEBUG(6, ("Option %s has value %d\n",
+                  opts[i].opt_name, opts[i].val.number));
+            break;
+
+        case DP_OPT_BOOL:
+            ret = confdb_get_bool(cdb, opts, conf_path,
+                                  opts[i].opt_name,
+                                  opts[i].def_val.boolean,
+                                  &opts[i].val.boolean);
+            if (ret != EOK) {
+                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
+                          opts[i].opt_name));
+                goto done;
+            }
+            DEBUG(6, ("Option %s is %s\n",
+                      opts[i].opt_name,
+                      opts[i].val.boolean?"TRUE":"FALSE"));
+            break;
+        }
+    }
+
+    ret = EOK;
+    *_opts = opts;
+
+done:
+    if (ret != EOK) talloc_zfree(opts);
+    return ret;
+}
+
+/* =Basic-Option-Helpers================================================== */
+
+static const char *dp_opt_type_to_string(enum dp_opt_type type)
+{
+    switch (type) {
+    case DP_OPT_STRING:
+        return "String";
+    case DP_OPT_BLOB:
+        return "Blob";
+    case DP_OPT_NUMBER:
+        return "Number";
+    case DP_OPT_BOOL:
+        return "Boolean";
+    }
+    return NULL;
+}
+
+const char *_dp_opt_get_cstring(struct dp_option *opts,
+                                int id, const char *location)
+{
+    if (opts[id].type != DP_OPT_STRING) {
+        DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
+                  " but value is of type '%s'!\n",
+                  location, opts[id].opt_name,
+                  dp_opt_type_to_string(opts[id].type)));
+        return NULL;
+    }
+    return opts[id].val.cstring;
+}
+
+char *_dp_opt_get_string(struct dp_option *opts,
+                         int id, const char *location)
+{
+    if (opts[id].type != DP_OPT_STRING) {
+        DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
+                  " but value is of type '%s'!\n",
+                  location, opts[id].opt_name,
+                  dp_opt_type_to_string(opts[id].type)));
+        return NULL;
+    }
+    return opts[id].val.string;
+}
+
+struct dp_opt_blob _dp_opt_get_blob(struct dp_option *opts,
+                                  int id, const char *location)
+{
+    struct dp_opt_blob null_blob = { NULL, 0 };
+    if (opts[id].type != DP_OPT_BLOB) {
+        DEBUG(0, ("[%s] Requested type 'Blob' for option '%s'"
+                  " but value is of type '%s'!\n",
+                  location, opts[id].opt_name,
+                  dp_opt_type_to_string(opts[id].type)));
+        return null_blob;
+    }
+    return opts[id].val.blob;
+}
+
+int _dp_opt_get_int(struct dp_option *opts,
+                    int id, const char *location)
+{
+    if (opts[id].type != DP_OPT_NUMBER) {
+        DEBUG(0, ("[%s] Requested type 'Number' for option '%s'"
+                  " but value is of type '%s'!\n",
+                  location, opts[id].opt_name,
+                  dp_opt_type_to_string(opts[id].type)));
+        return 0;
+    }
+    return opts[id].val.number;
+}
+
+bool _dp_opt_get_bool(struct dp_option *opts,
+                      int id, const char *location)
+{
+    if (opts[id].type != DP_OPT_BOOL) {
+        DEBUG(0, ("[%s] Requested type 'Boolean' for option '%s'"
+                  " but value is of type '%s'!\n",
+                  location, opts[id].opt_name,
+                  dp_opt_type_to_string(opts[id].type)));
+        return false;
+    }
+    return opts[id].val.boolean;
+}
+
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 487fb07..ae582e5 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -126,8 +126,8 @@ static void get_user_dn_done(void *pvt, int err, struct ldb_result *res)
             dn = talloc_asprintf(state, "%s=%s,%s",
                         state->ctx->opts->user_map[SDAP_AT_USER_NAME].name,
                         state->name,
-                        sdap_go_get_string(state->ctx->opts->basic,
-                                           SDAP_USER_SEARCH_BASE));
+                        dp_opt_get_string(state->ctx->opts->basic,
+                                          SDAP_USER_SEARCH_BASE));
             if (!dn) {
                 tevent_req_error(req, ENOMEM);
                 break;
@@ -174,7 +174,7 @@ struct auth_state {
     struct tevent_context *ev;
     struct sdap_auth_ctx *ctx;
     const char *username;
-    struct sdap_blob password;
+    struct dp_opt_blob password;
 
     struct sdap_handle *sh;
 
@@ -190,7 +190,7 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
                                     struct tevent_context *ev,
                                     struct sdap_auth_ctx *ctx,
                                     const char *username,
-                                    struct sdap_blob password)
+                                    struct dp_opt_blob password)
 {
     struct tevent_req *req, *subreq;
     struct auth_state *state;
@@ -335,7 +335,7 @@ static void sdap_pam_chpass_send(struct be_req *breq)
     struct sdap_auth_ctx *ctx;
     struct tevent_req *subreq;
     struct pam_data *pd;
-    struct sdap_blob authtok;
+    struct dp_opt_blob authtok;
 
     ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
                           struct sdap_auth_ctx);
@@ -460,7 +460,7 @@ struct sdap_pam_auth_state {
     struct be_req *breq;
     struct pam_data *pd;
     const char *username;
-    struct sdap_blob password;
+    struct dp_opt_blob password;
 };
 
 static void sdap_pam_auth_done(struct tevent_req *req);
@@ -475,7 +475,8 @@ static void sdap_pam_auth_send(struct be_req *breq)
     struct tevent_req *subreq;
     struct pam_data *pd;
 
-    ctx = talloc_get_type(breq->be_ctx->bet_info[BET_AUTH].pvt_bet_data, struct sdap_auth_ctx);
+    ctx = talloc_get_type(breq->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
+                          struct sdap_auth_ctx);
     pd = talloc_get_type(breq->req_data, struct pam_data);
 
     if (be_is_offline(ctx->be)) {
diff --git a/server/providers/ldap/ldap_id.c b/server/providers/ldap/ldap_id.c
index 271eaea..2218eee 100644
--- a/server/providers/ldap/ldap_id.c
+++ b/server/providers/ldap/ldap_id.c
@@ -117,7 +117,7 @@ static struct tevent_req *sdap_id_connect_send(TALLOC_CTX *memctx,
     state->ctx = ctx;
 
     subreq = sdap_connect_send(state, ev, ctx->opts,
-                               sdap_go_get_bool(ctx->opts->basic, SDAP_ID_TLS));
+                               dp_opt_get_bool(ctx->opts->basic, SDAP_ID_TLS));
     if (!subreq) {
         talloc_zfree(req);
         return NULL;
@@ -143,15 +143,15 @@ static void sdap_id_connect_done(struct tevent_req *subreq)
         return;
     }
 
-    sasl_mech = sdap_go_get_string(state->ctx->opts->basic, SDAP_SASL_MECH);
+    sasl_mech = dp_opt_get_string(state->ctx->opts->basic, SDAP_SASL_MECH);
     if (sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
-        if (sdap_go_get_bool(state->ctx->opts->basic, SDAP_KRB5_KINIT)) {
+        if (dp_opt_get_bool(state->ctx->opts->basic, SDAP_KRB5_KINIT)) {
             subreq = sdap_kinit_send(state, state->ev, state->sh,
-                                sdap_go_get_string(state->ctx->opts->basic,
+                                dp_opt_get_string(state->ctx->opts->basic,
                                                            SDAP_KRB5_KEYTAB),
-                                sdap_go_get_string(state->ctx->opts->basic,
+                                dp_opt_get_string(state->ctx->opts->basic,
                                                            SDAP_SASL_AUTHID),
-                                sdap_go_get_string(state->ctx->opts->basic,
+                                dp_opt_get_string(state->ctx->opts->basic,
                                                            SDAP_KRB5_REALM));
             if (!subreq) {
                 tevent_req_error(req, ENOMEM);
@@ -166,13 +166,13 @@ static void sdap_id_connect_done(struct tevent_req *subreq)
                             state->ev,
                             state->sh,
                             sasl_mech,
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                         SDAP_SASL_AUTHID),
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                     SDAP_DEFAULT_BIND_DN),
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                SDAP_DEFAULT_AUTHTOK_TYPE),
-                            sdap_go_get_blob(state->ctx->opts->basic,
+                            dp_opt_get_blob(state->ctx->opts->basic,
                                                     SDAP_DEFAULT_AUTHTOK));
     if (!subreq) {
         tevent_req_error(req, ENOMEM);
@@ -204,15 +204,15 @@ static void sdap_id_kinit_done(struct tevent_req *subreq)
     subreq = sdap_auth_send(state,
                             state->ev,
                             state->sh,
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                           SDAP_SASL_MECH),
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                         SDAP_SASL_AUTHID),
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                     SDAP_DEFAULT_BIND_DN),
-                            sdap_go_get_string(state->ctx->opts->basic,
+                            dp_opt_get_string(state->ctx->opts->basic,
                                                SDAP_DEFAULT_AUTHTOK_TYPE),
-                            sdap_go_get_blob(state->ctx->opts->basic,
+                            dp_opt_get_blob(state->ctx->opts->basic,
                                                     SDAP_DEFAULT_AUTHTOK));
     if (!subreq) {
         tevent_req_error(req, ENOMEM);
@@ -861,7 +861,7 @@ static void ldap_id_enumerate(struct tevent_context *ev,
     /* if enumeration takes so long, either we try to enumerate too
      * frequently, or something went seriously wrong */
     tv = tevent_timeval_current();
-    ert = sdap_go_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
+    ert = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
     tv = tevent_timeval_add(&tv, ert, 0);
     timeout = tevent_add_timer(ctx->be->ev, req, tv,
                                ldap_id_enumerate_timeout, req);
@@ -877,7 +877,7 @@ static void ldap_id_enumerate_timeout(struct tevent_context *ev,
                                                        struct sdap_id_ctx);
     int ert;
 
-    ert = sdap_go_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
+    ert = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
     DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", ert));
     ldap_id_enumerate_set_timer(ctx, tevent_timeval_current());
 
@@ -909,7 +909,7 @@ static void ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx,
     struct tevent_timer *enum_task;
     int ert;
 
-    ert = sdap_go_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
+    ert = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
     tv = tevent_timeval_add(&tv, ert, 0);
     enum_task = tevent_add_timer(ctx->be->ev, ctx, tv, ldap_id_enumerate, ctx);
     if (!enum_task) {
diff --git a/server/providers/ldap/sdap.c b/server/providers/ldap/sdap.c
index 47f76f9..b6edb94 100644
--- a/server/providers/ldap/sdap.c
+++ b/server/providers/ldap/sdap.c
@@ -31,35 +31,35 @@
 #define BOOL_FALSE { .boolean = false }
 #define BOOL_TRUE { .boolean = true }
 
-struct sdap_gen_opts default_basic_opts[] = {
-    { "ldap_uri", SDAP_STRING, { "ldap://localhost" }, NULL_STRING },
-    { "ldap_default_bind_dn", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_default_authtok_type", SDAP_STRING, NULL_STRING, NULL_STRING},
-    { "ldap_default_authtok", SDAP_BLOB, NULL_BLOB, NULL_BLOB },
-    { "ldap_search_timeout", SDAP_NUMBER, { .number = 60 }, NULL_NUMBER },
-    { "ldap_network_timeout", SDAP_NUMBER, { .number = 6 }, NULL_NUMBER },
-    { "ldap_opt_timeout", SDAP_NUMBER, { .number = 6 }, NULL_NUMBER },
-    { "ldap_tls_reqcert", SDAP_STRING, { "hard" }, NULL_STRING },
-    { "ldap_user_search_base", SDAP_STRING, { "ou=People,dc=example,dc=com" }, NULL_STRING },
-    { "ldap_user_search_scope", SDAP_STRING, { "sub" }, NULL_STRING },
-    { "ldap_user_search_filter", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_group_search_base", SDAP_STRING, { "ou=Group,dc=example,dc=com" }, NULL_STRING },
-    { "ldap_group_search_scope", SDAP_STRING, { "sub" }, NULL_STRING },
-    { "ldap_group_search_filter", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_schema", SDAP_STRING, { "rfc2307" }, NULL_STRING },
-    { "ldap_offline_timeout", SDAP_NUMBER, { .number = 60 }, NULL_NUMBER },
-    { "ldap_force_upper_case_realm", SDAP_BOOL, BOOL_FALSE, BOOL_FALSE },
-    { "ldap_enumeration_refresh_timeout", SDAP_NUMBER, { .number = 300 }, NULL_NUMBER },
-    { "ldap_stale_time", SDAP_NUMBER, { .number = 1800 }, NULL_NUMBER },
-    { "ldap_tls_cacert", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_tls_cacertdir", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_id_use_start_tls", SDAP_BOOL, BOOL_FALSE, BOOL_FALSE },
-    { "ldap_sasl_mech", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_sasl_authid", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_krb5_keytab", SDAP_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_krb5_init_creds", SDAP_BOOL, BOOL_TRUE, BOOL_TRUE },
+struct dp_option default_basic_opts[] = {
+    { "ldap_uri", DP_OPT_STRING, { "ldap://localhost" }, NULL_STRING },
+    { "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_default_authtok_type", DP_OPT_STRING, NULL_STRING, NULL_STRING},
+    { "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB },
+    { "ldap_search_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER },
+    { "ldap_network_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
+    { "ldap_opt_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
+    { "ldap_tls_reqcert", DP_OPT_STRING, { "hard" }, NULL_STRING },
+    { "ldap_user_search_base", DP_OPT_STRING, { "ou=People,dc=example,dc=com" }, NULL_STRING },
+    { "ldap_user_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
+    { "ldap_user_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_group_search_base", DP_OPT_STRING, { "ou=Group,dc=example,dc=com" }, NULL_STRING },
+    { "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
+    { "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_schema", DP_OPT_STRING, { "rfc2307" }, NULL_STRING },
+    { "ldap_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER },
+    { "ldap_force_upper_case_realm", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+    { "ldap_enumeration_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER },
+    { "ldap_stale_time", DP_OPT_NUMBER, { .number = 1800 }, NULL_NUMBER },
+    { "ldap_tls_cacert", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_tls_cacertdir", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_id_use_start_tls", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+    { "ldap_sasl_mech", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
-    { "krb5_realm", SDAP_STRING, NULL_STRING, NULL_STRING }
+    { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING }
 };
 
 struct sdap_id_map rfc2307_user_map[] = {
@@ -132,97 +132,16 @@ int sdap_get_options(TALLOC_CTX *memctx,
     opts = talloc_zero(memctx, struct sdap_options);
     if (!opts) return ENOMEM;
 
-    opts->basic = talloc_array(opts, struct sdap_gen_opts, SDAP_OPTS_BASIC);
-    if (!opts) return ENOMEM;
-
-    opts->user_map = talloc_array(opts, struct sdap_id_map, SDAP_OPTS_USER);
-    if (!opts) return ENOMEM;
-
-    opts->group_map = talloc_array(opts, struct sdap_id_map, SDAP_OPTS_GROUP);
-    if (!opts) return ENOMEM;
-
-    for (i = 0; i < SDAP_OPTS_BASIC; i++) {
-        char *tmp;
-
-        opts->basic[i].opt_name = default_basic_opts[i].opt_name;
-        opts->basic[i].type = default_basic_opts[i].type;
-        opts->basic[i].def_val = default_basic_opts[i].def_val;
-        ret = EOK;
-
-        switch (default_basic_opts[i].type) {
-        case SDAP_STRING:
-            ret = confdb_get_string(cdb, opts, conf_path,
-                                    opts->basic[i].opt_name,
-                                    opts->basic[i].def_val.cstring,
-                                    &opts->basic[i].val.string);
-            if (ret != EOK ||
-                ((opts->basic[i].def_val.string != NULL) &&
-                 (opts->basic[i].val.string == NULL))) {
-                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
-                          opts->basic[i].opt_name));
-                if (ret == EOK) ret = EINVAL;
-                goto done;
-            }
-            DEBUG(6, ("Option %s has value %s\n",
-                  opts->basic[i].opt_name, opts->basic[i].val.cstring));
-            break;
-
-        case SDAP_BLOB:
-            ret = confdb_get_string(cdb, opts, conf_path,
-                                    opts->basic[i].opt_name,
-                                    NULL, &tmp);
-            if (ret != EOK) {
-                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
-                          opts->basic[i].opt_name));
-                goto done;
-            }
-
-            if (tmp) {
-                opts->basic[i].val.blob.data = (uint8_t *)tmp;
-                opts->basic[i].val.blob.length = strlen(tmp);
-            } else {
-                opts->basic[i].val.blob.data = NULL;
-                opts->basic[i].val.blob.length = 0;
-            }
-
-            DEBUG(6, ("Option %s has %s value\n",
-                      opts->basic[i].opt_name,
-                      opts->basic[i].val.blob.length?"a":"no"));
-            break;
-
-        case SDAP_NUMBER:
-            ret = confdb_get_int(cdb, opts, conf_path,
-                                 opts->basic[i].opt_name,
-                                 opts->basic[i].def_val.number,
-                                 &opts->basic[i].val.number);
-            if (ret != EOK) {
-                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
-                          opts->basic[i].opt_name));
-                goto done;
-            }
-            DEBUG(6, ("Option %s has value %d\n",
-                  opts->basic[i].opt_name, opts->basic[i].val.number));
-            break;
-
-        case SDAP_BOOL:
-            ret = confdb_get_bool(cdb, opts, conf_path,
-                                  opts->basic[i].opt_name,
-                                  opts->basic[i].def_val.boolean,
-                                  &opts->basic[i].val.boolean);
-            if (ret != EOK) {
-                DEBUG(0, ("Failed to retrieve value for option (%s)\n",
-                          opts->basic[i].opt_name));
-                goto done;
-            }
-            DEBUG(6, ("Option %s is %s\n",
-                      opts->basic[i].opt_name,
-                      opts->basic[i].val.boolean?"TRUE":"FALSE"));
-            break;
-        }
+    ret = dp_get_options(opts, cdb, conf_path,
+                         default_basic_opts,
+                         SDAP_OPTS_BASIC,
+                         &opts->basic);
+    if (ret != EOK) {
+        goto done;
     }
 
     /* schema type */
-    schema = sdap_go_get_string(opts->basic, SDAP_SCHEMA);
+    schema = dp_opt_get_string(opts->basic, SDAP_SCHEMA);
     if (strcasecmp(schema, "rfc2307") == 0) {
         opts->schema_type = SDAP_SCHEMA_RFC2307;
         default_user_map = rfc2307_user_map;
@@ -238,6 +157,12 @@ int sdap_get_options(TALLOC_CTX *memctx,
         goto done;
     }
 
+    opts->user_map = talloc_array(opts, struct sdap_id_map, SDAP_OPTS_USER);
+    if (!opts->user_map) {
+        ret = ENOMEM;
+        goto done;
+    }
+
     for (i = 0; i < SDAP_OPTS_USER; i++) {
 
         opts->user_map[i].opt_name = default_user_map[i].opt_name;
@@ -260,6 +185,12 @@ int sdap_get_options(TALLOC_CTX *memctx,
                   opts->user_map[i].opt_name, opts->user_map[i].name));
     }
 
+    opts->group_map = talloc_array(opts, struct sdap_id_map, SDAP_OPTS_GROUP);
+    if (!opts->group_map) {
+        ret = ENOMEM;
+        goto done;
+    }
+
     for (i = 0; i < SDAP_OPTS_GROUP; i++) {
 
         opts->group_map[i].opt_name = default_group_map[i].opt_name;
@@ -290,90 +221,6 @@ done:
     return ret;
 }
 
-/* =Basic-Option-Helpers================================================== */
-
-static const char *sdap_type_to_string(enum sdap_type type)
-{
-    switch (type) {
-    case SDAP_STRING:
-        return "String";
-    case SDAP_BLOB:
-        return "Blob";
-    case SDAP_NUMBER:
-        return "Number";
-    case SDAP_BOOL:
-        return "Boolean";
-    }
-    return NULL;
-}
-
-const char *_sdap_go_get_cstring(struct sdap_gen_opts *opts,
-                                 int id, const char *location)
-{
-    if (opts[id].type != SDAP_STRING) {
-        DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
-                  " but value is of type '%s'!\n",
-                  location, opts[id].opt_name,
-                  sdap_type_to_string(opts[id].type)));
-        return NULL;
-    }
-    return opts[id].val.cstring;
-}
-
-char *_sdap_go_get_string(struct sdap_gen_opts *opts,
-                          int id, const char *location)
-{
-    if (opts[id].type != SDAP_STRING) {
-        DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
-                  " but value is of type '%s'!\n",
-                  location, opts[id].opt_name,
-                  sdap_type_to_string(opts[id].type)));
-        return NULL;
-    }
-    return opts[id].val.string;
-}
-
-struct sdap_blob _sdap_go_get_blob(struct sdap_gen_opts *opts,
-                                   int id, const char *location)
-{
-    struct sdap_blob null_blob = { NULL, 0 };
-    if (opts[id].type != SDAP_BLOB) {
-        DEBUG(0, ("[%s] Requested type 'Blob' for option '%s'"
-                  " but value is of type '%s'!\n",
-                  location, opts[id].opt_name,
-                  sdap_type_to_string(opts[id].type)));
-        return null_blob;
-    }
-    return opts[id].val.blob;
-}
-
-int _sdap_go_get_int(struct sdap_gen_opts *opts,
-                     int id, const char *location)
-{
-    if (opts[id].type != SDAP_NUMBER) {
-        DEBUG(0, ("[%s] Requested type 'Number' for option '%s'"
-                  " but value is of type '%s'!\n",
-                  location, opts[id].opt_name,
-                  sdap_type_to_string(opts[id].type)));
-        return 0;
-    }
-    return opts[id].val.number;
-}
-
-bool _sdap_go_get_bool(struct sdap_gen_opts *opts,
-                       int id, const char *location)
-{
-    if (opts[id].type != SDAP_BOOL) {
-        DEBUG(0, ("[%s] Requested type 'Boolean' for option '%s'"
-                  " but value is of type '%s'!\n",
-                  location, opts[id].opt_name,
-                  sdap_type_to_string(opts[id].type)));
-        return false;
-    }
-    return opts[id].val.boolean;
-}
-
-
 /* =Parse-msg============================================================= */
 
 static int sdap_parse_entry(TALLOC_CTX *memctx,
@@ -553,12 +400,12 @@ int sdap_get_msg_dn(TALLOC_CTX *memctx, struct sdap_handle *sh,
     return EOK;
 }
 
-errno_t setup_tls_config(struct sdap_gen_opts *basic_opts)
+errno_t setup_tls_config(struct dp_option *basic_opts)
 {
     int ret;
     int ldap_opt_x_tls_require_cert;
     const char *tls_opt;
-    tls_opt = sdap_go_get_string(basic_opts, SDAP_TLS_REQCERT);
+    tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_REQCERT);
     if (tls_opt) {
         if (strcasecmp(tls_opt, "never") == 0) {
             ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_NEVER;
@@ -589,7 +436,7 @@ errno_t setup_tls_config(struct sdap_gen_opts *basic_opts)
         }
     }
 
-    tls_opt = sdap_go_get_string(basic_opts, SDAP_TLS_CACERT);
+    tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CACERT);
     if (tls_opt) {
         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, tls_opt);
         if (ret != LDAP_OPT_SUCCESS) {
@@ -598,7 +445,7 @@ errno_t setup_tls_config(struct sdap_gen_opts *basic_opts)
         }
     }
 
-    tls_opt = sdap_go_get_string(basic_opts, SDAP_TLS_CACERTDIR);
+    tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CACERTDIR);
     if (tls_opt) {
         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, tls_opt);
         if (ret != LDAP_OPT_SUCCESS) {
diff --git a/server/providers/ldap/sdap.h b/server/providers/ldap/sdap.h
index 3aa29a3..49e9e74 100644
--- a/server/providers/ldap/sdap.h
+++ b/server/providers/ldap/sdap.h
@@ -19,8 +19,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "confdb/confdb.h"
-#include "db/sysdb.h"
+#include "providers/dp_backend.h"
 #include <ldap.h>
 
 struct sdap_msg {
@@ -136,33 +135,6 @@ enum sdap_group_opt {
     SDAP_OPTS_GROUP /* attrs counter */
 };
 
-enum sdap_type {
-    SDAP_STRING,
-    SDAP_BLOB,
-    SDAP_NUMBER,
-    SDAP_BOOL
-};
-
-struct sdap_blob {
-    uint8_t *data;
-    size_t length;
-};
-
-union sdap_value {
-    const char *cstring;
-    char *string;
-    struct sdap_blob blob;
-    int number;
-    bool boolean;
-};
-
-struct sdap_gen_opts {
-    const char *opt_name;
-    enum sdap_type type;
-    union sdap_value def_val;
-    union sdap_value val;
-};
-
 struct sdap_id_map {
     const char *opt_name;
     const char *def_name;
@@ -171,7 +143,7 @@ struct sdap_id_map {
 };
 
 struct sdap_options {
-    struct sdap_gen_opts *basic;
+    struct dp_option *basic;
     struct sdap_id_map *user_map;
     struct sdap_id_map *group_map;
 
@@ -191,22 +163,6 @@ int sdap_get_options(TALLOC_CTX *memctx,
                      const char *conf_path,
                      struct sdap_options **_opts);
 
-const char *_sdap_go_get_cstring(struct sdap_gen_opts *opts,
-                                 int id, const char *location);
-char *_sdap_go_get_string(struct sdap_gen_opts *opts,
-                          int id, const char *location);
-struct sdap_blob _sdap_go_get_blob(struct sdap_gen_opts *opts,
-                                   int id, const char *location);
-int _sdap_go_get_int(struct sdap_gen_opts *opts,
-                     int id, const char *location);
-bool _sdap_go_get_bool(struct sdap_gen_opts *opts,
-                       int id, const char *location);
-#define sdap_go_get_cstring(o, i) _sdap_go_get_cstring(o, i, __FUNCTION__)
-#define sdap_go_get_string(o, i) _sdap_go_get_string(o, i, __FUNCTION__)
-#define sdap_go_get_blob(o, i) _sdap_go_get_blob(o, i, __FUNCTION__)
-#define sdap_go_get_int(o, i) _sdap_go_get_int(o, i, __FUNCTION__)
-#define sdap_go_get_bool(o, i) _sdap_go_get_bool(o, i, __FUNCTION__)
-
 int sdap_parse_user(TALLOC_CTX *memctx, struct sdap_options *opts,
                     struct sdap_handle *sh, struct sdap_msg *sm,
                     struct sysdb_attrs **_attrs, char **_dn);
@@ -218,4 +174,4 @@ int sdap_parse_group(TALLOC_CTX *memctx, struct sdap_options *opts,
 int sdap_get_msg_dn(TALLOC_CTX *memctx, struct sdap_handle *sh,
                     struct sdap_msg *sm, char **_dn);
 
-errno_t setup_tls_config(struct sdap_gen_opts *basic_opts);
+errno_t setup_tls_config(struct dp_option *basic_opts);
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index 80b7e04..1e9e977 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -483,7 +483,7 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
     }
     /* Initialize LDAP handler */
     lret = ldap_initialize(&state->sh->ldap,
-                           sdap_go_get_string(opts->basic, SDAP_URI));
+                           dp_opt_get_string(opts->basic, SDAP_URI));
     if (lret != LDAP_SUCCESS) {
         DEBUG(1, ("ldap_initialize failed: %s\n", ldap_err2string(ret)));
         goto fail;
@@ -498,22 +498,22 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
     }
 
     /* Set Network Timeout */
-    tv.tv_sec = sdap_go_get_int(opts->basic, SDAP_NETWORK_TIMEOUT);
+    tv.tv_sec = dp_opt_get_int(opts->basic, SDAP_NETWORK_TIMEOUT);
     tv.tv_usec = 0;
     lret = ldap_set_option(state->sh->ldap, LDAP_OPT_NETWORK_TIMEOUT, &tv);
     if (lret != LDAP_OPT_SUCCESS) {
         DEBUG(1, ("Failed to set network timeout to %d\n",
-                  sdap_go_get_int(opts->basic, SDAP_NETWORK_TIMEOUT)));
+                  dp_opt_get_int(opts->basic, SDAP_NETWORK_TIMEOUT)));
         goto fail;
     }
 
     /* Set Default Timeout */
-    tv.tv_sec = sdap_go_get_int(opts->basic, SDAP_OPT_TIMEOUT);
+    tv.tv_sec = dp_opt_get_int(opts->basic, SDAP_OPT_TIMEOUT);
     tv.tv_usec = 0;
     lret = ldap_set_option(state->sh->ldap, LDAP_OPT_TIMEOUT, &tv);
     if (lret != LDAP_OPT_SUCCESS) {
         DEBUG(1, ("Failed to set default timeout to %d\n",
-                  sdap_go_get_int(opts->basic, SDAP_OPT_TIMEOUT)));
+                  dp_opt_get_int(opts->basic, SDAP_OPT_TIMEOUT)));
         goto fail;
     }
 
@@ -1199,7 +1199,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
                                   const char *sasl_user,
                                   const char *user_dn,
                                   const char *authtok_type,
-                                  struct sdap_blob authtok)
+                                  struct dp_opt_blob authtok)
 {
     struct tevent_req *req, *subreq;
     struct sdap_auth_state *state;
@@ -1466,7 +1466,7 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx,
             ret = ENOMEM;
             goto fail;
         }
-        if (sdap_go_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
+        if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
             make_realm_upper_case(upn);
         }
         DEBUG(7, ("Adding user principle [%s] to attributes of [%s].\n",
@@ -1680,11 +1680,11 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx,
         if (!opts->users_base) {
             opts->users_base = ldb_dn_new_fmt(opts,
                                     sysdb_handle_get_ldb(state->handle), "%s",
-                                    sdap_go_get_string(opts->basic,
+                                    dp_opt_get_string(opts->basic,
                                                       SDAP_USER_SEARCH_BASE));
             if (!opts->users_base) {
                 DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n",
-                          sdap_go_get_string(opts->basic,
+                          dp_opt_get_string(opts->basic,
                                              SDAP_USER_SEARCH_BASE)));
                 DEBUG(1, ("Out of memory?!\n"));
                 ret = ENOMEM;
@@ -1694,11 +1694,11 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx,
         if (!opts->groups_base) {
             opts->groups_base = ldb_dn_new_fmt(state->handle,
                                     sysdb_handle_get_ldb(state->handle), "%s",
-                                    sdap_go_get_string(opts->basic,
+                                    dp_opt_get_string(opts->basic,
                                                       SDAP_GROUP_SEARCH_BASE));
             if (!opts->users_base) {
                 DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n",
-                          sdap_go_get_string(opts->basic,
+                          dp_opt_get_string(opts->basic,
                                              SDAP_GROUP_SEARCH_BASE)));
                 DEBUG(1, ("Out of memory?!\n"));
                 ret = ENOMEM;
@@ -1950,7 +1950,7 @@ static void sdap_get_users_transaction(struct tevent_req *subreq)
     DEBUG(5, ("calling ldap_search_ext with [%s].\n", state->filter));
 
     lret = ldap_search_ext(state->sh->ldap,
-                           sdap_go_get_string(state->opts->basic,
+                           dp_opt_get_string(state->opts->basic,
                                               SDAP_USER_SEARCH_BASE),
                            LDAP_SCOPE_SUBTREE, state->filter,
                            discard_const(state->attrs),
@@ -1965,7 +1965,7 @@ static void sdap_get_users_transaction(struct tevent_req *subreq)
     /* FIXME: get timeouts from configuration, for now 10 minutes */
     ret = sdap_op_add(state, state->ev, state->sh, msgid,
                       sdap_get_users_done, req,
-                      sdap_go_get_int(state->opts->basic,
+                      dp_opt_get_int(state->opts->basic,
                                       SDAP_SEARCH_TIMEOUT),
                       &state->op);
     if (ret) {
@@ -2177,7 +2177,7 @@ static void sdap_get_groups_transaction(struct tevent_req *subreq)
     }
 
     lret = ldap_search_ext(state->sh->ldap,
-                           sdap_go_get_string(state->opts->basic,
+                           dp_opt_get_string(state->opts->basic,
                                               SDAP_GROUP_SEARCH_BASE),
                            LDAP_SCOPE_SUBTREE, state->filter,
                            discard_const(state->attrs),
@@ -2192,7 +2192,7 @@ static void sdap_get_groups_transaction(struct tevent_req *subreq)
     /* FIXME: get timeouts from configuration, for now 10 minutes */
     ret = sdap_op_add(state, state->ev, state->sh, msgid,
                       sdap_get_groups_done, req,
-                      sdap_go_get_int(state->opts->basic,
+                      dp_opt_get_int(state->opts->basic,
                                       SDAP_SEARCH_TIMEOUT),
                       &state->op);
     if (ret) {
@@ -2511,7 +2511,7 @@ static void sdap_get_initgr_transaction(struct tevent_req *subreq)
     DEBUG(5, ("calling ldap_search_ext with filter:[%s].\n", state->filter));
 
     lret = ldap_search_ext(state->sh->ldap,
-                           sdap_go_get_string(state->opts->basic,
+                           dp_opt_get_string(state->opts->basic,
                                               SDAP_GROUP_SEARCH_BASE),
                            LDAP_SCOPE_SUBTREE, state->filter,
                            discard_const(state->grp_attrs),
@@ -2527,7 +2527,7 @@ static void sdap_get_initgr_transaction(struct tevent_req *subreq)
     /* FIXME: get timeouts from configuration, for now 10 minutes */
     ret = sdap_op_add(state, state->ev, state->sh, msgid,
                       sdap_get_initgr_done, req,
-                      sdap_go_get_int(state->opts->basic,
+                      dp_opt_get_int(state->opts->basic,
                                       SDAP_SEARCH_TIMEOUT),
                       &state->op);
     if (ret) {
diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h
index b79960a..b679da3 100644
--- a/server/providers/ldap/sdap_async.h
+++ b/server/providers/ldap/sdap_async.h
@@ -69,7 +69,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
                                   const char *sasl_user,
                                   const char *user_dn,
                                   const char *authtok_type,
-                                  struct sdap_blob authtok);
+                                  struct dp_opt_blob authtok);
 int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result);
 
 struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
-- 
1.6.2.5

