diff options
author | Simo Sorce <simo@redhat.com> | 2015-03-22 16:52:02 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2015-03-22 17:01:52 -0400 |
commit | ea3b234e7dc56b185e1e25f6041d091e0aaef1c4 (patch) | |
tree | 894499fb71272aa5cd2aea96ade589c7dd9dfee5 | |
parent | 4efb5ab5686d7bfe00e2a387ba66de4e43ddf317 (diff) | |
download | gss-proxy-ea3b234e7dc56b185e1e25f6041d091e0aaef1c4.tar.gz gss-proxy-ea3b234e7dc56b185e1e25f6041d091e0aaef1c4.tar.xz gss-proxy-ea3b234e7dc56b185e1e25f6041d091e0aaef1c4.zip |
wipdelegate
-rw-r--r-- | proxy/src/mechglue/gpp_creds.c | 143 |
1 files changed, 136 insertions, 7 deletions
diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c index dff9c44..19e3e54 100644 --- a/proxy/src/mechglue/gpp_creds.c +++ b/proxy/src/mechglue/gpp_creds.c @@ -25,6 +25,9 @@ #include "gss_plugin.h" #include <gssapi/gssapi_krb5.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> static OM_uint32 get_local_def_creds(OM_uint32 *minor_status, struct gpp_name_handle *name, @@ -382,6 +385,115 @@ OM_uint32 gssi_set_cred_option(OM_uint32 *minor_status, return maj; } +#define GP_CCNAME "GSSPROXYCCNAME" +#define DEFAULT_GP_CCNAME ".gssproxyccache" + +#define PWBUFLEN 2048 +static char *get_def_ccname(void) +{ + struct passwd pwd, *res = NULL; + char buffer[PWBUFLEN]; + char *ccname; + int ret; + + ret = getpwuid_r(geteuid(), &pwd, buffer, PWBUFLEN, &res); + if (ret || !res) { + return NULL; + } + ret = asprintf(&ccname, "%s/%s", pwd.pw_dir, DEFAULT_GP_CCNAME); + if (ret == 1) { + return NULL; + } + return ccname; +} + +static int file_lock(int fd, size_t len, bool lock) +{ + struct flock l = { + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = len + }; + int ret; + + if (lock) { + l.l_type = F_WRLCK; + } else { + l.l_type = F_UNLCK; + } + errno = 0; + do { + ret = fcntl(fd, F_SETLKW, &l); + } while(ret == -1 && errno == EINTR); + + return ret; +} + +#define MAX_CRED_SIZE 1024*1024 +static int store_cred(const char *file_name, + struct gssx_cred *cred) +{ + /* version 1 */ + int version = 1; + XDR xdrctx; + size_t buflen = 0; + char buffer[MAX_CRED_SIZE]; + uint32_t beint; + ssize_t len = 0; + int fd = -1; + int ret; + + xdrmem_create(&xdrctx, buffer, MAX_CRED_SIZE, XDR_ENCODE); + if (!xdr_gssx_cred(&xdrctx, cred)) { + ret = EIO; + goto done; + } + buflen = htobe32(xdr_getpos(&xdrctx)); + + ret = EIO; + fd = open(file_name, O_RDWR|O_CLOEXEC, 0600); + if (fd != -1) { + ret = file_lock(fd, MAX_CRED_SIZE, true); + if (ret == -1) { + ret = errno; + goto done; + } + beint = htobe32(version); + len = gp_safe_write(fd, &beint, sizeof(uint32_t)); + if (len != sizeof(uint32_t)) { + ret = EIO; + len = 0; + goto done; + } + beint = htobe32(buflen); + len = gp_safe_write(fd, &beint, sizeof(uint32_t)); + if (len != sizeof(uint32_t)) { + ret = EIO; + len = 0; + goto done; + } + len = gp_safe_write(fd, buffer, buflen); + if (len != buflen) { + ret = EIO; + len = 0; + goto done; + } + + /* total file length for truncate */ + len += sizeof(uint32_t) * 2; + ret = 0; + } + +done: + if (fd != -1) { + (void)ftruncate(fd, len); + (void)file_lock(fd, MAX_CRED_SIZE, false); + (void)close(fd); + } + xdr_destroy(&xdrctx); + return ret; +} + OM_uint32 gssi_store_cred(OM_uint32 *minor_status, const gss_cred_id_t input_cred_handle, gss_cred_usage_t input_usage, @@ -392,6 +504,7 @@ OM_uint32 gssi_store_cred(OM_uint32 *minor_status, gss_cred_usage_t *cred_usage_stored) { struct gpp_cred_handle *cred = NULL; + char *gp_cc_name = NULL; OM_uint32 maj, min; GSSI_TRACE(); @@ -403,15 +516,31 @@ OM_uint32 gssi_store_cred(OM_uint32 *minor_status, cred = (struct gpp_cred_handle *)input_cred_handle; /* NOTE: For now we can do this only for local credentials */ - if (!cred->local) { - return GSS_S_UNAVAILABLE; + if (cred->local) { + maj = gss_store_cred(&min, cred->local, input_usage, + gpp_special_mech(desired_mech), + overwrite_cred, default_cred, + elements_stored, cred_usage_stored); + } else if (cred->remote) { + gp_cc_name = strdup(gp_getenv(GP_CCNAME)); + if (!gp_cc_name) { + gp_cc_name = get_def_ccname(); + if (!gp_cc_name) { + maj = GSS_S_FAILURE; + min = ENOMEM; + } + } + min = store_cred(gp_cc_name, cred->remote); + if (min != 0) { + maj = GSS_S_FAILURE; + } else { + maj = GSS_S_COMPLETE; + } + } else { + return GSS_S_NO_CRED; } - maj = gss_store_cred(&min, cred->local, input_usage, - gpp_special_mech(desired_mech), - overwrite_cred, default_cred, - elements_stored, cred_usage_stored); - + free(gp_cc_name); *minor_status = gpp_map_error(min); return maj; } |