summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2017-01-05 16:06:29 -0500
committerSimo Sorce <simo@redhat.com>2017-01-13 15:50:06 -0500
commit103f72370bc25e9ca152120e7917bc14a81e47a9 (patch)
tree3c5ca7a517ee571e79110afc4eae1497e369b6c9
parent2d49ba029e5b0fdaa4bafc3d5bca0cb1169c9877 (diff)
downloadgss-proxy-103f72370bc25e9ca152120e7917bc14a81e47a9.tar.gz
gss-proxy-103f72370bc25e9ca152120e7917bc14a81e47a9.tar.xz
gss-proxy-103f72370bc25e9ca152120e7917bc14a81e47a9.zip
Parse cred_store struct earlier
This will provide immediate feedback if an option is incorrectly formatted as well as avoid multiple parsing when the cred store spec needs to be used in multiple places. Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r--proxy/src/gp_config.c69
-rw-r--r--proxy/src/gp_creds.c46
-rw-r--r--proxy/src/gp_proxy.h5
3 files changed, 73 insertions, 47 deletions
diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c
index dfc7800..42ab973 100644
--- a/proxy/src/gp_config.c
+++ b/proxy/src/gp_config.c
@@ -55,13 +55,26 @@ static void free_str_array(const char ***a, int *count)
safefree(*a);
}
+void free_cred_store_elements(gss_key_value_set_desc *cs)
+{
+ int i;
+
+ if (!cs->elements) return;
+
+ for (i = 0; i < cs->count; i++) {
+ safefree(cs->elements[i].key);
+ safefree(cs->elements[i].value);
+ }
+ safefree(cs->elements);
+ cs->count = 0;
+}
+
static void gp_service_free(struct gp_service *svc)
{
free(svc->name);
if (svc->mechs & GP_CRED_KRB5) {
free(svc->krb5.principal);
- free_str_array(&(svc->krb5.cred_store),
- &svc->krb5.cred_count);
+ free_cred_store_elements(&svc->krb5.store);
gp_free_creds_handle(&svc->krb5.creds_handle);
}
SELINUX_context_free(svc->selinux_ctx);
@@ -73,9 +86,9 @@ static int setup_krb5_creds_handle(struct gp_service *svc)
uint32_t ret_maj, ret_min;
const char *keytab = NULL;
- for (unsigned i = 0; i < svc->krb5.cred_count; i++) {
- if (strncmp(svc->krb5.cred_store[i], "keytab:", 7) == 0) {
- keytab = svc->krb5.cred_store[i] + 7;
+ for (unsigned i = 0; i < svc->krb5.store.count; i++) {
+ if (strcmp(svc->krb5.store.elements[i].key, "keytab") == 0) {
+ keytab = svc->krb5.store.elements[i].value;
break;
}
}
@@ -99,6 +112,8 @@ static int get_krb5_mech_cfg(struct gp_service *svc,
{"krb5_client_keytab", "client_keytab" }
};
const char *value;
+ const char **strings = NULL;
+ int count = 0;
int i;
int ret;
@@ -127,11 +142,43 @@ static int get_krb5_mech_cfg(struct gp_service *svc,
}
/* instead look for the cred_store parameter */
- ret = gp_config_get_string_array(ctx, secname,
- "cred_store",
- &svc->krb5.cred_count,
- &svc->krb5.cred_store);
- if (ret == ENOENT) {
+ ret = gp_config_get_string_array(ctx, secname, "cred_store",
+ &count, &strings);
+ if (ret == 0) {
+ const char *p;
+ size_t len;
+ char *key;
+
+ svc->krb5.store.elements =
+ calloc(count, sizeof(gss_key_value_element_desc));
+ if (!svc->krb5.store.elements) {
+ ret = ENOMEM;
+ goto done;
+ }
+ svc->krb5.store.count = count;
+
+ for (int c = 0; c < count; c++) {
+ p = strchr(strings[c], ':');
+ if (!p) {
+ GPERROR("Invalid cred_store value, no ':' separator found in"
+ " [%s].\n", strings[c]);
+ ret = EINVAL;
+ goto done;
+ }
+ len = asprintf(&key, "%.*s", (int)(p - strings[c]), strings[c]);
+ if (len == -1) {
+ ret = ENOMEM;
+ goto done;
+ }
+ svc->krb5.store.elements[c].key = key;
+ svc->krb5.store.elements[c].value = strdup(p + 1);
+ if (!svc->krb5.store.elements[c].value) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ } else if (ret == ENOENT) {
/* when not there we ignore */
ret = 0;
}
@@ -140,6 +187,8 @@ static int get_krb5_mech_cfg(struct gp_service *svc,
ret = setup_krb5_creds_handle(svc);
}
+done:
+ free_str_array(&strings, &count);
return ret;
}
diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c
index 8280ef2..05ec659 100644
--- a/proxy/src/gp_creds.c
+++ b/proxy/src/gp_creds.c
@@ -181,17 +181,6 @@ done:
return str;
}
-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);
-}
-
int gp_get_acquire_type(struct gssx_arg_acquire_cred *arg)
{
struct gssx_option *val = NULL;
@@ -240,9 +229,6 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall,
uint32_t ret_maj = 0;
uint32_t ret_min = 0;
uid_t target_uid;
- const char *fmtstr;
- const char *p;
- char *str;
bool user_requested = false;
bool use_service_keytab = false;
int ret = -1;
@@ -301,6 +287,7 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall,
/* impersonation case (only for initiation) */
if (user_requested) {
if (try_impersonate(svc, *cred_usage, ACQ_NORMAL)) {
+ char *str;
/* When impersonating we want to use the service keytab to
* acquire initial credential ... */
use_service_keytab = true;
@@ -342,47 +329,36 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall,
}
}
- if (svc->krb5.cred_store == NULL) {
+ if (svc->krb5.store.count == 0) {
return 0;
}
/* allocate 1 more than in source, just in case we need to add
* an internal client_keytab element */
- cs->elements = calloc(svc->krb5.cred_count + 1,
+ cs->elements = calloc(svc->krb5.store.count + 1,
sizeof(gss_key_value_element_desc));
if (!cs->elements) {
ret = ENOMEM;
goto done;
}
- for (d = 0; d < svc->krb5.cred_count; d++) {
- p = strchr(svc->krb5.cred_store[d], ':');
- if (!p) {
- GPERROR("Invalid cred_store value"
- "no ':' separator found in [%s].\n",
- svc->krb5.cred_store[d]);
- ret = EINVAL;
- goto done;
- }
-
- if (strncmp(svc->krb5.cred_store[d], "client_keytab:", 14) == 0) {
+ for (d = 0; d < svc->krb5.store.count; d++) {
+ if (strcmp(svc->krb5.store.elements[d].key, "client_keytab") == 0) {
ck_num = cs->count;
- } else if (strncmp(svc->krb5.cred_store[d], "keytab:", 7) == 0) {
+ } else if (strcmp(svc->krb5.store.elements[d].key, "keytab") == 0) {
k_num = cs->count;
}
- ret = asprintf(&str, "%.*s", (int)(p - svc->krb5.cred_store[d]),
- svc->krb5.cred_store[d]);
- if (ret == -1) {
+ cs->elements[cs->count].key = strdup(svc->krb5.store.elements[d].key);
+ if (!cs->elements[cs->count].key) {
ret = ENOMEM;
goto done;
}
- cs->elements[cs->count].key = str;
- fmtstr = p + 1;
cs->elements[cs->count].value =
- get_formatted_string(fmtstr, target_uid);
+ get_formatted_string(svc->krb5.store.elements[d].value,
+ target_uid);
if (!cs->elements[cs->count].value) {
- safefree(str);
+ safefree(cs->elements[cs->count].key);
GPDEBUG("Failed to build credential store formatted string.\n");
ret = ENOMEM;
goto done;
diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h
index c7f4bb2..abcd201 100644
--- a/proxy/src/gp_proxy.h
+++ b/proxy/src/gp_proxy.h
@@ -6,6 +6,7 @@
#include <libintl.h>
#include <stdbool.h>
#include <stdint.h>
+#include <gssapi/gssapi_ext.h>
#include "verto.h"
#include "gp_common.h"
#include "gp_selinux.h"
@@ -21,8 +22,7 @@ struct gp_creds_handle;
struct gp_cred_krb5 {
char *principal;
- const char **cred_store;
- int cred_count;
+ gss_key_value_set_desc store;
struct gp_creds_handle *creds_handle;
};
@@ -86,6 +86,7 @@ struct gp_config *read_config(char *config_file, char *config_dir,
char *socket_name, int opt_daemonize);
struct gp_creds_handle *gp_service_get_creds_handle(struct gp_service *svc);
void free_config(struct gp_config **config);
+void free_cred_store_elements(gss_key_value_set_desc *cs);
/* from gp_init.c */
void init_server(bool daemonize, int *wait_fd);