From 30cd03bbbb9e5d8ca6b2014c4b1daceaf75a7397 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 12 Sep 2009 20:03:57 -0400 Subject: Turn ldap driver options into multitype This patch makes basic options multiype, the init function assigns a type from the initialization array, and processes values fetched from confdb accordingly. 4 types are supported so far: string, number, blob and boolean Also convert defines into enums where appropriate. Add fetch functions that check the requested type. --- server/providers/ldap/ldap_auth.c | 48 ++++--- server/providers/ldap/ldap_id.c | 80 +++++++----- server/providers/ldap/sdap.c | 254 +++++++++++++++++++++++++++---------- server/providers/ldap/sdap.h | 141 ++++++++++++-------- server/providers/ldap/sdap_async.c | 45 ++++--- server/providers/ldap/sdap_async.h | 2 +- 6 files changed, 376 insertions(+), 194 deletions(-) (limited to 'server') diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c index 51afee361..a64a27f7d 100644 --- a/server/providers/ldap/ldap_auth.c +++ b/server/providers/ldap/ldap_auth.c @@ -126,7 +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, - state->ctx->opts->basic[SDAP_USER_SEARCH_BASE].value); + sdap_go_get_string(state->ctx->opts->basic, + SDAP_USER_SEARCH_BASE)); if (!dn) { tevent_req_error(req, ENOMEM); break; @@ -173,7 +174,7 @@ struct auth_state { struct tevent_context *ev; struct sdap_auth_ctx *ctx; const char *username; - const char *password; + struct sdap_blob password; struct sdap_handle *sh; @@ -185,11 +186,11 @@ static void auth_connect_done(struct tevent_req *subreq); static void auth_get_user_dn_done(struct tevent_req *subreq); static void auth_bind_user_done(struct tevent_req *subreq); -struct tevent_req *auth_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_auth_ctx *ctx, - const char *username, - const char *password) +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 tevent_req *req, *subreq; struct auth_state *state; @@ -333,6 +334,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; ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data, struct sdap_auth_ctx); @@ -371,8 +373,10 @@ static void sdap_pam_chpass_send(struct be_req *breq) talloc_set_destructor((TALLOC_CTX *)state->new_password, password_destructor); + authtok.data = (uint8_t *)state->password; + authtok.length = strlen(state->password); subreq = auth_send(breq, breq->be_ctx->ev, - ctx, state->username, state->password); + ctx, state->username, authtok); if (!subreq) goto done; tevent_req_set_callback(subreq, sdap_auth4chpass_done, state); @@ -454,7 +458,7 @@ struct sdap_pam_auth_state { struct be_req *breq; struct pam_data *pd; const char *username; - char *password; + struct sdap_blob password; }; static void sdap_pam_auth_done(struct tevent_req *req); @@ -489,14 +493,11 @@ static void sdap_pam_auth_send(struct be_req *breq) state->breq = breq; state->pd = pd; state->username = pd->user; - state->password = talloc_strndup(state, - (char *)pd->authtok, pd->authtok_size); - if (!state->password) goto done; - talloc_set_destructor((TALLOC_CTX *)state->password, - password_destructor); - - subreq = auth_send(breq, breq->be_ctx->ev, - ctx, state->username, state->password); + state->password.data = pd->authtok; + state->password.length = pd->authtok_size; + + subreq = auth_send(breq, breq->be_ctx->ev, ctx, + state->username, state->password); if (!subreq) goto done; tevent_req_set_callback(subreq, sdap_pam_auth_done, state); @@ -551,12 +552,21 @@ static void sdap_pam_auth_done(struct tevent_req *req) if (result == SDAP_AUTH_SUCCESS && state->breq->be_ctx->domain->cache_credentials) { + char *password = talloc_strndup(state, (char *) + state->password.data, + state->password.length); + if (!password) { + DEBUG(2, ("Failed to cache password for %s\n", state->username)); + goto done; + } + talloc_set_destructor((TALLOC_CTX *)password, password_destructor); + subreq = sysdb_cache_password_send(state, state->breq->be_ctx->ev, state->breq->be_ctx->sysdb, NULL, state->breq->be_ctx->domain, - state->username, state->password); + state->username, password); /* password caching failures are not fatal errors */ if (!subreq) { @@ -633,7 +643,7 @@ int sssm_ldap_auth_init(struct be_ctx *bectx, &ctx->opts); if (ret != EOK) goto done; - tls_reqcert = ctx->opts->basic[SDAP_TLS_REQCERT].value; + tls_reqcert = sdap_go_get_string(ctx->opts->basic, SDAP_TLS_REQCERT); if (tls_reqcert) { if (strcasecmp(tls_reqcert, "never") == 0) { ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_NEVER; diff --git a/server/providers/ldap/ldap_id.c b/server/providers/ldap/ldap_id.c index 1984582d7..72caf9664 100644 --- a/server/providers/ldap/ldap_id.c +++ b/server/providers/ldap/ldap_id.c @@ -98,7 +98,7 @@ struct sdap_id_connect_state { bool use_start_tls; char *defaultBindDn; char *defaultAuthtokType; - char *defaultAuthtok; + struct sdap_blob defaultAuthtok; struct sdap_handle *sh; }; @@ -106,13 +106,13 @@ struct sdap_id_connect_state { static void sdap_id_connect_done(struct tevent_req *subreq); static void sdap_id_bind_done(struct tevent_req *subreq); -struct tevent_req *sdap_id_connect_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - bool use_start_tls, - char *defaultBindDn, - char *defaultAuthtokType, - char *defaultAuthtok) +static struct tevent_req *sdap_id_connect_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_id_ctx *ctx, + bool use_start_tls, + char *defaultBindDn, + char *defaultAuthtokType, + struct sdap_blob defaultAuthtok) { struct tevent_req *req, *subreq; struct sdap_id_connect_state *state; @@ -268,9 +268,12 @@ static struct tevent_req *users_get_send(TALLOC_CTX *memctx, /* FIXME: add option to decide if tls should be used * or SASL/GSSAPI, etc ... */ subreq = sdap_id_connect_send(state, ev, ctx, false, - ctx->opts->basic[SDAP_DEFAULT_BIND_DN].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK_TYPE].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK].value); + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_BIND_DN), + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK_TYPE), + sdap_go_get_blob(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK)); if (!subreq) { ret = ENOMEM; goto fail; @@ -434,9 +437,12 @@ static struct tevent_req *groups_get_send(TALLOC_CTX *memctx, /* FIXME: add option to decide if tls should be used * or SASL/GSSAPI, etc ... */ subreq = sdap_id_connect_send(state, ev, ctx, false, - ctx->opts->basic[SDAP_DEFAULT_BIND_DN].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK_TYPE].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK].value); + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_BIND_DN), + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK_TYPE), + sdap_go_get_blob(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK)); if (!subreq) { ret = ENOMEM; goto fail; @@ -574,9 +580,12 @@ static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, /* FIXME: add option to decide if tls should be used * or SASL/GSSAPI, etc ... */ subreq = sdap_id_connect_send(state, ev, ctx, false, - ctx->opts->basic[SDAP_DEFAULT_BIND_DN].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK_TYPE].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK].value); + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_BIND_DN), + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK_TYPE), + sdap_go_get_blob(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK)); if (!subreq) { ret = ENOMEM; goto fail; @@ -789,6 +798,7 @@ static void ldap_id_enumerate(struct tevent_context *ev, struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); struct tevent_timer *timeout; struct tevent_req *req; + int ert; if (be_is_offline(ctx->be)) { DEBUG(4, ("Backend is marked offline, retry later!\n")); @@ -811,7 +821,8 @@ 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(); - tv = tevent_timeval_add(&tv, ctx->opts->enum_refresh_timeout, 0); + ert = sdap_go_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); return; @@ -824,9 +835,10 @@ static void ldap_id_enumerate_timeout(struct tevent_context *ev, struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); struct sdap_id_ctx *ctx = tevent_req_callback_data(req, struct sdap_id_ctx); + int ert; - DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", - ctx->opts->enum_refresh_timeout)); + ert = sdap_go_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()); talloc_zfree(req); @@ -855,8 +867,10 @@ static void ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) { struct tevent_timer *enum_task; + int ert; - tv = tevent_timeval_add(&tv, ctx->opts->enum_refresh_timeout, 0); + ert = sdap_go_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) { DEBUG(0, ("FATAL: failed to setup enumeration task!\n")); @@ -965,6 +979,7 @@ fail: tevent_req_done(req); } + /* ==User-Enumeration===================================================== */ struct enum_users_state { @@ -1025,9 +1040,12 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, /* FIXME: add option to decide if tls should be used * or SASL/GSSAPI, etc ... */ subreq = sdap_id_connect_send(state, ev, ctx, false, - ctx->opts->basic[SDAP_DEFAULT_BIND_DN].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK_TYPE].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK].value); + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_BIND_DN), + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK_TYPE), + sdap_go_get_blob(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK)); if (!subreq) { ret = ENOMEM; goto fail; @@ -1175,9 +1193,12 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, /* FIXME: add option to decide if tls should be used * or SASL/GSSAPI, etc ... */ subreq = sdap_id_connect_send(state, ev, ctx, false, - ctx->opts->basic[SDAP_DEFAULT_BIND_DN].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK_TYPE].value, - ctx->opts->basic[SDAP_DEFAULT_AUTHTOK].value); + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_BIND_DN), + sdap_go_get_string(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK_TYPE), + sdap_go_get_blob(ctx->opts->basic, + SDAP_DEFAULT_AUTHTOK)); if (!subreq) { ret = ENOMEM; goto fail; @@ -1291,10 +1312,9 @@ int sssm_ldap_init(struct be_ctx *bectx, ctx->be = bectx; - ret = sdap_get_options(ctx, bectx->cdb, bectx->conf_path, - &ctx->opts); + ret = sdap_get_options(ctx, bectx->cdb, bectx->conf_path, &ctx->opts); - tls_reqcert = ctx->opts->basic[SDAP_TLS_REQCERT].value; + tls_reqcert = sdap_go_get_string(ctx->opts->basic, SDAP_TLS_REQCERT); if (tls_reqcert) { if (strcasecmp(tls_reqcert, "never") == 0) { ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_NEVER; diff --git a/server/providers/ldap/sdap.c b/server/providers/ldap/sdap.c index 616e4a37c..22d238e65 100644 --- a/server/providers/ldap/sdap.c +++ b/server/providers/ldap/sdap.c @@ -25,24 +25,31 @@ #include "confdb/confdb.h" #include "providers/ldap/sdap.h" +#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 } + struct sdap_gen_opts default_basic_opts[] = { - { "ldapUri", "ldap://localhost", NULL }, - { "defaultBindDn", NULL, NULL }, - { "defaultAuthtokType", NULL, NULL }, - { "defaultAuthtok", NULL, NULL }, - { "network_timeout", "5", NULL }, - { "opt_timeout", "5", NULL }, - { "tls_reqcert", "hard", NULL }, - { "userSearchBase", "ou=People,dc=example,dc=com", NULL }, - { "userSearchScope", "sub", NULL }, - { "userSearchFilter", NULL, NULL }, - { "groupSearchBase", "ou=Group,dc=example,dc=com", NULL }, - { "groupSearchScope", "sub", NULL }, - { "groupSearchFilter", NULL, NULL }, - { "ldapSchema", "rfc2307", NULL }, - { "offline_timeout", "60", NULL }, - { "force_upper_case_realm", "0", NULL }, - { "enumeration_refresh_timeout", "300", NULL } + { "ldapUri", SDAP_STRING, { "ldap://localhost" }, NULL_STRING }, + { "defaultBindDn", SDAP_STRING, NULL_STRING, NULL_STRING }, + { "defaultAuthtokType", SDAP_STRING, NULL_STRING, NULL_STRING}, + { "defaultAuthtok", SDAP_BLOB, NULL_BLOB, NULL_BLOB }, + { "network_timeout", SDAP_NUMBER, { .number = 5 }, NULL_NUMBER }, + { "opt_timeout", SDAP_NUMBER, { .number = 5 }, NULL_NUMBER }, + { "tls_reqcert", SDAP_STRING, { "hard" }, NULL_STRING }, + { "userSearchBase", SDAP_STRING, { "ou=People,dc=example,dc=com" }, NULL_STRING }, + { "userSearchScope", SDAP_STRING, { "sub" }, NULL_STRING }, + { "userSearchFilter", SDAP_STRING, NULL_STRING, NULL_STRING }, + { "groupSearchBase", SDAP_STRING, { "ou=Group,dc=example,dc=com" }, NULL_STRING }, + { "groupSearchScope", SDAP_STRING, { "sub" }, NULL_STRING }, + { "groupSearchFilter", SDAP_STRING, NULL_STRING, NULL_STRING }, + { "ldapSchema", SDAP_STRING, { "rfc2307" }, NULL_STRING }, + { "offline_timeout", SDAP_NUMBER, { .number = 60 }, NULL_NUMBER }, + { "force_upper_case_realm", SDAP_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "enumeration_refresh_timeout", SDAP_NUMBER, { .number = 300 }, NULL_NUMBER }, + { "stale_time", SDAP_NUMBER, { .number = 1800 }, NULL_NUMBER } }; struct sdap_id_map rfc2307_user_map[] = { @@ -109,6 +116,7 @@ int sdap_get_options(TALLOC_CTX *memctx, struct sdap_id_map *default_user_map; struct sdap_id_map *default_group_map; struct sdap_options *opts; + char *schema; int i, ret; opts = talloc_zero(memctx, struct sdap_options); @@ -124,76 +132,98 @@ int sdap_get_options(TALLOC_CTX *memctx, 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].def_value = default_basic_opts[i].def_value; - - ret = confdb_get_string(cdb, opts, conf_path, - opts->basic[i].opt_name, - opts->basic[i].def_value, - &opts->basic[i].value); - if (ret != EOK || - (opts->basic[i].def_value && !opts->basic[i].value)) { - DEBUG(0, ("Failed to retrieve a value (%s)\n", - opts->basic[i].opt_name)); - if (ret != EOK) ret = EINVAL; - goto done; - } - - DEBUG(5, ("Option %s has value %s\n", - opts->basic[i].opt_name, opts->basic[i].value)); - } - - /* re-read special options that are easier to be consumed after they are - * transformed */ - -/* TODO: better to have a blob object than a string here */ - ret = confdb_get_string(cdb, opts, conf_path, - "defaultAuthtok", NULL, - &opts->default_authtok); - if (ret != EOK) goto done; - if (opts->default_authtok) { - opts->default_authtok_size = strlen(opts->default_authtok); - } + 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; - ret = confdb_get_int(cdb, opts, conf_path, - "network_timeout", 5, - &opts->network_timeout); - if (ret != EOK) goto done; + 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; + } - ret = confdb_get_int(cdb, opts, conf_path, - "opt_timeout", 5, - &opts->opt_timeout); - if (ret != EOK) 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; + } - ret = confdb_get_int(cdb, opts, conf_path, - "offline_timeout", 60, - &opts->offline_timeout); - if (ret != EOK) goto done; + DEBUG(6, ("Option %s has %s value\n", + opts->basic[i].opt_name, + opts->basic[i].val.blob.length?"a":"no")); + break; - ret = confdb_get_bool(cdb, opts, conf_path, - "force_upper_case_realm", false, - &opts->force_upper_case_realm); - if (ret != EOK) goto done; + 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; - ret = confdb_get_int(cdb, opts, conf_path, - "enumeration_refresh_timeout", 300, - &opts->enum_refresh_timeout); - if (ret != EOK) goto done; + 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; + } + } /* schema type */ - if (strcasecmp(opts->basic[SDAP_SCHEMA].value, "rfc2307") == 0) { + schema = sdap_go_get_string(opts->basic, SDAP_SCHEMA); + if (strcasecmp(schema, "rfc2307") == 0) { opts->schema_type = SDAP_SCHEMA_RFC2307; default_user_map = rfc2307_user_map; default_group_map = rfc2307_group_map; } else - if (strcasecmp(opts->basic[SDAP_SCHEMA].value, "rfc2307bis") == 0) { + if (strcasecmp(schema, "rfc2307bis") == 0) { opts->schema_type = SDAP_SCHEMA_RFC2307BIS; default_user_map = rfc2307bis_user_map; default_group_map = rfc2307bis_group_map; } else { - DEBUG(0, ("Unrecognized schema type: %s\n", - opts->basic[SDAP_SCHEMA].value)); + DEBUG(0, ("Unrecognized schema type: %s\n", schema)); ret = EINVAL; goto done; } @@ -250,6 +280,90 @@ 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, diff --git a/server/providers/ldap/sdap.h b/server/providers/ldap/sdap.h index a39eef515..7168a5a00 100644 --- a/server/providers/ldap/sdap.h +++ b/server/providers/ldap/sdap.h @@ -69,60 +69,88 @@ enum sdap_result { SDAP_AUTH_FAILED }; -#define SDAP_URI 0 -#define SDAP_DEFAULT_BIND_DN 1 -#define SDAP_DEFAULT_AUTHTOK_TYPE 2 -#define SDAP_DEFAULT_AUTHTOK 3 -#define SDAP_NETWROK_TIMEOUT 4 -#define SDAP_OPT_TIMEOUT 5 -#define SDAP_TLS_REQCERT 6 -#define SDAP_USER_SEARCH_BASE 7 -#define SDAP_USER_SEARCH_SCOPE 8 -#define SDAP_USER_SEARCH_FILTER 9 -#define SDAP_GROUP_SEARCH_BASE 10 -#define SDAP_GROUP_SEARCH_SCOPE 11 -#define SDAP_GROUP_SEARCH_FILTER 12 -#define SDAP_SCHEMA 13 -#define SDAP_OFFLINE_TIMEOUT 14 -#define SDAP_FORCE_UPPER_CASE_REALM 15 -#define SDAP_ENUM_REFRESH_TIMEOUT 16 - -#define SDAP_OPTS_BASIC 17 /* opts counter */ +enum sdap_basic_opt { + SDAP_URI = 0, + SDAP_DEFAULT_BIND_DN, + SDAP_DEFAULT_AUTHTOK_TYPE, + SDAP_DEFAULT_AUTHTOK, + SDAP_NETWORK_TIMEOUT, + SDAP_OPT_TIMEOUT, + SDAP_TLS_REQCERT, + SDAP_USER_SEARCH_BASE, + SDAP_USER_SEARCH_SCOPE, + SDAP_USER_SEARCH_FILTER, + SDAP_GROUP_SEARCH_BASE, + SDAP_GROUP_SEARCH_SCOPE, + SDAP_GROUP_SEARCH_FILTER, + SDAP_SCHEMA, + SDAP_OFFLINE_TIMEOUT, + SDAP_FORCE_UPPER_CASE_REALM, + SDAP_ENUM_REFRESH_TIMEOUT, + SDAP_STALE_TIME, + + SDAP_OPTS_BASIC /* opts counter */ +}; /* the objectclass must be the first attribute. * Functions depend on this */ -#define SDAP_OC_USER 0 -#define SDAP_AT_USER_NAME 1 -#define SDAP_AT_USER_PWD 2 -#define SDAP_AT_USER_UID 3 -#define SDAP_AT_USER_GID 4 -#define SDAP_AT_USER_GECOS 5 -#define SDAP_AT_USER_HOME 6 -#define SDAP_AT_USER_SHELL 7 -#define SDAP_AT_USER_PRINC 8 -#define SDAP_AT_USER_FULLNAME 9 -#define SDAP_AT_USER_MEMBEROF 10 -#define SDAP_AT_USER_UUID 11 -#define SDAP_AT_USER_MODSTAMP 12 - -#define SDAP_OPTS_USER 13 /* attrs counter */ +enum sdap_user_opt { + SDAP_OC_USER = 0, + SDAP_AT_USER_NAME, + SDAP_AT_USER_PWD, + SDAP_AT_USER_UID, + SDAP_AT_USER_GID, + SDAP_AT_USER_GECOS, + SDAP_AT_USER_HOME, + SDAP_AT_USER_SHELL, + SDAP_AT_USER_PRINC, + SDAP_AT_USER_FULLNAME, + SDAP_AT_USER_MEMBEROF, + SDAP_AT_USER_UUID, + SDAP_AT_USER_MODSTAMP, + + SDAP_OPTS_USER /* attrs counter */ +}; /* the objectclass must be the first attribute. * Functions depend on this */ -#define SDAP_OC_GROUP 0 -#define SDAP_AT_GROUP_NAME 1 -#define SDAP_AT_GROUP_PWD 2 -#define SDAP_AT_GROUP_GID 3 -#define SDAP_AT_GROUP_MEMBER 4 -#define SDAP_AT_GROUP_UUID 5 -#define SDAP_AT_GROUP_MODSTAMP 6 +enum sdap_group_opt { + SDAP_OC_GROUP = 0, + SDAP_AT_GROUP_NAME, + SDAP_AT_GROUP_PWD, + SDAP_AT_GROUP_GID, + SDAP_AT_GROUP_MEMBER, + SDAP_AT_GROUP_UUID, + SDAP_AT_GROUP_MODSTAMP, + + SDAP_OPTS_GROUP /* attrs counter */ +}; + +enum sdap_type { + SDAP_STRING, + SDAP_BLOB, + SDAP_NUMBER, + SDAP_BOOL +}; -#define SDAP_OPTS_GROUP 7 /* attrs counter */ +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; - const char *def_value; - char *value; + enum sdap_type type; + union sdap_value def_val; + union sdap_value val; }; struct sdap_id_map { @@ -137,15 +165,6 @@ struct sdap_options { struct sdap_id_map *user_map; struct sdap_id_map *group_map; - /* transformed for easier consumption */ - uint32_t default_authtok_size; - char *default_authtok; /* todo: turn into uint8_t */ - int network_timeout; - int opt_timeout; - int offline_timeout; - int enum_refresh_timeout; - bool force_upper_case_realm; - /* supported schema types */ enum schema_type { SDAP_SCHEMA_RFC2307 = 1, /* memberUid = uid */ @@ -162,6 +181,22 @@ 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); diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c index bcdf22a08..1a0faf4ef 100644 --- a/server/providers/ldap/sdap_async.c +++ b/server/providers/ldap/sdap_async.c @@ -472,7 +472,8 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, return NULL; } /* Initialize LDAP handler */ - lret = ldap_initialize(&state->sh->ldap, opts->basic[SDAP_URI].value); + lret = ldap_initialize(&state->sh->ldap, + sdap_go_get_string(opts->basic, SDAP_URI)); if (lret != LDAP_SUCCESS) { DEBUG(1, ("ldap_initialize failed: %s\n", ldap_err2string(ret))); goto fail; @@ -487,22 +488,22 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, } /* Set Network Timeout */ - tv.tv_sec = opts->network_timeout; + tv.tv_sec = sdap_go_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", - opts->network_timeout)); + sdap_go_get_int(opts->basic, SDAP_NETWORK_TIMEOUT))); goto fail; } /* Set Default Timeout */ - tv.tv_sec = opts->opt_timeout; + tv.tv_sec = sdap_go_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", - opts->opt_timeout)); + sdap_go_get_int(opts->basic, SDAP_OPT_TIMEOUT))); goto fail; } @@ -766,7 +767,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, struct sdap_handle *sh, const char *user_dn, const char *authtok_type, - const char *password) + struct sdap_blob authtok) { struct tevent_req *req, *subreq; struct sdap_auth_state *state; @@ -780,13 +781,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, if (!req) return NULL; state->user_dn = user_dn; - if (password) { - state->pw.bv_val = discard_const(password); - state->pw.bv_len = strlen(password); - } else { - state->pw.bv_val = NULL; - state->pw.bv_len = 0; - } + state->pw.bv_val = (char *)authtok.data; + state->pw.bv_len = authtok.length; subreq = simple_bind_send(state, ev, sh, user_dn, &state->pw); if (!subreq) { @@ -1020,7 +1016,7 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, ret = ENOMEM; goto fail; } - if (opts->force_upper_case_realm) { + if (sdap_go_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", @@ -1234,10 +1230,12 @@ 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", - opts->basic[SDAP_USER_SEARCH_BASE].value); + sdap_go_get_string(opts->basic, + SDAP_USER_SEARCH_BASE)); if (!opts->users_base) { DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", - opts->basic[SDAP_USER_SEARCH_BASE].value)); + sdap_go_get_string(opts->basic, + SDAP_USER_SEARCH_BASE))); DEBUG(1, ("Out of memory?!\n")); ret = ENOMEM; goto fail; @@ -1246,10 +1244,12 @@ 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", - opts->basic[SDAP_GROUP_SEARCH_BASE].value); + sdap_go_get_string(opts->basic, + SDAP_GROUP_SEARCH_BASE)); if (!opts->users_base) { DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", - opts->basic[SDAP_USER_SEARCH_BASE].value)); + sdap_go_get_string(opts->basic, + SDAP_GROUP_SEARCH_BASE))); DEBUG(1, ("Out of memory?!\n")); ret = ENOMEM; goto fail; @@ -1500,7 +1500,8 @@ 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, - state->opts->basic[SDAP_USER_SEARCH_BASE].value, + sdap_go_get_string(state->opts->basic, + SDAP_USER_SEARCH_BASE), LDAP_SCOPE_SUBTREE, state->filter, discard_const(state->attrs), false, NULL, NULL, NULL, 0, &msgid); @@ -1723,7 +1724,8 @@ static void sdap_get_groups_transaction(struct tevent_req *subreq) } lret = ldap_search_ext(state->sh->ldap, - state->opts->basic[SDAP_GROUP_SEARCH_BASE].value, + sdap_go_get_string(state->opts->basic, + SDAP_GROUP_SEARCH_BASE), LDAP_SCOPE_SUBTREE, state->filter, discard_const(state->attrs), false, NULL, NULL, NULL, 0, &msgid); @@ -2053,7 +2055,8 @@ 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, - state->opts->basic[SDAP_GROUP_SEARCH_BASE].value, + sdap_go_get_string(state->opts->basic, + SDAP_GROUP_SEARCH_BASE), LDAP_SCOPE_SUBTREE, state->filter, discard_const(state->grp_attrs), false, NULL, NULL, NULL, 0, &msgid); diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h index c9af750bb..08b84d8b6 100644 --- a/server/providers/ldap/sdap_async.h +++ b/server/providers/ldap/sdap_async.h @@ -59,7 +59,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, struct sdap_handle *sh, const char *user_dn, const char *authtok_type, - const char *password); + struct sdap_blob authtok); int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result); struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, -- cgit