diff options
author | sjg <sjg@FreeBSD.org> | 2013-09-05 20:18:59 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2013-09-05 20:18:59 +0000 |
commit | 62bb1062226d3ce6a2350808256a25508978352d (patch) | |
tree | 22b131dceb13c3df96da594fbaadb693504797c7 /usr.sbin/gssd | |
parent | 72ab90509b3a51ab361bf710338f2ef44a4e360d (diff) | |
parent | 04932445481c2cb89ff69a83b961bdef3d64757e (diff) | |
download | FreeBSD-src-62bb1062226d3ce6a2350808256a25508978352d.zip FreeBSD-src-62bb1062226d3ce6a2350808256a25508978352d.tar.gz |
Merge from head
Diffstat (limited to 'usr.sbin/gssd')
-rw-r--r-- | usr.sbin/gssd/gssd.8 | 32 | ||||
-rw-r--r-- | usr.sbin/gssd/gssd.c | 393 |
2 files changed, 407 insertions, 18 deletions
diff --git a/usr.sbin/gssd/gssd.8 b/usr.sbin/gssd/gssd.8 index 73eb6e3..82c5317 100644 --- a/usr.sbin/gssd/gssd.8 +++ b/usr.sbin/gssd/gssd.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 30, 2012 +.Dd July 7, 2013 .Dt GSSD 8 .Os .Sh NAME @@ -34,6 +34,9 @@ .Sh SYNOPSIS .Nm .Op Fl d +.Op Fl h +.Op Fl o +.Op Fl v .Op Fl s Ar dir-list .Op Fl c Ar file-substring .Op Fl r Ar preferred-realm @@ -49,6 +52,29 @@ Run in debug mode. In this mode, .Nm will not fork when it starts. +.It Fl h +Enable support for host-based initiator credentials. +This permits a kerberized NFS mount to use a service principal in +the default Kerberos 5 keytab file for access. +Such access is enabled via the +gssname +option for the +.Xr mount_nfs 8 +command. +.It Fl o +Force use of DES and the associated old style GSS-API initialization token. +This may be required to make kerberized NFS mounts work against some +non-FreeBSD NFS servers. +.It Fl v +Run in verbose mode. +In this mode, +.Nm +will log activity messages to syslog using LOG_INFO | LOG_DAEMON or to +stderr, if the +.Fl d +option has also been specified. +The minor status is logged as a decimal number, since it is actually a +Kerberos return status, which is signed. .It Fl s Ar dir-list Look for an appropriate credential cache file in this list of directories. The list should be full pathnames from root, separated by ':' characters. @@ -79,7 +105,9 @@ by kernel GSS-API services. .Sh EXIT STATUS .Ex -std .Sh SEE ALSO -.Xr gssapi 3 +.Xr gssapi 3 , +.Xr mount_nfs 8 , +.Xr syslog 3 .Sh HISTORY The .Nm diff --git a/usr.sbin/gssd/gssd.c b/usr.sbin/gssd/gssd.c index 9777943..9548b8c 100644 --- a/usr.sbin/gssd/gssd.c +++ b/usr.sbin/gssd/gssd.c @@ -37,10 +37,13 @@ __FBSDID("$FreeBSD$"); #include <ctype.h> #include <dirent.h> #include <err.h> +#include <errno.h> #ifndef WITHOUT_KERBEROS #include <krb5.h> #endif #include <pwd.h> +#include <signal.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -57,6 +60,7 @@ __FBSDID("$FreeBSD$"); #ifndef _PATH_GSSDSOCK #define _PATH_GSSDSOCK "/var/run/gssd.sock" #endif +#define GSSD_CREDENTIAL_CACHE_FILE "/tmp/krb5cc_gssd" struct gss_resource { LIST_ENTRY(gss_resource) gr_link; @@ -70,10 +74,30 @@ uint32_t gss_start_time; int debug_level; static char ccfile_dirlist[PATH_MAX + 1], ccfile_substring[NAME_MAX + 1]; static char pref_realm[1024]; +static int verbose; +static int use_old_des; +static int hostbased_initiator_cred; +#ifndef WITHOUT_KERBEROS +/* 1.2.752.43.13.14 */ +static gss_OID_desc gss_krb5_set_allowable_enctypes_x_desc = +{6, (void *) "\x2a\x85\x70\x2b\x0d\x0e"}; +static gss_OID GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X = + &gss_krb5_set_allowable_enctypes_x_desc; +static gss_OID_desc gss_krb5_mech_oid_x_desc = +{9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; +static gss_OID GSS_KRB5_MECH_OID_X = + &gss_krb5_mech_oid_x_desc; +#endif static void gssd_load_mech(void); static int find_ccache_file(const char *, uid_t, char *); static int is_a_valid_tgt_cache(const char *, uid_t, int *, time_t *); +static void gssd_verbose_out(const char *, ...); +#ifndef WITHOUT_KERBEROS +static krb5_error_code gssd_get_cc_from_keytab(const char *); +static OM_uint32 gssd_get_user_cred(OM_uint32 *, uid_t, gss_cred_id_t *); +#endif +void gssd_terminate(int); extern void gssd_1(struct svc_req *rqstp, SVCXPRT *transp); extern int gssd_syscall(char *path); @@ -98,11 +122,38 @@ main(int argc, char **argv) ccfile_dirlist[0] = '\0'; pref_realm[0] = '\0'; debug = 0; - while ((ch = getopt(argc, argv, "ds:c:r:")) != -1) { + verbose = 0; + while ((ch = getopt(argc, argv, "dhovs:c:r:")) != -1) { switch (ch) { case 'd': debug_level++; break; + case 'h': +#ifndef WITHOUT_KERBEROS + /* + * Enable use of a host based initiator credential + * in the default keytab file. + */ + hostbased_initiator_cred = 1; +#else + errx(1, "This option not available when built" + " without MK_KERBEROS\n"); +#endif + break; + case 'o': +#ifndef WITHOUT_KERBEROS + /* + * Force use of DES and the old type of GSSAPI token. + */ + use_old_des = 1; +#else + errx(1, "This option not available when built" + " without MK_KERBEROS\n"); +#endif + break; + case 'v': + verbose = 1; + break; case 's': #ifndef WITHOUT_KERBEROS /* @@ -141,8 +192,13 @@ main(int argc, char **argv) gssd_load_mech(); - if (!debug_level) + if (!debug_level) { daemon(0, 0); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + } + signal(SIGTERM, gssd_terminate); memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; @@ -298,10 +354,26 @@ gssd_delete_resource(uint64_t id) } } +static void +gssd_verbose_out(const char *fmt, ...) +{ + va_list ap; + + if (verbose != 0) { + va_start(ap, fmt); + if (debug_level == 0) + vsyslog(LOG_INFO | LOG_DAEMON, fmt, ap); + else + vfprintf(stderr, fmt, ap); + va_end(ap); + } +} + bool_t gssd_null_1_svc(void *argp, void *result, struct svc_req *rqstp) { + gssd_verbose_out("gssd_null: done\n"); return (TRUE); } @@ -312,10 +384,27 @@ gssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *r gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; gss_name_t name = GSS_C_NO_NAME; char ccname[PATH_MAX + 5 + 1], *cp, *cp2; - int gotone; + int gotone, gotcred; + OM_uint32 min_stat; +#ifndef WITHOUT_KERBEROS + gss_buffer_desc principal_desc; + char enctype[sizeof(uint32_t)]; + int key_enctype; + OM_uint32 maj_stat; +#endif memset(result, 0, sizeof(*result)); - if (ccfile_dirlist[0] != '\0' && argp->cred == 0) { + if (hostbased_initiator_cred != 0 && argp->cred != 0 && + argp->uid == 0) { + /* + * These credentials are for a host based initiator name + * in a keytab file, which should now have credentials + * in /tmp/krb5cc_gssd, because gss_acquire_cred() did + * the equivalent of "kinit -k". + */ + snprintf(ccname, sizeof(ccname), "FILE:%s", + GSSD_CREDENTIAL_CACHE_FILE); + } else if (ccfile_dirlist[0] != '\0' && argp->cred == 0) { /* * For the "-s" case and no credentials provided as an * argument, search the directory list for an appropriate @@ -336,6 +425,9 @@ gssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *r } while (cp != NULL && *cp != '\0'); if (gotone == 0) { result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_init_sec_context: -s no" + " credential cache file found for uid=%d\n", + (int)argp->uid); return (TRUE); } } else { @@ -361,6 +453,8 @@ gssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *r cred = gssd_find_resource(argp->cred); if (!cred) { result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_init_sec_context: cred" + " resource not found\n"); return (TRUE); } } @@ -368,6 +462,8 @@ gssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *r ctx = gssd_find_resource(argp->ctx); if (!ctx) { result->major_status = GSS_S_CONTEXT_EXPIRED; + gssd_verbose_out("gssd_init_sec_context: context" + " resource not found\n"); return (TRUE); } } @@ -375,15 +471,61 @@ gssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *r name = gssd_find_resource(argp->name); if (!name) { result->major_status = GSS_S_BAD_NAME; + gssd_verbose_out("gssd_init_sec_context: name" + " resource not found\n"); return (TRUE); } } + gotcred = 0; +#ifndef WITHOUT_KERBEROS + if (use_old_des != 0) { + if (cred == GSS_C_NO_CREDENTIAL) { + /* Acquire a credential for the uid. */ + maj_stat = gssd_get_user_cred(&min_stat, argp->uid, + &cred); + if (maj_stat == GSS_S_COMPLETE) + gotcred = 1; + else + gssd_verbose_out("gssd_init_sec_context: " + "get user cred failed uid=%d major=0x%x " + "minor=%d\n", (int)argp->uid, + (unsigned int)maj_stat, (int)min_stat); + } + if (cred != GSS_C_NO_CREDENTIAL) { + key_enctype = ETYPE_DES_CBC_CRC; + enctype[0] = (key_enctype >> 24) & 0xff; + enctype[1] = (key_enctype >> 16) & 0xff; + enctype[2] = (key_enctype >> 8) & 0xff; + enctype[3] = key_enctype & 0xff; + principal_desc.length = sizeof(enctype); + principal_desc.value = enctype; + result->major_status = gss_set_cred_option( + &result->minor_status, &cred, + GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X, + &principal_desc); + gssd_verbose_out("gssd_init_sec_context: set allowable " + "enctype major=0x%x minor=%d\n", + (unsigned int)result->major_status, + (int)result->minor_status); + if (result->major_status != GSS_S_COMPLETE) { + if (gotcred != 0) + gss_release_cred(&min_stat, &cred); + return (TRUE); + } + } + } +#endif result->major_status = gss_init_sec_context(&result->minor_status, cred, &ctx, name, argp->mech_type, argp->req_flags, argp->time_req, argp->input_chan_bindings, &argp->input_token, &result->actual_mech_type, &result->output_token, &result->ret_flags, &result->time_rec); + gssd_verbose_out("gssd_init_sec_context: done major=0x%x minor=%d" + " uid=%d\n", (unsigned int)result->major_status, + (int)result->minor_status, (int)argp->uid); + if (gotcred != 0) + gss_release_cred(&min_stat, &cred); if (result->major_status == GSS_S_COMPLETE || result->major_status == GSS_S_CONTINUE_NEEDED) { @@ -409,6 +551,8 @@ gssd_accept_sec_context_1_svc(accept_sec_context_args *argp, accept_sec_context_ ctx = gssd_find_resource(argp->ctx); if (!ctx) { result->major_status = GSS_S_CONTEXT_EXPIRED; + gssd_verbose_out("gssd_accept_sec_context: ctx" + " resource not found\n"); return (TRUE); } } @@ -416,6 +560,8 @@ gssd_accept_sec_context_1_svc(accept_sec_context_args *argp, accept_sec_context_ cred = gssd_find_resource(argp->cred); if (!cred) { result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_accept_sec_context: cred" + " resource not found\n"); return (TRUE); } } @@ -426,6 +572,8 @@ gssd_accept_sec_context_1_svc(accept_sec_context_args *argp, accept_sec_context_ &src_name, &result->mech_type, &result->output_token, &result->ret_flags, &result->time_rec, &delegated_cred_handle); + gssd_verbose_out("gssd_accept_sec_context: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); if (result->major_status == GSS_S_COMPLETE || result->major_status == GSS_S_CONTINUE_NEEDED) { @@ -454,6 +602,8 @@ gssd_delete_sec_context_1_svc(delete_sec_context_args *argp, delete_sec_context_ result->major_status = GSS_S_COMPLETE; result->minor_status = 0; } + gssd_verbose_out("gssd_delete_sec_context: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -475,6 +625,8 @@ gssd_export_sec_context_1_svc(export_sec_context_args *argp, export_sec_context_ result->interprocess_token.length = 0; result->interprocess_token.value = NULL; } + gssd_verbose_out("gssd_export_sec_context: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -486,6 +638,8 @@ gssd_import_name_1_svc(import_name_args *argp, import_name_res *result, struct s result->major_status = gss_import_name(&result->minor_status, &argp->input_name_buffer, argp->input_name_type, &name); + gssd_verbose_out("gssd_import_name: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); if (result->major_status == GSS_S_COMPLETE) result->output_name = gssd_make_resource(name); @@ -509,6 +663,8 @@ gssd_canonicalize_name_1_svc(canonicalize_name_args *argp, canonicalize_name_res result->major_status = gss_canonicalize_name(&result->minor_status, name, argp->mech_type, &output_name); + gssd_verbose_out("gssd_canonicalize_name: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); if (result->major_status == GSS_S_COMPLETE) result->output_name = gssd_make_resource(output_name); @@ -526,11 +682,14 @@ gssd_export_name_1_svc(export_name_args *argp, export_name_res *result, struct s memset(result, 0, sizeof(*result)); if (!name) { result->major_status = GSS_S_BAD_NAME; + gssd_verbose_out("gssd_export_name: name resource not found\n"); return (TRUE); } result->major_status = gss_export_name(&result->minor_status, name, &result->exported_name); + gssd_verbose_out("gssd_export_name: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -548,6 +707,8 @@ gssd_release_name_1_svc(release_name_args *argp, release_name_res *result, struc result->major_status = GSS_S_COMPLETE; result->minor_status = 0; } + gssd_verbose_out("gssd_release_name: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -557,8 +718,11 @@ gssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struc { gss_name_t name = gssd_find_resource(argp->pname); uid_t uid; - char buf[128]; + char buf[1024], *bufp; struct passwd pwd, *pw; + size_t buflen; + int error; + static size_t buflen_hint = 1024; memset(result, 0, sizeof(*result)); if (name) { @@ -567,7 +731,24 @@ gssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struc name, argp->mech, &uid); if (result->major_status == GSS_S_COMPLETE) { result->uid = uid; - getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw); + buflen = buflen_hint; + for (;;) { + pw = NULL; + bufp = buf; + if (buflen > sizeof(buf)) + bufp = malloc(buflen); + if (bufp == NULL) + break; + error = getpwuid_r(uid, &pwd, bufp, buflen, + &pw); + if (error != ERANGE) + break; + if (buflen > sizeof(buf)) + free(bufp); + buflen += 1024; + if (buflen > buflen_hint) + buflen_hint = buflen; + } if (pw) { int len = NGRPS; int groups[NGRPS]; @@ -579,15 +760,27 @@ gssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struc mem_alloc(len * sizeof(int)); memcpy(result->gidlist.gidlist_val, groups, len * sizeof(int)); + gssd_verbose_out("gssd_pname_to_uid: mapped" + " to uid=%d, gid=%d\n", (int)result->uid, + (int)result->gid); } else { result->gid = 65534; result->gidlist.gidlist_len = 0; result->gidlist.gidlist_val = NULL; + gssd_verbose_out("gssd_pname_to_uid: mapped" + " to uid=%d, but no groups\n", + (int)result->uid); } - } + if (bufp != NULL && buflen > sizeof(buf)) + free(bufp); + } else + gssd_verbose_out("gssd_pname_to_uid: failed major=0x%x" + " minor=%d\n", (unsigned int)result->major_status, + (int)result->minor_status); } else { result->major_status = GSS_S_BAD_NAME; result->minor_status = 0; + gssd_verbose_out("gssd_pname_to_uid: no name\n"); } return (TRUE); @@ -600,8 +793,58 @@ gssd_acquire_cred_1_svc(acquire_cred_args *argp, acquire_cred_res *result, struc gss_cred_id_t cred; char ccname[PATH_MAX + 5 + 1], *cp, *cp2; int gotone; +#ifndef WITHOUT_KERBEROS + gss_buffer_desc namebuf; + uint32_t minstat; + krb5_error_code kret; +#endif memset(result, 0, sizeof(*result)); + if (argp->desired_name) { + desired_name = gssd_find_resource(argp->desired_name); + if (!desired_name) { + result->major_status = GSS_S_BAD_NAME; + gssd_verbose_out("gssd_acquire_cred: no desired name" + " found\n"); + return (TRUE); + } + } + +#ifndef WITHOUT_KERBEROS + if (hostbased_initiator_cred != 0 && argp->desired_name != 0 && + argp->uid == 0 && argp->cred_usage == GSS_C_INITIATE) { + /* This is a host based initiator name in the keytab file. */ + snprintf(ccname, sizeof(ccname), "FILE:%s", + GSSD_CREDENTIAL_CACHE_FILE); + setenv("KRB5CCNAME", ccname, TRUE); + result->major_status = gss_display_name(&result->minor_status, + desired_name, &namebuf, NULL); + gssd_verbose_out("gssd_acquire_cred: desired name for host " + "based initiator cred major=0x%x minor=%d\n", + (unsigned int)result->major_status, + (int)result->minor_status); + if (result->major_status != GSS_S_COMPLETE) + return (TRUE); + if (namebuf.length > PATH_MAX + 5) { + result->minor_status = 0; + result->major_status = GSS_S_FAILURE; + return (TRUE); + } + memcpy(ccname, namebuf.value, namebuf.length); + ccname[namebuf.length] = '\0'; + if ((cp = strchr(ccname, '@')) != NULL) + *cp = '/'; + kret = gssd_get_cc_from_keytab(ccname); + gssd_verbose_out("gssd_acquire_cred: using keytab entry for " + "%s, kerberos ret=%d\n", ccname, (int)kret); + gss_release_buffer(&minstat, &namebuf); + if (kret != 0) { + result->minor_status = kret; + result->major_status = GSS_S_FAILURE; + return (TRUE); + } + } else +#endif /* !WITHOUT_KERBEROS */ if (ccfile_dirlist[0] != '\0' && argp->desired_name == 0) { /* * For the "-s" case and no name provided as an @@ -623,8 +866,11 @@ gssd_acquire_cred_1_svc(acquire_cred_args *argp, acquire_cred_res *result, struc } while (cp != NULL && *cp != '\0'); if (gotone == 0) { result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_acquire_cred: no cred cache" + " file found\n"); return (TRUE); } + setenv("KRB5CCNAME", ccname, TRUE); } else { /* * If there wasn't a "-s" option or the name has @@ -642,20 +888,14 @@ gssd_acquire_cred_1_svc(acquire_cred_args *argp, acquire_cred_res *result, struc } snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%d", (int) argp->uid); - } - setenv("KRB5CCNAME", ccname, TRUE); - - if (argp->desired_name) { - desired_name = gssd_find_resource(argp->desired_name); - if (!desired_name) { - result->major_status = GSS_S_BAD_NAME; - return (TRUE); - } + setenv("KRB5CCNAME", ccname, TRUE); } result->major_status = gss_acquire_cred(&result->minor_status, desired_name, argp->time_req, argp->desired_mechs, argp->cred_usage, &cred, &result->actual_mechs, &result->time_rec); + gssd_verbose_out("gssd_acquire_cred: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); if (result->major_status == GSS_S_COMPLETE) result->output_cred = gssd_make_resource(cred); @@ -673,11 +913,14 @@ gssd_set_cred_option_1_svc(set_cred_option_args *argp, set_cred_option_res *resu memset(result, 0, sizeof(*result)); if (!cred) { result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_set_cred: no credentials\n"); return (TRUE); } result->major_status = gss_set_cred_option(&result->minor_status, &cred, argp->option_name, &argp->option_value); + gssd_verbose_out("gssd_set_cred: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -695,6 +938,8 @@ gssd_release_cred_1_svc(release_cred_args *argp, release_cred_res *result, struc result->major_status = GSS_S_COMPLETE; result->minor_status = 0; } + gssd_verbose_out("gssd_release_cred: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -707,6 +952,8 @@ gssd_display_status_1_svc(display_status_args *argp, display_status_res *result, result->major_status = gss_display_status(&result->minor_status, argp->status_value, argp->status_type, argp->mech_type, &result->message_context, &result->status_string); + gssd_verbose_out("gssd_display_status: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); return (TRUE); } @@ -780,6 +1027,8 @@ find_ccache_file(const char *dirpath, uid_t uid, char *rpath) len = snprintf(namepath, sizeof(namepath), "%s/%s", dirpath, dp->d_name); if (len < sizeof(namepath) && + (hostbased_initiator_cred == 0 || strcmp(namepath, + GSSD_CREDENTIAL_CACHE_FILE) != 0) && strstr(dp->d_name, ccfile_substring) != NULL && lstat(namepath, &sb) >= 0 && sb.st_uid == uid && @@ -926,3 +1175,115 @@ is_a_valid_tgt_cache(const char *filepath, uid_t uid, int *retrating, #endif /* !WITHOUT_KERBEROS */ } +#ifndef WITHOUT_KERBEROS +/* + * This function attempts to do essentially a "kinit -k" for the principal + * name provided as the argument, so that there will be a TGT in the + * credential cache. + */ +static krb5_error_code +gssd_get_cc_from_keytab(const char *name) +{ + krb5_error_code ret, opt_ret, princ_ret, cc_ret, kt_ret, cred_ret; + krb5_context context; + krb5_principal principal; + krb5_keytab kt; + krb5_creds cred; + krb5_get_init_creds_opt *opt; + krb5_deltat start_time = 0; + krb5_ccache ccache; + + ret = krb5_init_context(&context); + if (ret != 0) + return (ret); + opt_ret = cc_ret = kt_ret = cred_ret = 1; /* anything non-zero */ + princ_ret = ret = krb5_parse_name(context, name, &principal); + if (ret == 0) + opt_ret = ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret == 0) + cc_ret = ret = krb5_cc_default(context, &ccache); + if (ret == 0) + ret = krb5_cc_initialize(context, ccache, principal); + if (ret == 0) { + krb5_get_init_creds_opt_set_default_flags(context, "gssd", + krb5_principal_get_realm(context, principal), opt); + kt_ret = ret = krb5_kt_default(context, &kt); + } + if (ret == 0) + cred_ret = ret = krb5_get_init_creds_keytab(context, &cred, + principal, kt, start_time, NULL, opt); + if (ret == 0) + ret = krb5_cc_store_cred(context, ccache, &cred); + if (kt_ret == 0) + krb5_kt_close(context, kt); + if (cc_ret == 0) + krb5_cc_close(context, ccache); + if (opt_ret == 0) + krb5_get_init_creds_opt_free(context, opt); + if (princ_ret == 0) + krb5_free_principal(context, principal); + if (cred_ret == 0) + krb5_free_cred_contents(context, &cred); + krb5_free_context(context); + return (ret); +} + +/* + * Acquire a gss credential for a uid. + */ +static OM_uint32 +gssd_get_user_cred(OM_uint32 *min_statp, uid_t uid, gss_cred_id_t *credp) +{ + gss_buffer_desc principal_desc; + gss_name_t name; + OM_uint32 maj_stat, min_stat; + gss_OID_set mechlist; + struct passwd *pw; + + pw = getpwuid(uid); + if (pw == NULL) { + *min_statp = 0; + return (GSS_S_FAILURE); + } + + /* + * The mechanism must be set to KerberosV for acquisition + * of credentials to work reliably. + */ + maj_stat = gss_create_empty_oid_set(min_statp, &mechlist); + if (maj_stat != GSS_S_COMPLETE) + return (maj_stat); + maj_stat = gss_add_oid_set_member(min_statp, GSS_KRB5_MECH_OID_X, + &mechlist); + if (maj_stat != GSS_S_COMPLETE) { + gss_release_oid_set(&min_stat, &mechlist); + return (maj_stat); + } + + principal_desc.value = (void *)pw->pw_name; + principal_desc.length = strlen(pw->pw_name); + maj_stat = gss_import_name(min_statp, &principal_desc, + GSS_C_NT_USER_NAME, &name); + if (maj_stat != GSS_S_COMPLETE) { + gss_release_oid_set(&min_stat, &mechlist); + return (maj_stat); + } + /* Acquire the credentials. */ + maj_stat = gss_acquire_cred(min_statp, name, 0, mechlist, + GSS_C_INITIATE, credp, NULL, NULL); + gss_release_name(&min_stat, &name); + gss_release_oid_set(&min_stat, &mechlist); + return (maj_stat); +} +#endif /* !WITHOUT_KERBEROS */ + +void gssd_terminate(int sig __unused) +{ + +#ifndef WITHOUT_KERBEROS + if (hostbased_initiator_cred != 0) + unlink(GSSD_CREDENTIAL_CACHE_FILE); +#endif + exit(0); +} + |