summaryrefslogtreecommitdiffstats
path: root/proxy/src
diff options
context:
space:
mode:
Diffstat (limited to 'proxy/src')
-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);