diff options
-rw-r--r-- | utils/gssd/Makefile.am | 2 | ||||
-rw-r--r-- | utils/gssd/gss_util.c | 25 | ||||
-rw-r--r-- | utils/gssd/svcgssd.c | 7 | ||||
-rw-r--r-- | utils/gssd/svcgssd_krb5.c | 200 | ||||
-rw-r--r-- | utils/gssd/svcgssd_krb5.h | 36 | ||||
-rw-r--r-- | utils/gssd/svcgssd_proc.c | 5 |
6 files changed, 265 insertions, 10 deletions
diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am index 95a2bd0..d7888ad 100644 --- a/utils/gssd/Makefile.am +++ b/utils/gssd/Makefile.am @@ -51,7 +51,9 @@ svcgssd_SOURCES = \ svcgssd_main_loop.c \ svcgssd_mech2file.c \ svcgssd_proc.c \ + svcgssd_krb5.c \ \ + svcgssd_krb5.h \ svcgssd.h svcgssd_LDADD = \ diff --git a/utils/gssd/gss_util.c b/utils/gssd/gss_util.c index ee304cc..ca27d61 100644 --- a/utils/gssd/gss_util.c +++ b/utils/gssd/gss_util.c @@ -276,20 +276,25 @@ gssd_acquire_cred(char *server_name, const gss_OID oid) u_int32_t ignore_maj_stat, ignore_min_stat; gss_buffer_desc pbuf; - name.value = (void *)server_name; - name.length = strlen(server_name); + /* If server_name is NULL, get cred for GSS_C_NO_NAME */ + if (server_name == NULL) { + target_name = GSS_C_NO_NAME; + } else { + name.value = (void *)server_name; + name.length = strlen(server_name); - maj_stat = gss_import_name(&min_stat, &name, - oid, - &target_name); + maj_stat = gss_import_name(&min_stat, &name, + oid, + &target_name); - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid); - return (FALSE); + if (maj_stat != GSS_S_COMPLETE) { + pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid); + return (FALSE); + } } - maj_stat = gss_acquire_cred(&min_stat, target_name, 0, - GSS_C_NULL_OID_SET, GSS_C_ACCEPT, + maj_stat = gss_acquire_cred(&min_stat, target_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_ACCEPT, &gssd_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c index 17af2da..1afff9e 100644 --- a/utils/gssd/svcgssd.c +++ b/utils/gssd/svcgssd.c @@ -262,6 +262,13 @@ main(int argc, char *argv[]) "/etc/krb5.keytab?\n"); exit(1); } + } else { + status = gssd_acquire_cred(NULL, + (const gss_OID)GSS_C_NT_HOSTBASED_SERVICE); + if (status == FALSE) { + printerr(0, "unable to obtain nameless credentials\n"); + exit(1); + } } if (!fg) diff --git a/utils/gssd/svcgssd_krb5.c b/utils/gssd/svcgssd_krb5.c new file mode 100644 index 0000000..fc67a6f --- /dev/null +++ b/utils/gssd/svcgssd_krb5.c @@ -0,0 +1,200 @@ +/* + * COPYRIGHT (c) 2011 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> +#include <errno.h> +#include <gssapi/gssapi.h> +#include <krb5.h> + +#include "gss_util.h" +#include "gss_oids.h" +#include "err_util.h" +#include "svcgssd_krb5.h" + +#define MYBUFLEN 1024 + +char *supported_enctypes_filename = "/proc/fs/nfsd/supported_krb5_enctypes"; +int parsed_num_enctypes = 0; +krb5_enctype *parsed_enctypes = NULL; +char *cached_enctypes = NULL; + +/*==========================*/ +/*=== Internal routines ===*/ +/*==========================*/ + +/* + * Parse the supported encryption type information + */ +static int +parse_enctypes(char *enctypes) +{ + int n = 0; + char *curr, *comma; + int i; + + /* Don't parse the same string over and over... */ + if (cached_enctypes && strcmp(cached_enctypes, enctypes) == 0) + return 0; + + /* Free any existing cached_enctypes */ + free(cached_enctypes); + + if (parsed_enctypes != NULL) { + free(parsed_enctypes); + parsed_enctypes = NULL; + parsed_num_enctypes = 0; + } + + /* count the number of commas */ + for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) { + comma = strchr(curr, ','); + if (comma != NULL) + n++; + else + break; + } + + /* If no more commas and we're not at the end, there's one more value */ + if (*curr != '\0') + n++; + + /* Empty string, return an error */ + if (n == 0) + return ENOENT; + + /* Allocate space for enctypes array */ + if ((parsed_enctypes = (int *) calloc(n, sizeof(int))) == NULL) { + return ENOMEM; + } + + /* Now parse each value into the array */ + for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) { + parsed_enctypes[i++] = atoi(curr); + comma = strchr(curr, ','); + if (comma == NULL) + break; + } + + parsed_num_enctypes = n; + if ((cached_enctypes = malloc(strlen(enctypes)+1))) + strcpy(cached_enctypes, enctypes); + + return 0; +} + +static void +get_kernel_supported_enctypes(void) +{ + FILE *s_e; + int ret; + char buffer[MYBUFLEN + 1]; + + memset(buffer, '\0', sizeof(buffer)); + + s_e = fopen(supported_enctypes_filename, "r"); + if (s_e == NULL) + goto out_clean_parsed; + + ret = fread(buffer, 1, MYBUFLEN, s_e); + if (ret < 0) { + fclose(s_e); + goto out_clean_parsed; + } + fclose(s_e); + if (parse_enctypes(buffer)) { + goto out_clean_parsed; + } +out: + return; + +out_clean_parsed: + if (parsed_enctypes != NULL) { + free(parsed_enctypes); + parsed_num_enctypes = 0; + } + goto out; +} + +/*==========================*/ +/*=== External routines ===*/ +/*==========================*/ + +/* + * Get encryption types supported by the kernel, and then + * call gss_krb5_set_allowable_enctypes() to limit the + * encryption types negotiated. + * + * Returns: + * 0 => all went well + * -1 => there was an error + */ + +int +svcgssd_limit_krb5_enctypes(void) +{ +#ifdef HAVE_SET_ALLOWABLE_ENCTYPES + u_int maj_stat, min_stat; + krb5_enctype default_enctypes[] = { ENCTYPE_DES_CBC_CRC, + ENCTYPE_DES_CBC_MD5, + ENCTYPE_DES_CBC_MD4 }; + int default_num_enctypes = + sizeof(default_enctypes) / sizeof(default_enctypes[0]); + krb5_enctype *enctypes; + int num_enctypes; + + get_kernel_supported_enctypes(); + + if (parsed_enctypes != NULL) { + enctypes = parsed_enctypes; + num_enctypes = parsed_num_enctypes; + } else { + enctypes = default_enctypes; + num_enctypes = default_num_enctypes; + } + + maj_stat = gss_set_allowable_enctypes(&min_stat, gssd_creds, + &krb5oid, num_enctypes, enctypes); + if (maj_stat != GSS_S_COMPLETE) { + printerr(1, "WARNING: gss_set_allowable_enctypes failed\n"); + pgsserr("svcgssd_limit_krb5_enctypes: gss_set_allowable_enctypes", + maj_stat, min_stat, &krb5oid); + return -1; + } +#endif + return 0; +} diff --git a/utils/gssd/svcgssd_krb5.h b/utils/gssd/svcgssd_krb5.h new file mode 100644 index 0000000..07d5eb9 --- /dev/null +++ b/utils/gssd/svcgssd_krb5.h @@ -0,0 +1,36 @@ +/* + * COPYRIGHT (c) 2011 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#ifndef SVCGSSD_KRB5_H +#define SVCGSSD_KRB5_H + +int svcgssd_limit_krb5_enctypes(void); + +#endif /* SVCGSSD_KRB5_H */ diff --git a/utils/gssd/svcgssd_proc.c b/utils/gssd/svcgssd_proc.c index 0ecbab6..7a916d7 100644 --- a/utils/gssd/svcgssd_proc.c +++ b/utils/gssd/svcgssd_proc.c @@ -57,6 +57,7 @@ #include "err_util.h" #include "context.h" #include "gss_oids.h" +#include "svcgssd_krb5.h" extern char * mech2file(gss_OID mech); #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel" @@ -443,6 +444,10 @@ handle_nullreq(FILE *f) { memcpy(&ctx, in_handle.value, in_handle.length); } + if (svcgssd_limit_krb5_enctypes()) { + goto out_err; + } + maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds, &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name, &mech, &out_tok, &ret_flags, NULL, NULL); |