summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2013-04-12 11:50:48 -0400
committerSimo Sorce <simo@redhat.com>2013-04-23 12:02:29 -0700
commitf0ede0791991f5a7f4112b174cd69b5d90a62447 (patch)
tree70864ffc172c9b007cf2213eca527d7d2465f094
parent3bc4655d770e8105fbc0815d6c35512eec8b7223 (diff)
downloadgss-proxy-f0ede0791991f5a7f4112b174cd69b5d90a62447.tar.gz
gss-proxy-f0ede0791991f5a7f4112b174cd69b5d90a62447.tar.xz
gss-proxy-f0ede0791991f5a7f4112b174cd69b5d90a62447.zip
Treat credential store as opaquely as possible.
The credential store design goal is to allow administrators to set arbitrary strings without additional applications knowledge. This allows extending the number of crdential types GSSAPI can be made to support without having to recompile applications to add explicit support. Only explicitly check for cred store values that ned special treatment and let admins decide what to put in cred_store. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Günther Deschner <gdeschner@redhat.com>
-rw-r--r--proxy/src/gp_common.h2
-rw-r--r--proxy/src/gp_creds.c162
2 files changed, 95 insertions, 69 deletions
diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h
index 13a4c9b..f4a8a58 100644
--- a/proxy/src/gp_common.h
+++ b/proxy/src/gp_common.h
@@ -58,7 +58,7 @@
} while (0)
#define safefree(ptr) do { \
- free(ptr); \
+ free(no_const(ptr)); \
ptr = NULL; \
} while(0)
diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c
index 35d66af..4a731b0 100644
--- a/proxy/src/gp_creds.c
+++ b/proxy/src/gp_creds.c
@@ -176,13 +176,22 @@ done:
return str;
}
-#define DEFAULT_CCACHE ""CCACHE_PATH"/krb5cc_%u"
-#define DEFAULT_CLIENT_KEYTAB ""VARDIR"lib/gssproxy/clients/%u.keytab"
+static void free_cred_store_elements(gss_key_value_set_desc *cs)
+{
+ int i;
+
+ for (i = 0; i < cs->count; i++) {
+ safefree(cs->elements[i].key);
+ safefree(cs->elements[i].value);
+ }
+ safefree(cs->elements);
+}
static int gp_get_cred_environment(struct gp_service *svc,
gssx_name *desired_name,
- gss_name_t *requested_name, char **_ccache,
- char **_client_keytab, char **_keytab)
+ gss_name_t *requested_name,
+ gss_cred_usage_t cred_usage,
+ gss_key_value_set_desc *cs)
{
gss_name_t name = GSS_C_NO_NAME;
gss_OID_desc name_type;
@@ -190,11 +199,13 @@ static int gp_get_cred_environment(struct gp_service *svc,
uint32_t ret_min = 0;
uid_t target_uid;
const char *fmtstr;
- char *ccache = NULL;
- char *client_keytab = NULL;
- char *keytab = NULL;
+ const char *p;
+ char *str;
bool user_requested = false;
int ret = 0;
+ int k_num = -1;
+ int ck_num = -1;
+ int c, s;
target_uid = svc->euid;
@@ -215,47 +226,92 @@ static int gp_get_cred_environment(struct gp_service *svc,
}
}
- if (svc->krb5.ccache == NULL) {
- fmtstr = DEFAULT_CCACHE;
- } else {
- fmtstr = svc->krb5.ccache;
- }
- ccache = get_formatted_string(fmtstr, target_uid);
- if (!ccache) {
- GPDEBUG("Failed to construct ccache string.\n");
- ret = ENOMEM;
- goto done;
+ if (svc->krb5.cred_store == NULL) {
+ cs->elements = NULL;
+ cs->count = 0;
+ return 0;
}
- if ((target_uid == 0) && (!user_requested)) {
- fmtstr = svc->krb5.keytab;
- } else {
- fmtstr = svc->krb5.client_keytab;
- }
- if (fmtstr == NULL) {
- fmtstr = DEFAULT_CLIENT_KEYTAB;
- }
- client_keytab = get_formatted_string(fmtstr, target_uid);
- if (!client_keytab) {
- GPDEBUG("Failed to construct client_keytab string.\n");
+ cs->count = svc->krb5.cred_count;
+ cs->elements = calloc(cs->count, sizeof(gss_key_value_element_desc));
+ if (!cs->elements) {
ret = ENOMEM;
goto done;
}
- if (svc->krb5.keytab != NULL) {
- fmtstr = svc->krb5.keytab;
- keytab = get_formatted_string(svc->krb5.ccache, target_uid);
+ for (c = 0; c < cs->count; c++) {
+ p = strchr(svc->krb5.cred_store[c], ':');
+ if (!p) {
+ GPERROR("Invalid cred_store value"
+ "no ':' separator found in [%s].\n",
+ svc->krb5.cred_store[c]);
+ ret = EINVAL;
+ goto done;
+ }
+ s = p - svc->krb5.cred_store[c];
+ str = strdup(svc->krb5.cred_store[c]);
+ if (!str) {
+ ret = ENOMEM;
+ goto done;
+ }
+ str[s] = '\0';
+ cs->elements[c].key = str;
+
+ if (strcmp(cs->elements[c].key, "keytab") == 0) {
+ k_num = c;
+ } else if (strcmp(cs->elements[c].key, "client_keytab") == 0) {
+ ck_num = c;
+ }
+
+ fmtstr = p + 1;
+ cs->elements[c].value = get_formatted_string(fmtstr, target_uid);
+ if (!cs->elements[c].value) {
+ GPDEBUG("Failed to build credential store formatted string.\n");
+ ret = ENOMEM;
+ goto done;
+ }
}
- *_ccache = ccache;
- *_client_keytab = client_keytab;
- *_keytab = keytab;
+ /* when a user is not explicitly requested then it means the calling
+ * application wants to use the credentials in the standard keytab,
+ * if any. */
+ if (!user_requested && k_num != -1) {
+ if (ck_num != -1) {
+ safefree(cs->elements[ck_num].value);
+ cs->elements[ck_num].value = strdup(cs->elements[k_num].value);
+ if (!cs->elements[ck_num].value) {
+ ret = ENOMEM;
+ goto done;
+ }
+ } else {
+ gss_key_value_element_desc *t;
+ c = cs->count;
+ t = realloc(cs->elements, c + 1);
+ if (!t) {
+ ret = ENOMEM;
+ goto done;
+ }
+ cs->elements = t;
+ cs->elements[c].key = strdup("client_keytab");
+ if (!cs->elements[c].key) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* increment now so in case of failure to opy the value, key is
+ * still freed properly */
+ cs->count = c + 1;
+ cs->elements[c].value = strdup(cs->elements[k_num].value);
+ if (!cs->elements[c].value) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ }
done:
if (ret) {
- free(ccache);
- free(client_keytab);
- free(keytab);
+ free_cred_store_elements(cs);
}
return ret;
}
@@ -272,17 +328,12 @@ uint32_t gp_add_krb5_creds(uint32_t *min,
uint32_t *initiator_time_rec,
uint32_t *acceptor_time_rec)
{
- char *ccache_name = NULL;
- char *client_keytab = NULL;
- char *keytab_name = NULL;
uint32_t ret_maj = 0;
uint32_t ret_min = 0;
uint32_t discard;
gss_name_t req_name = GSS_C_NO_NAME;
gss_OID_set_desc desired_mechs = { 1, &gp_mech_krb5 };
- gss_key_value_element_desc cred_elems[3];
gss_key_value_set_desc cred_store;
- int c;
if (!min || !output_cred_handle) {
return GSS_S_CALL_INACCESSIBLE_WRITE;
@@ -302,38 +353,13 @@ uint32_t gp_add_krb5_creds(uint32_t *min,
return GSS_S_CRED_UNAVAIL;
}
- if (cred_usage == GSS_C_ACCEPT && svc->krb5.keytab == NULL) {
- ret_maj = GSS_S_CRED_UNAVAIL;
- goto done;
- }
-
ret_min = gp_get_cred_environment(svc, desired_name, &req_name,
- &ccache_name, &client_keytab,
- &keytab_name);
+ cred_usage, &cred_store);
if (ret_min) {
ret_maj = GSS_S_CRED_UNAVAIL;
goto done;
}
- cred_store.elements = cred_elems;
- c = 0;
- if (ccache_name) {
- cred_elems[c].key = "ccache";
- cred_elems[c].value = ccache_name;
- c++;
- }
- if (client_keytab) {
- cred_elems[c].key = "client_keytab";
- cred_elems[c].value = client_keytab;
- c++;
- }
- if (keytab_name) {
- cred_elems[c].key = "keytab";
- cred_elems[c].value = keytab_name;
- c++;
- }
- cred_store.count = c;
-
ret_maj = gss_acquire_cred_from(&ret_min, req_name, GSS_C_INDEFINITE,
&desired_mechs, cred_usage, &cred_store,
output_cred_handle, actual_mechs, NULL);