From owner-svn-src-head@FreeBSD.ORG Mon Jun 24 02:19:24 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 46C58F5; Mon, 24 Jun 2013 02:19:24 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 3880917F7; Mon, 24 Jun 2013 02:19:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r5O2JOf7082520; Mon, 24 Jun 2013 02:19:24 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r5O2JO9H082519; Mon, 24 Jun 2013 02:19:24 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201306240219.r5O2JO9H082519@svn.freebsd.org> From: Rick Macklem Date: Mon, 24 Jun 2013 02:19:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r252138 - head/usr.sbin/gssd X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Jun 2013 02:19:24 -0000 Author: rmacklem Date: Mon Jun 24 02:19:23 2013 New Revision: 252138 URL: http://svnweb.freebsd.org/changeset/base/252138 Log: Add a new "-o" option to the gssd which forces gss_init_sec_context() to use DES and the associated old style GSS initialization token. This appears to be required for some non-FreeBSD servers to get a kerberized NFS mount to work. Also, ignore some signals when daemonized, which might fix the gssd from "disappearing" without leaving a core dump. Given the tight timeframe for the FreeBSD9.2 release, I have committed this while waiting for code review. I will commit changes recommended by the review in a separate commit. Reviewed by: dfr (pending) MFC after: 10 days Modified: head/usr.sbin/gssd/gssd.c Modified: head/usr.sbin/gssd/gssd.c ============================================================================== --- head/usr.sbin/gssd/gssd.c Mon Jun 24 01:09:28 2013 (r252137) +++ head/usr.sbin/gssd/gssd.c Mon Jun 24 02:19:23 2013 (r252138) @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #endif #include +#include #include #include #include @@ -73,11 +74,26 @@ 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; +#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 OM_uint32 gssd_get_user_cred(OM_uint32 *, uid_t, gss_cred_id_t *); +#endif extern void gssd_1(struct svc_req *rqstp, SVCXPRT *transp); extern int gssd_syscall(char *path); @@ -103,11 +119,22 @@ main(int argc, char **argv) pref_realm[0] = '\0'; debug = 0; verbose = 0; - while ((ch = getopt(argc, argv, "dvs:c:r:")) != -1) { + while ((ch = getopt(argc, argv, "dovs:c:r:")) != -1) { switch (ch) { case 'd': debug_level++; 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; @@ -149,8 +176,12 @@ 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); + } memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; @@ -336,7 +367,14 @@ gssd_init_sec_context_1_svc(init_sec_con 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) { @@ -411,7 +449,46 @@ gssd_init_sec_context_1_svc(init_sec_con 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, @@ -420,6 +497,8 @@ gssd_init_sec_context_1_svc(init_sec_con 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) { @@ -687,6 +766,11 @@ gssd_acquire_cred_1_svc(acquire_cred_arg 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 (ccfile_dirlist[0] != '\0' && argp->desired_name == 0) { @@ -1026,3 +1110,52 @@ is_a_valid_tgt_cache(const char *filepat #endif /* !WITHOUT_KERBEROS */ } +#ifndef WITHOUT_KERBEROS +/* + * 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 */