0d4651fac9
k5login_directory settings for krb5.conf (#539423)
334 lines
12 KiB
Diff
334 lines
12 KiB
Diff
commit 3ec524d3aa8f92b150a02062ae8faf0bb2ffaa9d
|
|
Author: ghudson <ghudson@dc483132-0cff-0310-8789-dd5450dbe970>
|
|
Date: Fri Oct 1 15:56:30 2010 +0000
|
|
|
|
ticket: 6792
|
|
subject: Implement k5login_directory and k5login_authoritative options
|
|
|
|
Add and document two new options for controlling k5login behavior.
|
|
|
|
|
|
git-svn-id: svn://anonsvn.mit.edu:/krb5/trunk@24402 dc483132-0cff-0310-8789-dd5450dbe970
|
|
|
|
diff --git a/doc/admin.texinfo b/doc/admin.texinfo
|
|
index 8603b93..2a811de 100644
|
|
--- a/doc/admin.texinfo
|
|
+++ b/doc/admin.texinfo
|
|
@@ -468,6 +468,20 @@ Sets the maximum allowable amount of clockskew in seconds that the
|
|
library will tolerate before assuming that a Kerberos message is
|
|
invalid. The default value is @value{DefaultClockskew}.
|
|
|
|
+@itemx k5login_authoritative
|
|
+If the value of this relation is true (the default), principals must
|
|
+be listed in a local user's k5login file to be granted login access,
|
|
+if a k5login file exists. If the value of this relation is false, a
|
|
+principal may still be granted login access through other mechanisms
|
|
+even if a k5login file exists but does not list the principal.
|
|
+
|
|
+@itemx k5login_directory
|
|
+If set, the library will look for a local user's k5login file within the
|
|
+named directory, with a filename corresponding to the local username.
|
|
+If not set, the library will look for k5login files in the user's home
|
|
+directory, with the filename @code{.k5login}. For security reasons,
|
|
+k5login files must be owned by the local user or by root.
|
|
+
|
|
@itemx kdc_timesync
|
|
If this is set to 1 (for true), then client machines will compute the
|
|
difference between their time and the time returned by the KDC in the
|
|
diff --git a/src/config-files/krb5.conf.M b/src/config-files/krb5.conf.M
|
|
index 2995aa2..e658e89 100644
|
|
--- a/src/config-files/krb5.conf.M
|
|
+++ b/src/config-files/krb5.conf.M
|
|
@@ -155,6 +155,20 @@ This relation sets the maximum allowable amount of clockskew in seconds
|
|
that the library will tolerate before assuming that a Kerberos message
|
|
is invalid. The default value is 300 seconds, or five minutes.
|
|
|
|
+.IP k5login_authoritative
|
|
+If the value of this relation is true (the default), principals must
|
|
+be listed in a local user's k5login file to be granted login access,
|
|
+if a k5login file exists. If the value of this relation is false, a
|
|
+principal may still be granted login access through other mechanisms
|
|
+even if a k5login file exists but does not list the principal.
|
|
+
|
|
+.IP k5login_directory
|
|
+If set, the library will look for a local user's k5login file within
|
|
+the named directory, with a filename corresponding to the local
|
|
+username. If not set, the library will look for k5login files in the
|
|
+user's home directory, with the filename .k5login. For security
|
|
+reasons, k5login files must be owned by the local user or by root.
|
|
+
|
|
.IP kdc_timesync
|
|
If the value of this relation is non-zero (the default), the library
|
|
will compute the difference between the system clock and the time
|
|
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
|
index 750f989..f2a037c 100644
|
|
--- a/src/include/k5-int.h
|
|
+++ b/src/include/k5-int.h
|
|
@@ -222,6 +222,8 @@ typedef INT64_TYPE krb5_int64;
|
|
#define KRB5_CONF_IPROP_PORT "iprop_port"
|
|
#define KRB5_CONF_IPROP_SLAVE_POLL "iprop_slave_poll"
|
|
#define KRB5_CONF_IPROP_LOGFILE "iprop_logfile"
|
|
+#define KRB5_CONF_K5LOGIN_AUTHORITATIVE "k5login_authoritative"
|
|
+#define KRB5_CONF_K5LOGIN_DIRECTORY "k5login_directory"
|
|
#define KRB5_CONF_KADMIND_PORT "kadmind_port"
|
|
#define KRB5_CONF_KRB524_SERVER "krb524_server"
|
|
#define KRB5_CONF_KDC "kdc"
|
|
diff --git a/src/lib/krb5/os/kuserok.c b/src/lib/krb5/os/kuserok.c
|
|
index 1bc7505..985bb14 100644
|
|
--- a/src/lib/krb5/os/kuserok.c
|
|
+++ b/src/lib/krb5/os/kuserok.c
|
|
@@ -48,105 +48,138 @@
|
|
#define FILE_OWNER_OK(UID) ((UID) == 0)
|
|
#endif
|
|
|
|
+enum result { ACCEPT, REJECT, PASS };
|
|
+
|
|
/*
|
|
- * Given a Kerberos principal "principal", and a local username "luser",
|
|
- * determine whether user is authorized to login according to the
|
|
- * authorization file ("~luser/.k5login" by default). Returns TRUE
|
|
- * if authorized, FALSE if not authorized.
|
|
- *
|
|
- * If there is no account for "luser" on the local machine, returns
|
|
- * FALSE. If there is no authorization file, and the given Kerberos
|
|
- * name "server" translates to the same name as "luser" (using
|
|
- * krb5_aname_to_lname()), returns TRUE. Otherwise, if the authorization file
|
|
- * can't be accessed, returns FALSE. Otherwise, the file is read for
|
|
- * a matching principal name, instance, and realm. If one is found,
|
|
- * returns TRUE, if none is found, returns FALSE.
|
|
- *
|
|
- * The file entries are in the format produced by krb5_unparse_name(),
|
|
- * one entry per line.
|
|
- *
|
|
+ * Find the k5login filename for luser, either in the user's homedir or in a
|
|
+ * configured directory under the username.
|
|
*/
|
|
+static krb5_error_code
|
|
+get_k5login_filename(krb5_context context, const char *luser,
|
|
+ const char *homedir, char **filename_out)
|
|
+{
|
|
+ krb5_error_code ret;
|
|
+ char *dir, *filename;
|
|
|
|
-krb5_boolean KRB5_CALLCONV
|
|
-krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
|
|
+ *filename_out = NULL;
|
|
+ ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
|
|
+ KRB5_CONF_K5LOGIN_DIRECTORY, NULL, NULL, &dir);
|
|
+ if (ret != 0)
|
|
+ return ret;
|
|
+
|
|
+ if (dir == NULL) {
|
|
+ /* Look in the user's homedir. */
|
|
+ if (asprintf(&filename, "%s/.k5login", homedir) < 0)
|
|
+ return ENOMEM;
|
|
+ } else {
|
|
+ /* Look in the configured directory. */
|
|
+ if (asprintf(&filename, "%s/%s", dir, luser) < 0)
|
|
+ ret = ENOMEM;
|
|
+ profile_release_string(dir);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+ *filename_out = filename;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Determine whether principal is authorized to log in as luser according to
|
|
+ * the user's k5login file. Return ACCEPT if the k5login file authorizes the
|
|
+ * principal, PASS if the k5login file does not exist, or REJECT if the k5login
|
|
+ * file exists but does not authorize the principal. If k5login files are
|
|
+ * configured to be non-authoritative, pass instead of rejecting.
|
|
+ */
|
|
+static enum result
|
|
+k5login_ok(krb5_context context, krb5_principal principal, const char *luser)
|
|
{
|
|
+ int authoritative = TRUE;
|
|
+ enum result result = REJECT;
|
|
+ char *filename = NULL, *princname = NULL;
|
|
+ char gobble, *newline, linebuf[BUFSIZ], pwbuf[BUFSIZ];
|
|
struct stat sbuf;
|
|
- struct passwd *pwd;
|
|
- char pbuf[MAXPATHLEN];
|
|
- krb5_boolean isok = FALSE;
|
|
- FILE *fp;
|
|
- char kuser[MAX_USERNAME];
|
|
- char *princname;
|
|
- char linebuf[BUFSIZ];
|
|
- char *newline;
|
|
- int gobble;
|
|
- char pwbuf[BUFSIZ];
|
|
- struct passwd pwx;
|
|
- int result;
|
|
-
|
|
- /* no account => no access */
|
|
+ struct passwd pwx, *pwd;
|
|
+ FILE *fp = NULL;
|
|
+
|
|
+ if (profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS,
|
|
+ KRB5_CONF_K5LOGIN_AUTHORITATIVE, NULL, TRUE,
|
|
+ &authoritative) != 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ /* Get the local user's homedir and uid. */
|
|
if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
|
|
- return(FALSE);
|
|
- result = snprintf(pbuf, sizeof(pbuf), "%s/.k5login", pwd->pw_dir);
|
|
- if (SNPRINTF_OVERFLOW(result, sizeof(pbuf)))
|
|
- return(FALSE);
|
|
-
|
|
- if (access(pbuf, F_OK)) { /* not accessible */
|
|
- /*
|
|
- * if he's trying to log in as himself, and there is no .k5login file,
|
|
- * let him. To find out, call
|
|
- * krb5_aname_to_localname to convert the principal to a name
|
|
- * which we can string compare.
|
|
- */
|
|
- if (!(krb5_aname_to_localname(context, principal,
|
|
- sizeof(kuser), kuser))
|
|
- && (strcmp(kuser, luser) == 0)) {
|
|
- return(TRUE);
|
|
- }
|
|
- }
|
|
- if (krb5_unparse_name(context, principal, &princname))
|
|
- return(FALSE); /* no hope of matching */
|
|
+ goto cleanup;
|
|
+
|
|
+ if (get_k5login_filename(context, luser, pwd->pw_dir, &filename) != 0)
|
|
+ goto cleanup;
|
|
|
|
- /* open ~/.k5login */
|
|
- if ((fp = fopen(pbuf, "r")) == NULL) {
|
|
- free(princname);
|
|
- return(FALSE);
|
|
+ if (access(filename, F_OK) != 0) {
|
|
+ result = PASS;
|
|
+ goto cleanup;
|
|
}
|
|
+
|
|
+ if (krb5_unparse_name(context, principal, &princname) != 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ fp = fopen(filename, "r");
|
|
+ if (fp == NULL)
|
|
+ goto cleanup;
|
|
set_cloexec_file(fp);
|
|
- /*
|
|
- * For security reasons, the .k5login file must be owned either by
|
|
- * the user himself, or by root. Otherwise, don't grant access.
|
|
- */
|
|
- if (fstat(fileno(fp), &sbuf)) {
|
|
- fclose(fp);
|
|
- free(princname);
|
|
- return(FALSE);
|
|
- }
|
|
- if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) {
|
|
- fclose(fp);
|
|
- free(princname);
|
|
- return(FALSE);
|
|
- }
|
|
|
|
- /* check each line */
|
|
- while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
|
|
- /* null-terminate the input string */
|
|
- linebuf[BUFSIZ-1] = '\0';
|
|
- newline = NULL;
|
|
- /* nuke the newline if it exists */
|
|
- if ((newline = strchr(linebuf, '\n')))
|
|
+ /* For security reasons, the .k5login file must be owned either by
|
|
+ * the user or by root. */
|
|
+ if (fstat(fileno(fp), &sbuf))
|
|
+ goto cleanup;
|
|
+ if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid))
|
|
+ goto cleanup;
|
|
+
|
|
+ /* Check each line. */
|
|
+ while (result != ACCEPT && (fgets(linebuf, sizeof(linebuf), fp) != NULL)) {
|
|
+ newline = strrchr(linebuf, '\n');
|
|
+ if (newline != NULL)
|
|
*newline = '\0';
|
|
- if (!strcmp(linebuf, princname)) {
|
|
- isok = TRUE;
|
|
- continue;
|
|
- }
|
|
- /* clean up the rest of the line if necessary */
|
|
- if (!newline)
|
|
+ if (strcmp(linebuf, princname) == 0)
|
|
+ result = ACCEPT;
|
|
+ /* Clean up the rest of the line if necessary. */
|
|
+ if (newline == NULL)
|
|
while (((gobble = getc(fp)) != EOF) && gobble != '\n');
|
|
}
|
|
+
|
|
+cleanup:
|
|
free(princname);
|
|
- fclose(fp);
|
|
- return(isok);
|
|
+ free(filename);
|
|
+ if (fp != NULL)
|
|
+ fclose(fp);
|
|
+ /* If k5login files are non-authoritative, never reject. */
|
|
+ return (!authoritative && result == REJECT) ? PASS : result;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Determine whether principal is authorized to log in as luser according to
|
|
+ * aname-to-localname translation. Return ACCEPT if principal translates to
|
|
+ * luser or PASS if it does not.
|
|
+ */
|
|
+static enum result
|
|
+an2ln_ok(krb5_context context, krb5_principal principal, const char *luser)
|
|
+{
|
|
+ krb5_error_code ret;
|
|
+ char kuser[MAX_USERNAME];
|
|
+
|
|
+ ret = krb5_aname_to_localname(context, principal, sizeof(kuser), kuser);
|
|
+ if (ret != 0)
|
|
+ return PASS;
|
|
+ return (strcmp(kuser, luser) == 0) ? ACCEPT : PASS;
|
|
+}
|
|
+
|
|
+krb5_boolean KRB5_CALLCONV
|
|
+krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
|
|
+{
|
|
+ enum result result;
|
|
+
|
|
+ result = k5login_ok(context, principal, luser);
|
|
+ if (result == PASS)
|
|
+ result = an2ln_ok(context, principal, luser);
|
|
+ return (result == ACCEPT) ? TRUE : FALSE;
|
|
}
|
|
|
|
#else /* _WIN32 */
|
|
commit 6f46ab42b718410aee67a888b3fefe7df8ce2062
|
|
Author: ghudson <ghudson@dc483132-0cff-0310-8789-dd5450dbe970>
|
|
Date: Sat Oct 2 11:48:06 2010 +0000
|
|
|
|
ticket: 6792
|
|
|
|
In the krb5_kuserok implementation, fix an unintentional type change
|
|
to "gobble" (was an int, was accidentally changed to a char) which
|
|
could result in an infinite loop.
|
|
|
|
|
|
git-svn-id: svn://anonsvn.mit.edu:/krb5/trunk@24413 dc483132-0cff-0310-8789-dd5450dbe970
|
|
|
|
diff --git a/src/lib/krb5/os/kuserok.c b/src/lib/krb5/os/kuserok.c
|
|
index 985bb14..e1619f3 100644
|
|
--- a/src/lib/krb5/os/kuserok.c
|
|
+++ b/src/lib/krb5/os/kuserok.c
|
|
@@ -93,10 +93,10 @@ get_k5login_filename(krb5_context context, const char *luser,
|
|
static enum result
|
|
k5login_ok(krb5_context context, krb5_principal principal, const char *luser)
|
|
{
|
|
- int authoritative = TRUE;
|
|
+ int authoritative = TRUE, gobble;
|
|
enum result result = REJECT;
|
|
char *filename = NULL, *princname = NULL;
|
|
- char gobble, *newline, linebuf[BUFSIZ], pwbuf[BUFSIZ];
|
|
+ char *newline, linebuf[BUFSIZ], pwbuf[BUFSIZ];
|
|
struct stat sbuf;
|
|
struct passwd pwx, *pwd;
|
|
FILE *fp = NULL;
|