diff options
author | Jacques Vidrine <nectar@FreeBSD.org> | 2001-01-24 20:36:33 +0000 |
---|---|---|
committer | Jacques Vidrine <nectar@FreeBSD.org> | 2001-01-24 20:36:33 +0000 |
commit | 31d87969c907658eba1ac1eb5d876fd9b01fb3a9 (patch) | |
tree | e4872a4afdb06e2d416c56b65d7a208238f710b3 /security | |
parent | s/w32/win32/, my fault :Q (diff) |
Bug fixes and paranoia:
compat_heimdal.c:
= Stop shooting at feet when freeing a particular chunk of memory.
Found by complaints from free(), and pinpointed with MALLOC_OPTIONS=A.
pam_krb5_auth.c:
= In addition to dropping and restoring uid when delving in /tmp,
drop and restore gid.
= Explicitly set permissions on the credentials cache for good measure.
The following was
Obtained from: Sam Hartman <hartmans@mit.edu> via bugs.debian.org
support.c:
= verify_krb_v5_tgt: Do a little more to prevent KDC spoofing.
Allow for a key separate from the host key to use only for PAM.
Notes
Notes:
svn path=/head/; revision=37547
Diffstat (limited to 'security')
-rw-r--r-- | security/pam_krb5/files/patch-ab | 5 | ||||
-rw-r--r-- | security/pam_krb5/files/patch-ad | 93 | ||||
-rw-r--r-- | security/pam_krb5/files/patch-af | 108 | ||||
-rw-r--r-- | security/pam_krb5/files/patch-ah | 6 |
4 files changed, 163 insertions, 49 deletions
diff --git a/security/pam_krb5/files/patch-ab b/security/pam_krb5/files/patch-ab index 29f2cac50699..55b8502c3914 100644 --- a/security/pam_krb5/files/patch-ab +++ b/security/pam_krb5/files/patch-ab @@ -1,12 +1,13 @@ --- pam_krb5.h.orig Tue Jan 4 19:08:51 2000 -+++ pam_krb5.h Mon Nov 6 13:42:22 2000 ++++ pam_krb5.h Wed Jan 24 13:37:28 2001 @@ -5,7 +5,18 @@ */ int get_user_info(pam_handle_t *, char *, int, char **); -krb5_error_code pam_prompter(krb5_context, void *, const char *, - const char *, int, krb5_prompt[]); - int verify_krb_v5_tgt(krb5_context, krb5_ccache, int); +-int verify_krb_v5_tgt(krb5_context, krb5_ccache, int); ++int verify_krb_v5_tgt(krb5_context, krb5_ccache, char *, int); void cleanup_cache(pam_handle_t *, void *, int); + +krb5_prompter_fct pam_prompter; diff --git a/security/pam_krb5/files/patch-ad b/security/pam_krb5/files/patch-ad index ee54cfe5b873..e753e20043a7 100644 --- a/security/pam_krb5/files/patch-ad +++ b/security/pam_krb5/files/patch-ad @@ -1,9 +1,11 @@ --- pam_krb5_auth.c.orig Tue Jan 4 19:08:51 2000 -+++ pam_krb5_auth.c Mon Nov 6 13:45:48 2000 -@@ -7,9 +7,11 @@ ++++ pam_krb5_auth.c Wed Jan 24 14:08:18 2001 +@@ -7,18 +7,22 @@ static const char rcsid[] = "$Id: pam_krb5_auth.c,v 1.18 2000/01/04 08:44:08 fcusack Exp $"; ++#include <sys/types.h> ++#include <sys/stat.h> +#include <errno.h> #include <limits.h> /* PATH_MAX */ #include <pwd.h> /* getpwnam */ @@ -12,7 +14,9 @@ #include <strings.h> /* strchr */ #include <syslog.h> /* syslog */ #include <unistd.h> /* chown */ -@@ -19,6 +21,7 @@ +-#include <sys/types.h> /* chown */ + + #include <security/pam_appl.h> #include <security/pam_modules.h> #include <krb5.h> @@ -20,7 +24,7 @@ #include "pam_krb5.h" extern krb5_cc_ops krb5_mcc_ops; -@@ -42,7 +45,7 @@ +@@ -42,7 +46,7 @@ krb5_get_init_creds_opt opts; int pamret, i; @@ -29,7 +33,7 @@ char *princ_name = NULL; char *pass = NULL, *service = NULL; char *prompt = NULL; -@@ -74,13 +77,13 @@ +@@ -74,13 +78,13 @@ } /* Get service name */ @@ -45,7 +49,7 @@ DLOG("krb5_init_context()", error_message(krbret)); return PAM_SERVICE_ERR; } -@@ -93,7 +96,7 @@ +@@ -93,7 +97,7 @@ krb5_get_init_creds_opt_set_forwardable(&opts, 1); /* For CNS */ @@ -54,7 +58,7 @@ /* Solaris dtlogin doesn't call pam_end() on failure */ if (krbret != KRB5_CC_TYPE_EXISTS) { DLOG("krb5_cc_register()", error_message(krbret)); -@@ -103,14 +106,14 @@ +@@ -103,14 +107,14 @@ } /* Get principal name */ @@ -71,7 +75,7 @@ DLOG("krb5_unparse_name()", error_message(krbret)); pamret = PAM_SERVICE_ERR; goto cleanup2; -@@ -126,18 +129,19 @@ +@@ -126,18 +130,19 @@ (void) sprintf(prompt, "Password for %s: ", princ_name); if (try_first_pass || use_first_pass) @@ -94,7 +98,7 @@ DLOG("pam_set_item()", pam_strerror(pamh, pamret)); free(pass); pamret = PAM_SERVICE_ERR; -@@ -145,25 +149,26 @@ +@@ -145,25 +150,26 @@ } free(pass); /* Now we get it back from the library. */ @@ -126,7 +130,7 @@ DLOG("pam_get_item()", pam_strerror(pamh, pamret)); pamret = PAM_SERVICE_ERR; goto cleanup2; -@@ -177,9 +182,8 @@ +@@ -177,9 +183,8 @@ } /* Get a TGT */ @@ -138,7 +142,7 @@ DLOG("krb5_get_init_creds_password()", error_message(krbret)); if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { pass = NULL; -@@ -193,17 +197,17 @@ +@@ -193,17 +198,17 @@ strcpy(cache_name, "MEMORY:"); (void) tmpnam(&cache_name[7]); @@ -159,7 +163,16 @@ DLOG("krb5_cc_store_cred()", error_message(krbret)); (void) krb5_cc_destroy(pam_context, ccache); pamret = PAM_SERVICE_ERR; -@@ -224,7 +228,7 @@ +@@ -211,7 +216,7 @@ + } + + /* Verify it */ +- if (verify_krb_v5_tgt(pam_context, ccache, debug) == -1) { ++ if (verify_krb_v5_tgt(pam_context, ccache, service, debug) == -1) { + (void) krb5_cc_destroy(pam_context, ccache); + pamret = PAM_AUTH_ERR; + goto cleanup; +@@ -224,7 +229,7 @@ pamret = PAM_AUTH_ERR; goto cleanup; } @@ -168,7 +181,15 @@ DLOG("pam_set_data()", pam_strerror(pamh, pamret)); (void) krb5_cc_destroy(pam_context, ccache); pamret = PAM_SERVICE_ERR; -@@ -288,22 +292,22 @@ +@@ -275,6 +280,7 @@ + + int debug = 0; + uid_t euid; ++ gid_t egid; + + if (flags == PAM_REINITIALIZE_CRED) + return PAM_SUCCESS; /* XXX Incorrect behavior */ +@@ -288,30 +294,32 @@ else if (strcmp(argv[i], "no_ccache") == 0) return PAM_SUCCESS; else if (strstr(argv[i], "ccache=") == argv[i]) @@ -195,8 +216,9 @@ DLOG("krb5_init_context()", error_message(krbret)); return PAM_SERVICE_ERR; } -@@ -311,7 +315,8 @@ + euid = geteuid(); /* Usually 0 */ ++ egid = getegid(); /* Retrieve the cache name */ - if (pamret = pam_get_data(pamh, "ccache", (const void **) &ccache_temp)) { @@ -205,7 +227,19 @@ DLOG("pam_get_data()", pam_strerror(pamh, pamret)); pamret = PAM_CRED_UNAVAIL; goto cleanup3; -@@ -340,7 +345,7 @@ +@@ -326,6 +334,11 @@ + } + + /* Avoid following a symlink as root */ ++ if (setegid(pw->pw_gid)) { ++ DLOG("setegid()", name); /* XXX should really log group name or id */ ++ pamret = PAM_SERVICE_ERR; ++ goto cleanup3; ++ } + if (seteuid(pw->pw_uid)) { + DLOG("seteuid()", name); + pamret = PAM_SERVICE_ERR; +@@ -340,7 +353,7 @@ pamret = PAM_BUF_ERR; goto cleanup3; } @@ -214,7 +248,7 @@ } else { /* cache_name was supplied */ char *p = calloc(PATH_MAX + 10, 1); /* should be plenty */ -@@ -357,10 +362,10 @@ +@@ -357,10 +370,10 @@ if (*q == '%') { q++; if (*q == 'u') { @@ -227,7 +261,7 @@ p += strlen(p); } else { /* Not a special token */ -@@ -375,24 +380,27 @@ +@@ -375,24 +388,27 @@ } /* Initialize the new ccache */ @@ -259,7 +293,7 @@ DLOG("krb5_cc_start_seq_get()", error_message(krbret)); (void) krb5_cc_destroy(pam_context, ccache_perm); pamret = PAM_SERVICE_ERR; -@@ -400,9 +408,10 @@ +@@ -400,9 +416,10 @@ } /* Copy the creds (should be two of them) */ @@ -273,7 +307,20 @@ DLOG("krb5_cc_store_cred()", error_message(krbret)); (void) krb5_cc_destroy(pam_context, ccache_perm); krb5_free_cred_contents(pam_context, &creds); -@@ -432,7 +441,7 @@ +@@ -420,6 +437,12 @@ + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } ++ if (chmod(&cache_name[5], (S_IRUSR|S_IWUSR)) == -1) { ++ DLOG("chmod()", strerror(errno)); ++ (void) krb5_cc_destroy(pam_context, ccache_perm); ++ pamret = PAM_SERVICE_ERR; ++ goto cleanup2; ++ } + } + (void) krb5_cc_close(pam_context, ccache_perm); + +@@ -432,7 +455,7 @@ } sprintf(cache_env_name, "KRB5CCNAME=%s", cache_name); @@ -282,3 +329,11 @@ DLOG("pam_putenv()", pam_strerror(pamh, pamret)); (void) krb5_cc_destroy(pam_context, ccache_perm); pamret = PAM_SERVICE_ERR; +@@ -445,6 +468,7 @@ + krb5_free_context(pam_context); + DLOG("exit", pamret ? "failure" : "success"); + (void) seteuid(euid); ++ (void) setegid(egid); + return pamret; + } + diff --git a/security/pam_krb5/files/patch-af b/security/pam_krb5/files/patch-af index 26167b15def5..552f6b726a86 100644 --- a/security/pam_krb5/files/patch-af +++ b/security/pam_krb5/files/patch-af @@ -1,5 +1,5 @@ --- support.c.orig Tue Jan 4 19:08:51 2000 -+++ support.c Mon Nov 6 13:36:39 2000 ++++ support.c Wed Jan 24 13:37:28 2001 @@ -6,11 +6,15 @@ static const char rcsid[] = "$Id: support.c,v 1.8 2000/01/04 09:50:03 fcusack Exp $"; @@ -40,7 +40,7 @@ return pamret; /* Caller should ignore errors for non-response conversations */ -@@ -51,124 +56,6 @@ +@@ -51,172 +56,71 @@ return pamret; } @@ -164,8 +164,30 @@ - /* * This routine with some modification is from the MIT V5B6 appl/bsd/login.c ++ * Modified by Sam Hartman <hartmans@mit.edu> to support PAM services ++ * for Debian. * -@@ -189,8 +76,6 @@ + * Verify the Kerberos ticket-granting ticket just retrieved for the + * user. If the Kerberos server doesn't respond, assume the user is + * trying to fake us out (since we DID just get a TGT from what is + * supposedly our KDC). If the host/<host> service is unknown (i.e., +- * the local keytab doesn't have it), let her in. ++ * the local keytab doesn't have it), and we cannot find another ++ * service we do have, let her in. + * + * Returns 1 for confirmation, -1 for failure, 0 for uncertainty. + */ + int +-verify_krb_v5_tgt(krb5_context context, krb5_ccache ccache, int debug) ++verify_krb_v5_tgt(krb5_context context, krb5_ccache ccache, ++ char * pam_service, int debug) + { + char phost[BUFSIZ]; +- krb5_error_code retval; ++ char *services [3]; ++ char **service; ++ krb5_error_code retval = -1; + krb5_principal princ; krb5_keyblock * keyblock = 0; krb5_data packet; krb5_auth_context auth_context = NULL; @@ -174,38 +196,74 @@ packet.data = 0; -@@ -198,8 +83,8 @@ - * Get the server principal for the local host. - * (Use defaults of "host" and canonicalized local name.) - */ + /* +- * Get the server principal for the local host. +- * (Use defaults of "host" and canonicalized local name.) +- */ - if (retval = krb5_sname_to_principal(context, NULL, NULL, - KRB5_NT_SRV_HST, &princ)) { -+ if ((retval = krb5_sname_to_principal(context, NULL, NULL, KRB5_NT_SRV_HST, -+ &princ)) != 0) { ++ * If possible we want to try and verify the ticket we have ++ * received against a keytab. We will try multiple service ++ * principals, including at least the host principal and the PAM ++ * service principal. The host principal is preferred because access ++ * to that key is generally sufficient to compromise root, while the ++ * service key for this PAM service may be less carefully guarded. ++ * It is important to check the keytab first before the KDC so we do ++ * not get spoofed by a fake KDC.*/ ++ services [0] = "host"; ++ services [1] = pam_service; ++ services [2] = NULL; ++ for ( service = &services[0]; *service != NULL; service++ ) { ++ if ((retval = krb5_sname_to_principal(context, NULL, *service, KRB5_NT_SRV_HST, ++ &princ)) != 0) { if (debug) - syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", - "krb5_sname_to_principal()", error_message(retval)); -@@ -207,7 +92,7 @@ - } +- syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", +- "krb5_sname_to_principal()", error_message(retval)); ++ syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", ++ "krb5_sname_to_principal()", error_message(retval)); + return -1; +- } ++ } - /* Extract the name directly. */ +- /* Extract the name directly. */ - strncpy(phost, krb5_princ_component(c, princ, 1)->data, BUFSIZ); -+ strncpy(phost, compat_princ_component(context, princ, 1), BUFSIZ); - phost[BUFSIZ - 1] = '\0'; - - /* -@@ -215,8 +100,8 @@ - * (use default/configured keytab, kvno IGNORE_VNO to get the - * first match, and enctype is currently ignored anyhow.) - */ +- phost[BUFSIZ - 1] = '\0'; +- +- /* +- * Do we have host/<host> keys? +- * (use default/configured keytab, kvno IGNORE_VNO to get the +- * first match, and enctype is currently ignored anyhow.) +- */ - if (retval = krb5_kt_read_service_key(context, NULL, princ, 0, - ENCTYPE_DES_CBC_MD5, &keyblock)) { -+ if ((retval = krb5_kt_read_service_key(context, NULL, princ, 0, -+ ENCTYPE_DES_CBC_MD5, &keyblock)) != 0) { ++ /* Extract the name directly. */ ++ strncpy(phost, compat_princ_component(context, princ, 1), BUFSIZ); ++ phost[BUFSIZ - 1] = '\0'; ++ ++ /* ++ * Do we have service/<host> keys? ++ * (use default/configured keytab, kvno IGNORE_VNO to get the ++ * first match, and ignore enctype.) ++ */ ++ if ((retval = krb5_kt_read_service_key(context, NULL, princ, 0, ++ 0, &keyblock)) != 0) ++ continue; ++ break; ++ } ++ if (retval != 0 ) { /* failed to find key */ /* Keytab or service key does not exist */ if (debug) syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", -@@ -256,7 +141,7 @@ +@@ -228,7 +132,7 @@ + krb5_free_keyblock(context, keyblock); + + /* Talk to the kdc and construct the ticket. */ +- retval = krb5_mk_req(context, &auth_context, 0, "host", phost, ++ retval = krb5_mk_req(context, &auth_context, 0, *service, phost, + NULL, ccache, &packet); + if (auth_context) { + krb5_auth_con_free(context, auth_context); +@@ -256,7 +160,7 @@ cleanup: if (packet.data) diff --git a/security/pam_krb5/files/patch-ah b/security/pam_krb5/files/patch-ah index 480089da1745..933c37ed4ec6 100644 --- a/security/pam_krb5/files/patch-ah +++ b/security/pam_krb5/files/patch-ah @@ -1,5 +1,5 @@ ---- compat_heimdal.c.orig Mon Nov 6 13:27:02 2000 -+++ compat_heimdal.c Mon Nov 6 13:43:10 2000 +--- compat_heimdal.c.orig Wed Jan 24 12:40:26 2001 ++++ compat_heimdal.c Wed Jan 24 12:50:52 2001 @@ -0,0 +1,133 @@ +#include <errno.h> +#include <stdio.h> @@ -20,7 +20,7 @@ +void +compat_free_data_contents(krb5_context context, krb5_data *data) +{ -+ krb5_xfree(data); ++ krb5_xfree(data->data); +} + +krb5_error_code |