summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-07-14 14:32:16 +0200
committerStefan Metzmacher <metze@samba.org>2011-07-15 11:15:05 +0200
commit890c30ce46e4c576e61f8ae0f52d91f0f1ebfeab (patch)
tree9bb7c2cbf0110b1a480473f3038138e4aabf542e /source4/heimdal/lib
parent255e3e18e00f717d99f3bc57c8a8895ff624f3c3 (diff)
downloadsamba-890c30ce46e4c576e61f8ae0f52d91f0f1ebfeab.tar.gz
samba-890c30ce46e4c576e61f8ae0f52d91f0f1ebfeab.tar.bz2
samba-890c30ce46e4c576e61f8ae0f52d91f0f1ebfeab.zip
s4:heimdal: add missing files
metze
Diffstat (limited to 'source4/heimdal/lib')
-rw-r--r--source4/heimdal/lib/gssapi/krb5/authorize_localname.c66
-rw-r--r--source4/heimdal/lib/gssapi/krb5/pname_to_uid.c85
-rw-r--r--source4/heimdal/lib/gssapi/mech/compat.h94
-rw-r--r--source4/heimdal/lib/krb5/aname_to_localname.c90
-rw-r--r--source4/heimdal/lib/krb5/kuserok.c303
5 files changed, 638 insertions, 0 deletions
diff --git a/source4/heimdal/lib/gssapi/krb5/authorize_localname.c b/source4/heimdal/lib/gssapi/krb5/authorize_localname.c
new file mode 100644
index 0000000000..4bab062ac4
--- /dev/null
+++ b/source4/heimdal/lib/gssapi/krb5/authorize_localname.c
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include "gsskrb5_locl.h"
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_authorize_localname(OM_uint32 *minor_status,
+ const gss_name_t input_name,
+ gss_const_buffer_t user_name,
+ gss_const_OID user_name_type)
+{
+ krb5_context context;
+ krb5_principal princ = (krb5_principal)input_name;
+ char *user;
+ int user_ok;
+
+ if (!gss_oid_equal(user_name_type, GSS_C_NT_USER_NAME))
+ return GSS_S_BAD_NAMETYPE;
+
+ GSSAPI_KRB5_INIT(&context);
+
+ user = malloc(user_name->length + 1);
+ if (user == NULL) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ memcpy(user, user_name->value, user_name->length);
+ user[user_name->length] = '\0';
+
+ *minor_status = 0;
+ user_ok = krb5_kuserok(context, princ, user);
+
+ free(user);
+
+ return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED;
+}
diff --git a/source4/heimdal/lib/gssapi/krb5/pname_to_uid.c b/source4/heimdal/lib/gssapi/krb5/pname_to_uid.c
new file mode 100644
index 0000000000..ff754e7798
--- /dev/null
+++ b/source4/heimdal/lib/gssapi/krb5/pname_to_uid.c
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "gsskrb5_locl.h"
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_pname_to_uid(OM_uint32 *minor_status,
+ const gss_name_t pname,
+ const gss_OID mech_type,
+ uid_t *uidp)
+{
+#ifdef NO_LOCALNAME
+ *minor_status = KRB5_NO_LOCALNAME;
+ return GSS_S_FAILURE;
+#else
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_const_principal princ = (krb5_const_principal)pname;
+ char localname[256];
+#ifdef POSIX_GETPWNAM_R
+ char pwbuf[2048];
+ struct passwd pw, *pwd;
+#else
+ struct passwd *pwd;
+#endif
+
+ GSSAPI_KRB5_INIT(&context);
+
+ *minor_status = 0;
+
+ ret = krb5_aname_to_localname(context, princ,
+ sizeof(localname), localname);
+ if (ret != 0) {
+ *minor_status = ret;
+ return GSS_S_FAILURE;
+ }
+
+#ifdef POSIX_GETPWNAM_R
+ if (getpwnam_r(localname, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) {
+ *minor_status = KRB5_NO_LOCALNAME;
+ return GSS_S_FAILURE;
+ }
+#else
+ pwd = getpwnam(localname);
+#endif
+
+ if (pwd == NULL) {
+ *minor_status = KRB5_NO_LOCALNAME;
+ return GSS_S_FAILURE;
+ }
+
+ *uidp = pwd->pw_uid;
+
+ return GSS_S_COMPLETE;
+#endif /* NO_LOCALNAME */
+}
diff --git a/source4/heimdal/lib/gssapi/mech/compat.h b/source4/heimdal/lib/gssapi/mech/compat.h
new file mode 100644
index 0000000000..e63f1e5343
--- /dev/null
+++ b/source4/heimdal/lib/gssapi/mech/compat.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_saslname_for_mech_t (
+ OM_uint32 *, /* minor_status */
+ const gss_OID, /* desired_mech */
+ gss_buffer_t, /* sasl_mech_name */
+ gss_buffer_t, /* mech_name */
+ gss_buffer_t /* mech_description */
+ );
+
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_mech_for_saslname_t (
+ OM_uint32 *, /* minor_status */
+ const gss_buffer_t, /* sasl_mech_name */
+ gss_OID * /* mech_type */
+ );
+
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_attrs_for_mech_t (
+ OM_uint32 *, /* minor_status */
+ gss_const_OID, /* mech */
+ gss_OID_set *, /* mech_attrs */
+ gss_OID_set * /* known_mech_attrs */
+ );
+
+typedef OM_uint32 GSSAPI_CALLCONV _gss_acquire_cred_with_password_t
+ (OM_uint32 *, /* minor_status */
+ const gss_name_t, /* desired_name */
+ const gss_buffer_t, /* password */
+ OM_uint32, /* time_req */
+ const gss_OID_set, /* desired_mechs */
+ gss_cred_usage_t, /* cred_usage */
+ gss_cred_id_t *, /* output_cred_handle */
+ gss_OID_set *, /* actual_mechs */
+ OM_uint32 * /* time_rec */
+ );
+
+typedef OM_uint32 GSSAPI_CALLCONV _gss_add_cred_with_password_t (
+ OM_uint32 *, /* minor_status */
+ const gss_cred_id_t, /* input_cred_handle */
+ const gss_name_t, /* desired_name */
+ const gss_OID, /* desired_mech */
+ const gss_buffer_t, /* password */
+ gss_cred_usage_t, /* cred_usage */
+ OM_uint32, /* initiator_time_req */
+ OM_uint32, /* acceptor_time_req */
+ gss_cred_id_t *, /* output_cred_handle */
+ gss_OID_set *, /* actual_mechs */
+ OM_uint32 *, /* initiator_time_rec */
+ OM_uint32 * /* acceptor_time_rec */
+ );
+
+/*
+ * API-as-SPI compatibility for compatibility with MIT mechanisms;
+ * native Heimdal mechanisms should not use these.
+ */
+struct gss_mech_compat_desc_struct {
+ _gss_inquire_saslname_for_mech_t *gmc_inquire_saslname_for_mech;
+ _gss_inquire_mech_for_saslname_t *gmc_inquire_mech_for_saslname;
+ _gss_inquire_attrs_for_mech_t *gmc_inquire_attrs_for_mech;
+ _gss_acquire_cred_with_password_t *gmc_acquire_cred_with_password;
+#if 0
+ _gss_add_cred_with_password_t *gmc_add_cred_with_password;
+#endif
+};
+
diff --git a/source4/heimdal/lib/krb5/aname_to_localname.c b/source4/heimdal/lib/krb5/aname_to_localname.c
new file mode 100644
index 0000000000..7bfd861da9
--- /dev/null
+++ b/source4/heimdal/lib/krb5/aname_to_localname.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997 - 1999, 2002 - 2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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.
+ */
+
+#include "krb5_locl.h"
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_aname_to_localname (krb5_context context,
+ krb5_const_principal aname,
+ size_t lnsize,
+ char *lname)
+{
+ krb5_error_code ret;
+ krb5_realm *lrealms, *r;
+ int valid;
+ size_t len;
+ const char *res;
+
+ ret = krb5_get_default_realms (context, &lrealms);
+ if (ret)
+ return ret;
+
+ valid = 0;
+ for (r = lrealms; *r != NULL; ++r) {
+ if (strcmp (*r, aname->realm) == 0) {
+ valid = 1;
+ break;
+ }
+ }
+ krb5_free_host_realm (context, lrealms);
+ if (valid == 0)
+ return KRB5_NO_LOCALNAME;
+
+ if (aname->name.name_string.len == 1)
+ res = aname->name.name_string.val[0];
+ else if (aname->name.name_string.len == 2
+ && strcmp (aname->name.name_string.val[1], "root") == 0) {
+ krb5_principal rootprinc;
+ krb5_boolean userok;
+
+ res = "root";
+
+ ret = krb5_copy_principal(context, aname, &rootprinc);
+ if (ret)
+ return ret;
+
+ userok = krb5_kuserok(context, rootprinc, res);
+ krb5_free_principal(context, rootprinc);
+ if (!userok)
+ return KRB5_NO_LOCALNAME;
+
+ } else
+ return KRB5_NO_LOCALNAME;
+
+ len = strlen (res);
+ if (len >= lnsize)
+ return ERANGE;
+ strlcpy (lname, res, lnsize);
+
+ return 0;
+}
diff --git a/source4/heimdal/lib/krb5/kuserok.c b/source4/heimdal/lib/krb5/kuserok.c
new file mode 100644
index 0000000000..2fe4e490aa
--- /dev/null
+++ b/source4/heimdal/lib/krb5/kuserok.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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.
+ */
+
+#include "krb5_locl.h"
+#include <dirent.h>
+
+#ifndef _WIN32
+
+/* see if principal is mentioned in the filename access file, return
+ TRUE (in result) if so, FALSE otherwise */
+
+static krb5_error_code
+check_one_file(krb5_context context,
+ const char *filename,
+ struct passwd *pwd,
+ krb5_principal principal,
+ krb5_boolean *result)
+{
+ FILE *f;
+ char buf[BUFSIZ];
+ krb5_error_code ret;
+ struct stat st;
+
+ *result = FALSE;
+
+ f = fopen (filename, "r");
+ if (f == NULL)
+ return errno;
+ rk_cloexec_file(f);
+
+ /* check type and mode of file */
+ if (fstat(fileno(f), &st) != 0) {
+ fclose (f);
+ return errno;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ fclose (f);
+ return EISDIR;
+ }
+ if (st.st_uid != pwd->pw_uid && st.st_uid != 0) {
+ fclose (f);
+ return EACCES;
+ }
+ if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
+ fclose (f);
+ return EACCES;
+ }
+
+ while (fgets (buf, sizeof(buf), f) != NULL) {
+ krb5_principal tmp;
+ char *newline = buf + strcspn(buf, "\n");
+
+ if(*newline != '\n') {
+ int c;
+ c = fgetc(f);
+ if(c != EOF) {
+ while(c != EOF && c != '\n')
+ c = fgetc(f);
+ /* line was too long, so ignore it */
+ continue;
+ }
+ }
+ *newline = '\0';
+ ret = krb5_parse_name (context, buf, &tmp);
+ if (ret)
+ continue;
+ *result = krb5_principal_compare (context, principal, tmp);
+ krb5_free_principal (context, tmp);
+ if (*result) {
+ fclose (f);
+ return 0;
+ }
+ }
+ fclose (f);
+ return 0;
+}
+
+static krb5_error_code
+check_directory(krb5_context context,
+ const char *dirname,
+ struct passwd *pwd,
+ krb5_principal principal,
+ krb5_boolean *result)
+{
+ DIR *d;
+ struct dirent *dent;
+ char filename[MAXPATHLEN];
+ krb5_error_code ret = 0;
+ struct stat st;
+
+ *result = FALSE;
+
+ if(lstat(dirname, &st) < 0)
+ return errno;
+
+ if (!S_ISDIR(st.st_mode))
+ return ENOTDIR;
+
+ if (st.st_uid != pwd->pw_uid && st.st_uid != 0)
+ return EACCES;
+ if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
+ return EACCES;
+
+ if((d = opendir(dirname)) == NULL)
+ return errno;
+
+ {
+ int fd;
+ struct stat st2;
+
+ fd = dirfd(d);
+ if(fstat(fd, &st2) < 0) {
+ closedir(d);
+ return errno;
+ }
+ if(st.st_dev != st2.st_dev || st.st_ino != st2.st_ino) {
+ closedir(d);
+ return EACCES;
+ }
+ }
+
+ while((dent = readdir(d)) != NULL) {
+ if(strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0 ||
+ dent->d_name[0] == '#' || /* emacs autosave */
+ dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */
+ continue;
+ snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name);
+ ret = check_one_file(context, filename, pwd, principal, result);
+ if(ret == 0 && *result == TRUE)
+ break;
+ ret = 0; /* don't propagate errors upstream */
+ }
+ closedir(d);
+ return ret;
+}
+
+#endif /* !_WIN32 */
+
+static krb5_boolean
+match_local_principals(krb5_context context,
+ krb5_principal principal,
+ const char *luser)
+{
+ krb5_error_code ret;
+ krb5_realm *realms, *r;
+ krb5_boolean result = FALSE;
+
+ /* multi-component principals can never match */
+ if(krb5_principal_get_comp_string(context, principal, 1) != NULL)
+ return FALSE;
+
+ ret = krb5_get_default_realms (context, &realms);
+ if (ret)
+ return FALSE;
+
+ for (r = realms; *r != NULL; ++r) {
+ if(strcmp(krb5_principal_get_realm(context, principal),
+ *r) != 0)
+ continue;
+ if(strcmp(krb5_principal_get_comp_string(context, principal, 0),
+ luser) == 0) {
+ result = TRUE;
+ break;
+ }
+ }
+ krb5_free_host_realm (context, realms);
+ return result;
+}
+
+/**
+ * This function takes the name of a local user and checks if
+ * principal is allowed to log in as that user.
+ *
+ * The user may have a ~/.k5login file listing principals that are
+ * allowed to login as that user. If that file does not exist, all
+ * principals with a first component identical to the username, and a
+ * realm considered local, are allowed access.
+ *
+ * The .k5login file must contain one principal per line, be owned by
+ * user and not be writable by group or other (but must be readable by
+ * anyone).
+ *
+ * Note that if the file exists, no implicit access rights are given
+ * to user@@LOCALREALM.
+ *
+ * Optionally, a set of files may be put in ~/.k5login.d (a
+ * directory), in which case they will all be checked in the same
+ * manner as .k5login. The files may be called anything, but files
+ * starting with a hash (#) , or ending with a tilde (~) are
+ * ignored. Subdirectories are not traversed. Note that this directory
+ * may not be checked by other Kerberos implementations.
+ *
+ * If no configuration file exists, match user against local domains,
+ * ie luser@@LOCAL-REALMS-IN-CONFIGURATION-FILES.
+ *
+ * @param context Kerberos 5 context.
+ * @param principal principal to check if allowed to login
+ * @param luser local user id
+ *
+ * @return returns TRUE if access should be granted, FALSE otherwise.
+ *
+ * @ingroup krb5_support
+ */
+
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
+krb5_kuserok (krb5_context context,
+ krb5_principal principal,
+ const char *luser)
+{
+#ifndef _WIN32
+ char *buf;
+ size_t buflen;
+ struct passwd *pwd = NULL;
+ char *profile_dir = NULL;
+ krb5_error_code ret;
+ krb5_boolean result = FALSE;
+
+ krb5_boolean found_file = FALSE;
+
+#ifdef POSIX_GETPWNAM_R
+ char pwbuf[2048];
+ struct passwd pw;
+
+ if(getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
+ return FALSE;
+#else
+ pwd = getpwnam (luser);
+#endif
+ if (pwd == NULL)
+ return FALSE;
+ profile_dir = pwd->pw_dir;
+
+#define KLOGIN "/.k5login"
+ buflen = strlen(profile_dir) + sizeof(KLOGIN) + 2; /* 2 for .d */
+ buf = malloc(buflen);
+ if(buf == NULL)
+ return FALSE;
+ /* check user's ~/.k5login */
+ strlcpy(buf, profile_dir, buflen);
+ strlcat(buf, KLOGIN, buflen);
+ ret = check_one_file(context, buf, pwd, principal, &result);
+
+ if(ret == 0 && result == TRUE) {
+ free(buf);
+ return TRUE;
+ }
+
+ if(ret != ENOENT)
+ found_file = TRUE;
+
+ strlcat(buf, ".d", buflen);
+ ret = check_directory(context, buf, pwd, principal, &result);
+ free(buf);
+ if(ret == 0 && result == TRUE)
+ return TRUE;
+
+ if(ret != ENOENT && ret != ENOTDIR)
+ found_file = TRUE;
+
+ /* finally if no files exist, allow all principals matching
+ <localuser>@<LOCALREALM> */
+ if(found_file == FALSE)
+ return match_local_principals(context, principal, luser);
+
+ return FALSE;
+#else
+ /* The .k5login file may be on a remote profile and we don't have
+ access to the profile until we have a token handle for the
+ user's credentials. */
+ return match_local_principals(context, principal, luser);
+#endif
+}