summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2010-10-04 15:34:24 -0400
committerNalin Dahyabhai <nalin@dahyabhai.net>2010-10-04 15:34:24 -0400
commit0d4651fac9141255523bde51cf3f23d66cafc9d8 (patch)
tree4c96160cee0bcb2814f7c0373513b24f08c6b4dc
parent82f4c7f41e7e973dc788fd02fe59878915df7504 (diff)
downloadkrb5-1.8.3-6.fc15.tar.gz
krb5-1.8.3-6.fc15.tar.xz
krb5-1.8.3-6.fc15.zip
- pull down patches from trunk to implement k5login_authoritative andkrb5-1.8.3-6.fc15
k5login_directory settings for krb5.conf (#539423)
-rw-r--r--krb5-trunk-k5login.patch333
1 files changed, 333 insertions, 0 deletions
diff --git a/krb5-trunk-k5login.patch b/krb5-trunk-k5login.patch
new file mode 100644
index 0000000..e3bfc94
--- /dev/null
+++ b/krb5-trunk-k5login.patch
@@ -0,0 +1,333 @@
+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;