static OM_uint32
enumerateAttributes(OM_uint32 *minor, gss_name_t name, int noisy);
+static OM_uint32
+showLocalIdentity(OM_uint32 *minor, gss_name_t name);
static void
usage()
return -1;
}
enumerateAttributes(&min_stat, client, TRUE);
+ showLocalIdentity(&min_stat, client);
maj_stat = gss_release_name(&min_stat, &client);
if (maj_stat != GSS_S_COMPLETE) {
display_status("releasing name", maj_stat, min_stat);
return major;
}
+
+static OM_uint32
+showLocalIdentity(OM_uint32 *minor, gss_name_t name)
+{
+ OM_uint32 major;
+ uid_t uid;
+
+ major = gss_pname_to_uid(minor, name, GSS_C_NO_OID, &uid);
+ if (major == GSS_S_COMPLETE)
+ printf("UID: %lu\n", (unsigned long)uid);
+ else if (major != GSS_S_UNAVAILABLE)
+ display_status("gss_pname_to_uid", major, *minor);
+
+ return major;
+}
extern "C" {
#endif /* __cplusplus */
-#if 0
/*
* Solaris extensions
*/
-int KRB5_CALLCONV gssd_pname_to_uid
- (char *,
- gss_OID,
- gss_OID,
- uid_t *);
-
-int KRB5_CALLCONV __gss_userok
- (const gss_name_t /*name*/,
- const char * /*username*/);
-#endif
+OM_uint32 KRB5_CALLCONV
+gss_pname_to_uid
+ (OM_uint32 *minor,
+ const gss_name_t name,
+ const gss_OID mech_type,
+ uid_t *uidOut);
+
+OM_uint32 KRB5_CALLCONV
+gss_userok(OM_uint32 *minor,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok);
OM_uint32 KRB5_CALLCONV
gss_acquire_cred_with_password(
/*
* Naming extensions
*/
+GSS_DLLIMP extern gss_buffer_t GSS_C_ATTR_LOCAL_LOGIN_USER;
+
OM_uint32 KRB5_CALLCONV gss_display_name_ext
(
OM_uint32 *, /* minor_status */
return GSS_S_BAD_MECH_ATTR;
}
+
+static gss_buffer_desc const_attrs[] = {
+ { sizeof("local-login-user") - 1,
+ "local-login-user" },
+};
+
+GSS_DLLIMP gss_buffer_t GSS_C_ATTR_LOCAL_LOGIN_USER = &const_attrs[0];
#include "gssapiP_krb5.h"
#include "mglueP.h"
+#ifndef NO_PASSWORD
+#include <pwd.h>
+#endif
+
/** exported constants defined in gssapi_krb5{,_nx}.h **/
/* these are bogus, but will compile */
return major;
}
+#ifndef NO_PASSWORD
+static OM_uint32
+krb5_gss_pname_to_uid(OM_uint32 *minor,
+ const gss_name_t pname,
+ const gss_OID mech_type,
+ uid_t *uid)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ char localname[BUFSIZ], pwbuf[BUFSIZ];
+ struct passwd pwx, *pw;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(pname)) {
+ *minor = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)pname;
+
+ code = krb5_aname_to_localname(context, kname->princ,
+ sizeof(localname), localname);
+ if (code != 0) {
+ *minor = KRB5_NO_LOCALNAME;
+ krb5_free_context(context);
+ return GSS_S_FAILURE;
+ }
+
+ code = k5_getpwnam_r(localname, &pwx, pwbuf, sizeof(pwbuf), &pw);
+ if (code == 0 && pw != NULL)
+ *uid = pw->pw_uid;
+ else
+ *minor = KRB5_NO_LOCALNAME;
+
+ krb5_free_context(context);
+
+ return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+#endif /* !NO_PASSWORD */
+
+static OM_uint32
+krb5_gss_userok(OM_uint32 *minor,
+ const gss_name_t pname,
+ const char *local_user,
+ int *user_ok)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+
+ *minor = 0;
+ *user_ok = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(pname)) {
+ *minor = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)pname;
+
+ *user_ok = krb5_kuserok(context, kname->princ, local_user);
+
+ krb5_free_context(context);
+
+ return GSS_S_COMPLETE;
+}
+
static struct gss_config krb5_mechanism = {
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
NULL,
krb5_gss_inquire_context,
krb5_gss_internal_release_oid,
krb5_gss_wrap_size_limit,
+#ifdef NO_PASSWORD
+ NULL,
+#else
+ krb5_gss_pname_to_uid,
+#endif
+ krb5_gss_userok,
krb5_gss_export_name,
krb5_gss_store_cred,
krb5_gss_inquire_sec_context_by_oid,
+GSS_C_ATTR_LOCAL_LOGIN_USER
GSS_C_INQ_SSPI_SESSION_KEY
GSS_C_NT_ANONYMOUS
GSS_C_NT_EXPORT_NAME
gss_nt_user_name
gss_oid_equal
gss_oid_to_str
+gss_pname_to_uid
gss_pseudo_random
gss_process_context_token
gss_release_any_name_mapping
gss_unwrap
gss_unwrap_aead
gss_unwrap_iov
+gss_userok
gss_verify
gss_verify_mic
gss_wrap
$(srcdir)/g_unseal.c \
$(srcdir)/g_unwrap_aead.c \
$(srcdir)/g_unwrap_iov.c \
+ $(srcdir)/g_userok.c \
$(srcdir)/g_verify.c \
$(srcdir)/g_wrap_aead.c \
- $(srcdir)/g_wrap_iov.c
+ $(srcdir)/g_wrap_iov.c \
+ $(srcdir)/gssd_pname_to_uid.c
OBJS = \
$(OUTPRE)g_accept_sec_context.$(OBJEXT) \
$(OUTPRE)g_unseal.$(OBJEXT) \
$(OUTPRE)g_unwrap_aead.$(OBJEXT) \
$(OUTPRE)g_unwrap_iov.$(OBJEXT) \
+ $(OUTPRE)g_userok.$(OBJEXT) \
$(OUTPRE)g_verify.$(OBJEXT) \
$(OUTPRE)g_wrap_aead.$(OBJEXT) \
- $(OUTPRE)g_wrap_iov.$(OBJEXT)
+ $(OUTPRE)g_wrap_iov.$(OBJEXT) \
+ $(OUTPRE)gssd_pname_to_uid.$(OBJEXT)
STLIBOBJS = \
g_accept_sec_context.o \
g_unseal.o \
g_unwrap_aead.o \
g_unwrap_iov.o \
+ g_userok.o \
g_verify.o \
g_wrap_aead.o \
- g_wrap_iov.o
+ g_wrap_iov.o \
+ gssd_pname_to_uid.o
EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi
EXPORTED_HEADERS = mechglue.h
+/*
+ * Copyright (c) 2011, PADL Software Pty Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of PADL Software nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#include <mglueP.h>
#include <gssapi/gssapi.h>
+static OM_uint32
+mech_userok(OM_uint32 *minor,
+ const gss_union_name_t unionName,
+ const char *user,
+ int *user_ok)
+{
+ OM_uint32 major = GSS_S_UNAVAILABLE;
+ gss_mechanism mech;
+
+ /* may need to import the name if this is not MN */
+ if (unionName->mech_type == GSS_C_NO_OID)
+ return (GSS_S_FAILURE);
+
+ mech = gssint_get_mechanism(unionName->mech_type);
+ if (mech == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ if (mech->gss_userok) {
+ major = mech->gss_userok(minor, unionName->mech_name, user, user_ok);
+ if (major != GSS_S_COMPLETE)
+ map_error(minor, mech);
+ }
+ return (major);
+}
+
+/*
+ * Naming extensions based local login authorization.
+ */
static OM_uint32
-compare_names(OM_uint32 *minor,
- const gss_OID mech_type,
+attr_userok(OM_uint32 *minor,
const gss_name_t name,
const char *user,
int *user_ok)
{
+ OM_uint32 major = GSS_S_UNAVAILABLE;
+ OM_uint32 tmpMinor;
+ size_t userLen = strlen(user);
+ int more = -1;
+
+ *user_ok = 0;
+
+ while (more != 0 && *user_ok == 0) {
+ gss_buffer_desc value;
+ gss_buffer_desc display_value;
+ int authenticated = 0, complete = 0;
+
+ major = gss_get_name_attribute(minor,
+ name,
+ GSS_C_ATTR_LOCAL_LOGIN_USER,
+ &authenticated,
+ &complete,
+ &value,
+ &display_value,
+ &more);
+ if (GSS_ERROR(major))
+ break;
+
+ if (authenticated &&
+ value.length == userLen &&
+ memcmp(value.value, user, userLen) == 0)
+ *user_ok = 1;
+
+ gss_release_buffer(&tmpMinor, &value);
+ gss_release_buffer(&tmpMinor, &display_value);
+ }
+
+ return (major);
+}
+
+/*
+ * Equality based local login authorization.
+ */
+static OM_uint32
+compare_names_userok(OM_uint32 *minor,
+ const gss_OID mech_type,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok)
+{
OM_uint32 status, tmpMinor;
gss_name_t imported_name;
*user_ok = 0;
gss_user.value = (void *)user;
- if (!gss_user.value || !name || !mech_type)
+ if (gss_user.value == NULL ||
+ name == GSS_C_NO_NAME ||
+ mech_type == GSS_C_NO_OID)
return (GSS_S_BAD_NAME);
gss_user.length = strlen(gss_user.value);
OM_uint32
-gssint_userok(OM_uint32 *minor,
- const gss_name_t name,
- const char *user,
- int *user_ok)
+gss_userok(OM_uint32 *minor,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok)
{
- gss_mechanism mech;
- gss_union_name_t intName;
- gss_name_t mechName = NULL;
OM_uint32 major;
+ gss_union_name_t unionName;
if (minor == NULL || user_ok == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
return (GSS_S_CALL_INACCESSIBLE_READ);
*user_ok = 0;
- *minor = GSS_S_COMPLETE;
+ *minor = 0;
- intName = (gss_union_name_t)name;
+ unionName = (gss_union_name_t)name;
- mech = gssint_get_mechanism(intName->mech_type);
- if (mech == NULL)
- return (GSS_S_UNAVAILABLE);
+ /* If mech returns yes, we return yes */
+ major = mech_userok(minor, unionName, user, user_ok);
+ if (major == GSS_S_COMPLETE && *user_ok)
+ return (GSS_S_COMPLETE);
- /* may need to import the name if this is not MN */
- if (intName->mech_type == NULL) {
- return (GSS_S_FAILURE);
- } else
- mechName = intName->mech_name;
+ /* If attribute exists, we evaluate attribute */
+ if (attr_userok(minor, name, user, user_ok) == GSS_S_COMPLETE)
+ return (GSS_S_COMPLETE);
- if (mech->gssint_userok) {
- major = mech->gssint_userok(minor, mechName,
- user, user_ok);
- if (major != GSS_S_COMPLETE)
- map_error(minor_status, mech);
- } else
- major = compare_names(minor, intName->mech_type,
- name, user, user_ok);
+ /* If mech returns unavail, we compare the local name */
+ if (major == GSS_S_UNAVAILABLE) {
+ major = compare_names_userok(minor, unionName->mech_type,
+ name, user, user_ok);
+ }
return (major);
} /* gss_userok */
/* #pragma ident "@(#)gssd_pname_to_uid.c 1.18 04/02/23 SMI" */
-
+/*
+ * Copyright (c) 2011, PADL Software Pty Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of PADL Software nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
* Copyright 1996 by Sun Microsystems, Inc.
*
#include "mglueP.h"
-int gssd_pname_to_uid(pname, name_type, mech_type, uid)
+#ifndef NO_PASSWORD
+#include <pwd.h>
+#endif
-char * pname;
-gss_OID name_type;
-gss_OID mech_type;
-uid_t * uid;
+static OM_uint32
+attr_pname_to_uid(OM_uint32 *minor,
+ const gss_mechanism mech,
+ const gss_name_t mech_name,
+ uid_t *uidp)
{
- int status;
- gss_mechanism mech;
+ OM_uint32 major = GSS_S_UNAVAILABLE;
+#ifndef NO_PASSWORD
+ OM_uint32 tmpMinor;
+ int more = -1;
+
+ if (mech->gss_get_name_attribute == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ while (more != 0) {
+ gss_buffer_desc value;
+ gss_buffer_desc display_value;
+ int authenticated = 0, complete = 0, code;
+ char pwbuf[BUFSIZ];
+ struct passwd pw, *pwd;
+ char *localLoginUser;
+
+ major = mech->gss_get_name_attribute(minor,
+ mech_name,
+ GSS_C_ATTR_LOCAL_LOGIN_USER,
+ &authenticated,
+ &complete,
+ &value,
+ &display_value,
+ &more);
+ if (GSS_ERROR(major)) {
+ map_error(minor, mech);
+ break;
+ }
+
+ localLoginUser = malloc(value.length + 1);
+ if (localLoginUser == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ break;
+ }
+
+ memcpy(localLoginUser, value.value, value.length);
+ localLoginUser[value.length] = '\0';
+
+ code = k5_getpwnam_r(localLoginUser, &pw, pwbuf, sizeof(pwbuf), &pwd);
+
+ free(localLoginUser);
+ gss_release_buffer(&tmpMinor, &value);
+ gss_release_buffer(&tmpMinor, &display_value);
+
+ if (code == 0 && pwd != NULL) {
+ *uidp = pwd->pw_uid;
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+ break;
+ } else
+ major = GSS_S_UNAVAILABLE;
+ }
+#endif /* !NO_PASSWORD */
+
+ return major;
+}
+
+OM_uint32
+gss_pname_to_uid(OM_uint32 *minor,
+ const gss_name_t pname,
+ const gss_OID mech_type,
+ uid_t *uidp)
+{
+ OM_uint32 major, tmpMinor;
+ gss_mechanism mech;
+ gss_union_name_t unionName;
+ gss_name_t mechName = GSS_C_NO_NAME, mechNameP;
/*
* find the appropriate mechanism specific pname_to_uid procedure and
* call it.
*/
+ if (minor == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *minor = 0;
+
+ if (pname == GSS_C_NO_NAME)
+ return GSS_S_CALL_INACCESSIBLE_READ;
- mech = gssint_get_mechanism (mech_type);
+ if (uidp == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
- if (mech) {
- if (mech_type == GSS_C_NULL_OID)
- mech_type = &mech->mech_type;
+ unionName = (gss_union_name_t)pname;
- if (mech->pname_to_uid) {
- status = mech->pname_to_uid(pname, name_type, mech_type, uid);
- if (status != GSS_S_COMPLETE)
- map_error(minor_status, mech);
- } else
- status = GSS_S_BAD_MECH;
+ if (mech_type != GSS_C_NO_OID)
+ mech = gssint_get_mechanism(mech_type);
+ else
+ mech = gssint_get_mechanism(unionName->mech_type);
+
+ if (mech == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ /* may need to create a mechanism specific name */
+ if (unionName->mech_type == GSS_C_NO_OID ||
+ (unionName->mech_type != GSS_C_NO_OID &&
+ !g_OID_equal(unionName->mech_type, &mech->mech_type))) {
+ major = gssint_import_internal_name(minor, &mech->mech_type,
+ unionName, &mechName);
+ if (GSS_ERROR(major))
+ return major;
+
+ mechNameP = mechName;
} else
- status = GSS_S_BAD_MECH;
+ mechNameP = unionName->mech_name;
+
+ major = GSS_S_UNAVAILABLE;
+
+ if (mech->gss_pname_to_uid != NULL) {
+ major = mech->gss_pname_to_uid(minor, mechNameP, mech_type, uidp);
+ if (GSS_ERROR(major))
+ map_error(minor, mech);
+ }
+
+ if (GSS_ERROR(major))
+ major = attr_pname_to_uid(minor, mech, mechNameP, uidp);
+
+ if (mechName != GSS_C_NO_NAME)
+ gssint_release_internal_name(&tmpMinor, &mech->mech_type, &mechName);
- return(status);
+ return major;
}
OM_uint32, /* req_output_size */
OM_uint32 * /* max_input_size */
);
-#if 0
- int (*pname_to_uid)
+ OM_uint32 (*gss_pname_to_uid)
(
- char *, /* pname */
- gss_OID, /* name type */
- gss_OID, /* mech type */
+ OM_uint32 *, /* minor */
+ const gss_name_t, /* name */
+ const gss_OID, /* mech_type */
uid_t * /* uid */
- );
- OM_uint32 (*gssint_userok)
+ );
+ OM_uint32 (*gss_userok)
(
OM_uint32 *, /* minor_status */
const gss_name_t, /* pname */
const char *, /* local user */
int * /* user ok? */
/* */);
-#endif
OM_uint32 (*gss_export_name)
(
OM_uint32 *, /* minor_status */
spnego_gss_inquire_context, /* gss_inquire_context */
NULL, /* gss_internal_release_oid */
spnego_gss_wrap_size_limit, /* gss_wrap_size_limit */
+ NULL, /* gssd_pname_to_uid */
+ NULL, /* gss_userok */
NULL, /* gss_export_name */
NULL, /* gss_store_cred */
spnego_gss_inquire_sec_context_by_oid, /* gss_inquire_sec_context_by_oid */