summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-03-22 16:52:02 -0400
committerSimo Sorce <simo@redhat.com>2015-03-22 17:01:52 -0400
commitea3b234e7dc56b185e1e25f6041d091e0aaef1c4 (patch)
tree894499fb71272aa5cd2aea96ade589c7dd9dfee5
parent4efb5ab5686d7bfe00e2a387ba66de4e43ddf317 (diff)
downloadgss-proxy-delegate.tar.gz
gss-proxy-delegate.tar.xz
gss-proxy-delegate.zip
-rw-r--r--proxy/src/mechglue/gpp_creds.c143
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;
}