summaryrefslogtreecommitdiffstats
path: root/src/providers/krb5
diff options
context:
space:
mode:
authorPavel Reichl <preichl@redhat.com>2015-04-30 06:43:05 -0400
committerJakub Hrozek <jhrozek@redhat.com>2015-05-28 11:04:28 +0200
commitaa8a8318aaa3270e9d9957d0c22dec6342360a37 (patch)
tree9f6ccd9d2cc601adde7f21fa161715f9d76aee2d /src/providers/krb5
parent62b20154899f847e760d6dfbae6a32fb45b448de (diff)
downloadsssd-aa8a8318aaa3270e9d9957d0c22dec6342360a37.tar.gz
sssd-aa8a8318aaa3270e9d9957d0c22dec6342360a37.tar.xz
sssd-aa8a8318aaa3270e9d9957d0c22dec6342360a37.zip
krb5: new option krb5_map_user
New option `krb5_map_user` providing mapping of ID provider names to Kerberos principals. Resolves: https://fedorahosted.org/sssd/ticket/2509 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/providers/krb5')
-rw-r--r--src/providers/krb5/krb5_access.c8
-rw-r--r--src/providers/krb5/krb5_auth.c76
-rw-r--r--src/providers/krb5/krb5_auth.h5
-rw-r--r--src/providers/krb5/krb5_common.h8
-rw-r--r--src/providers/krb5/krb5_init_shared.c11
-rw-r--r--src/providers/krb5/krb5_opts.h1
-rw-r--r--src/providers/krb5/krb5_utils.c114
-rw-r--r--src/providers/krb5/krb5_utils.h5
8 files changed, 213 insertions, 15 deletions
diff --git a/src/providers/krb5/krb5_access.c b/src/providers/krb5/krb5_access.c
index 7fda2a379..3afb90150 100644
--- a/src/providers/krb5/krb5_access.c
+++ b/src/providers/krb5/krb5_access.c
@@ -64,7 +64,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx,
state->krb5_ctx = krb5_ctx;
state->access_allowed = false;
- ret = krb5_setup(state, pd, krb5_ctx, &state->kr);
+ ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive,
+ &state->kr);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n");
goto done;
@@ -105,9 +106,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx,
goto done;
break;
case 1:
- ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx,
- be_ctx->domain, pd->user, pd->domain,
- &state->kr->upn);
+ ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, be_ctx->domain,
+ state->kr->user, pd->domain, &state->kr->upn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "find_or_guess_upn failed.\n");
goto done;
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 148b08fdf..8c851442b 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -36,6 +36,7 @@
#include "util/find_uid.h"
#include "util/auth_utils.h"
#include "db/sysdb.h"
+#include "util/sss_utf8.h"
#include "util/child_common.h"
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
@@ -175,15 +176,51 @@ static int krb5_cleanup(void *ptr)
return EOK;
}
+static errno_t
+get_krb_primary(struct map_id_name_to_krb_primary *name_to_primary,
+ char *id_prov_name, bool cs, const char **_krb_primary)
+{
+ errno_t ret;
+ int i = 0;
+
+ while(name_to_primary != NULL &&
+ name_to_primary[i].id_name != NULL &&
+ name_to_primary[i].krb_primary != NULL) {
+
+ if (sss_string_equal(cs, name_to_primary[i].id_name, id_prov_name)) {
+ *_krb_primary = name_to_primary[i].krb_primary;
+ ret = EOK;
+ goto done;
+ }
+ i++;
+ }
+
+ /* Handle also the case of name_to_primary being NULL */
+ ret = ENOENT;
+
+done:
+ return ret;
+}
+
errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
- struct krb5_ctx *krb5_ctx, struct krb5child_req **krb5_req)
+ struct krb5_ctx *krb5_ctx, bool cs,
+ struct krb5child_req **_krb5_req)
{
- struct krb5child_req *kr = NULL;
+ struct krb5child_req *kr;
+ const char *mapped_name;
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
- kr = talloc_zero(mem_ctx, struct krb5child_req);
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ kr = talloc_zero(tmp_ctx, struct krb5child_req);
if (kr == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
kr->is_offline = false;
talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
@@ -191,9 +228,28 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
kr->pd = pd;
kr->krb5_ctx = krb5_ctx;
- *krb5_req = kr;
+ ret = get_krb_primary(krb5_ctx->name_to_primary,
+ pd->user, cs, &mapped_name);
+ if (ret == EOK) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Setting mapped name to: %s\n", mapped_name);
+ kr->user = mapped_name;
+ } else if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_ALL, "No mapping for: %s\n", pd->user);
+ kr->user = pd->user;
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "get_krb_primary failed - %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ }
- return EOK;
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ *_krb5_req = talloc_steal(mem_ctx, kr);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
}
@@ -502,7 +558,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
attrs[6] = SYSDB_AUTH_TYPE;
attrs[7] = NULL;
- ret = krb5_setup(state, pd, krb5_ctx, &state->kr);
+ ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive,
+ &state->kr);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n");
goto done;
@@ -535,9 +592,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
break;
case 1:
- ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx,
- be_ctx->domain, pd->user, pd->domain,
- &kr->upn);
+ ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, be_ctx->domain,
+ kr->user, pd->domain, &kr->upn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "find_or_guess_upn failed.\n");
goto done;
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index c93252916..a00f1d9d9 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -55,10 +55,13 @@ struct krb5child_req {
bool valid_tgt;
bool upn_from_different_realm;
bool send_pac;
+
+ const char *user;
};
errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
- struct krb5_ctx *krb5_ctx, struct krb5child_req **krb5_req);
+ struct krb5_ctx *krb5_ctx, bool case_sensitive,
+ struct krb5child_req **krb5_req);
void krb5_pam_handler(struct be_req *be_req);
void krb5_pam_handler_auth_done(struct tevent_req *req);
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 81e64688a..8f6fb229a 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -67,6 +67,7 @@ enum krb5_opts {
KRB5_CANONICALIZE,
KRB5_USE_ENTERPRISE_PRINCIPAL,
KRB5_USE_KDCINFO,
+ KRB5_MAP_USER,
KRB5_OPTS
};
@@ -89,6 +90,11 @@ enum krb5_config_type {
K5C_IPA_SERVER
};
+struct map_id_name_to_krb_primary {
+ const char *id_name;
+ const char* krb_primary;
+};
+
struct krb5_ctx {
/* opts taken from kinit */
/* in seconds */
@@ -128,6 +134,8 @@ struct krb5_ctx {
hash_table_t *wait_queue_hash;
enum krb5_config_type config_type;
+
+ struct map_id_name_to_krb_primary *name_to_primary;
};
struct remove_info_files_ctx {
diff --git a/src/providers/krb5/krb5_init_shared.c b/src/providers/krb5/krb5_init_shared.c
index 3b4bf096e..767291c0b 100644
--- a/src/providers/krb5/krb5_init_shared.c
+++ b/src/providers/krb5/krb5_init_shared.c
@@ -24,6 +24,7 @@
#include "providers/krb5/krb5_common.h"
#include "providers/krb5/krb5_auth.h"
+#include "providers/krb5/krb5_utils.h"
#include "providers/krb5/krb5_init_shared.h"
errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
@@ -90,6 +91,16 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
goto done;
}
+ ret = parse_krb5_map_user(krb5_auth_ctx,
+ dp_opt_get_cstring(krb5_auth_ctx->opts,
+ KRB5_MAP_USER),
+ &krb5_auth_ctx->name_to_primary);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "parse_krb5_map_user failed: %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ }
+
ret = EOK;
done:
diff --git a/src/providers/krb5/krb5_opts.h b/src/providers/krb5/krb5_opts.h
index db62cc3b2..50d701b8b 100644
--- a/src/providers/krb5/krb5_opts.h
+++ b/src/providers/krb5/krb5_opts.h
@@ -45,6 +45,7 @@ struct dp_option default_krb5_opts[] = {
{ "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index de2d94503..0b73880ec 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -465,3 +465,117 @@ errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
return EOK;
}
+
+static errno_t split_tuple(TALLOC_CTX *mem_ctx, const char *tuple,
+ const char **_first, const char **_second)
+{
+ errno_t ret;
+ char **list;
+ int n;
+
+ ret = split_on_separator(mem_ctx, tuple, ':', true, true, &list, &n);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "split_on_separator failed - %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ } else if (n != 2) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "split_on_separator failed - Expected format is: "
+ "'username:primary' but got: '%s'.\n", tuple);
+ ret = EINVAL;
+ goto done;
+ }
+
+ *_first = list[0];
+ *_second = list[1];
+
+done:
+ return ret;
+}
+
+static errno_t
+fill_name_to_primary_map(TALLOC_CTX *mem_ctx, char **map,
+ struct map_id_name_to_krb_primary *name_to_primary,
+ size_t size)
+{
+ int i;
+ errno_t ret;
+
+ for (i = 0; i < size; i++) {
+ ret = split_tuple(mem_ctx, map[i],
+ &name_to_primary[i].id_name,
+ &name_to_primary[i].krb_primary);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "split_tuple failed - %s:[%d]\n", sss_strerror(ret), ret);
+ goto done;
+ }
+ }
+
+ ret = EOK;
+
+done:
+ return ret;
+}
+
+errno_t
+parse_krb5_map_user(TALLOC_CTX *mem_ctx, const char *krb5_map_user,
+ struct map_id_name_to_krb_primary **_name_to_primary)
+{
+ int size;
+ char **map;
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ struct map_id_name_to_krb_primary *name_to_primary;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (krb5_map_user == NULL || strlen(krb5_map_user) == 0) {
+ DEBUG(SSSDBG_FUNC_DATA, "Warning: krb5_map_user is empty!\n");
+ size = 0;
+ } else {
+ ret = split_on_separator(tmp_ctx, krb5_map_user, ',', true, true,
+ &map, &size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to parse krb5_map_user!\n");
+ goto done;
+ }
+ }
+
+ name_to_primary = talloc_zero_array(tmp_ctx,
+ struct map_id_name_to_krb_primary,
+ size + 1);
+ if (name_to_primary == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ /* sentinel */
+ name_to_primary[size].id_name = NULL;
+ name_to_primary[size].krb_primary = NULL;
+
+ if (size > 0) {
+ ret = fill_name_to_primary_map(name_to_primary, map, name_to_primary,
+ size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "fill_name_to_primary_map failed: %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ }
+ }
+
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ *_name_to_primary = talloc_steal(mem_ctx, name_to_primary);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 0155905b5..75b93c30e 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -49,4 +49,9 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
char *domain_name,
struct sss_domain_info **dom);
+
+errno_t
+parse_krb5_map_user(TALLOC_CTX *mem_ctx, const char *krb5_map_user,
+ struct map_id_name_to_krb_primary **_name_to_primary);
+
#endif /* __KRB5_UTILS_H__ */