From: Peter Avalos Date: Sat, 24 Dec 2011 20:24:52 +0000 (-0800) Subject: GC pam_krb5 and pam_ksu. X-Git-Tag: v3.0.0~304 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/b9ab0360a28e6f144e0b1dc6286b8c0b1c7f3cfc GC pam_krb5 and pam_ksu. These haven't been built since 2009, and pam_krb5 is available in pkgsrc if someone needs it. --- diff --git a/lib/pam_module/pam_krb5/Makefile b/lib/pam_module/pam_krb5/Makefile deleted file mode 100644 index 1d431151f4..0000000000 --- a/lib/pam_module/pam_krb5/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $DragonFly: src/lib/pam_module/pam_krb5/Makefile,v 1.3 2005/07/28 19:25:41 joerg Exp $ - -LIB= pam_krb5 -SRCS= pam_krb5.c -MAN= pam_krb5.8 - -DPADD= ${LIBKRB5} ${LIBGSSAPI} ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} \ - ${LIBCOM_ERR} ${LIBROKEN} -LDADD= -lkrb5 -lgssapi -lasn1 -lcrypto -lcrypt -lcom_err -lroken - -.include diff --git a/lib/pam_module/pam_krb5/pam_krb5.8 b/lib/pam_module/pam_krb5/pam_krb5.8 deleted file mode 100644 index 2d2d388315..0000000000 --- a/lib/pam_module/pam_krb5/pam_krb5.8 +++ /dev/null @@ -1,218 +0,0 @@ -.\" -.\" $Id: pam_krb5.5,v 1.5 2000/01/05 00:59:56 fcusack Exp $ -.\" $FreeBSD: src/lib/libpam/modules/pam_krb5/pam_krb5.8,v 1.6 2001/11/24 23:41:32 dd Exp $ -.\" $DragonFly: src/lib/pam_module/pam_krb5/pam_krb5.8,v 1.1 2005/07/12 23:04:02 joerg Exp $ -.Dd January 15, 1999 -.Dt PAM_KRB5 8 -.Os -.Sh NAME -.Nm pam_krb5 -.Nd Kerberos 5 PAM module -.Sh SYNOPSIS -.Pa /usr/lib/pam_krb5.so -.Sh DESCRIPTION -The Kerberos 5 service module for PAM, typically -.Pa /usr/lib/pam_krb5.so , -provides functionality for three PAM categories: -authentication, -account management, -and password management. -It also provides null functions for session management. -The -.Pa pam_krb5.so -module is a shared object -that can be dynamically loaded to provide -the necessary functionality upon demand. -Its path is specified in the -PAM configuration file. -.Ss Kerberos 5 Authentication Module -The Kerberos 5 authentication component -provides functions to verify the identity of a user -.Pq Fn pam_sm_authenticate -and to set user specific credentials -.Pq Fn pam_sm_setcred . -.Fn pam_sm_authenticate -converts the supplied username into a Kerberos principal, -by appending the default local realm name. -It also supports usernames with explicit realm names. -If a realm name is supplied, then upon a successful return, it -changes the username by mapping the principal name into a local username -(calling -.Fn krb5_aname_to_localname ) . -This typically just means -the realm name is stripped. -.Pp -It prompts the user for a password and obtains a new Kerberos TGT for -the principal. -The TGT is verified by obtaining a service -ticket for the local host. -.Pp -When prompting for the current password, the authentication -module will use the prompt -.Dq Li "Password for :" . -.Pp -The -.Fn pam_sm_setcred -function stores the newly acquired credentials in a credentials cache, -and sets the environment variable -.Ev KRB5CCNAME -appropriately. -The credentials cache should be destroyed by the user at logout with -.Xr kdestroy 1 . -.Pp -The following options may be passed to the authentication module: -.Bl -tag -width ".Cm use_first_pass" -.It Cm debug -.Xr syslog 3 -debugging information at -.Dv LOG_DEBUG -level. -.It Cm no_warn -suppress warning messages to the user. -These messages include -reasons why the user's -authentication attempt was declined. -.It Cm use_first_pass -If the authentication module is not the first in the stack, -and a previous module obtained the user's password, that password is -used to authenticate the user. -If this fails, the authentication -module returns failure without prompting the user for a password. -This option has no effect if the authentication module is -the first in the stack, or if no previous modules obtained the -user's password. -.It Cm try_first_pass -This option is similar to the -.Cm use_first_pass -option, except that if the previously obtained password fails, the -user is prompted for another password. -.It Cm forwardable -Obtain forwardable Kerberos credentials for the user. -.It Cm no_ccache -Do not save the obtained credentials in a credentials cache. -This is a -useful option if the authentication module is used for services such -as ftp or pop, where the user would not be able to destroy them. -[This -is not a recommendation to use the module for those services.] -.It Cm ccache Ns = Ns Ar name -Use -.Ar name -as the credentials cache. -.Ar name -must be in the form -.Ar type : Ns Ar residual . -The special tokens -.Ql %u , -to designate the decimal UID of the user; -and -.Ql %p , -to designate the current process ID; can be used in -.Ar name . -.El -.Ss Kerberos 5 Account Management Module -The Kerberos 5 account management component -provides a function to perform account management, -.Fn pam_sm_acct_mgmt . -The function verifies that the authenticated principal is allowed -to login to the local user account by calling -.Fn krb5_kuserok -(which checks the user's -.Pa .k5login -file). -.Ss Kerberos 5 Password Management Module -The Kerberos 5 password management component -provides a function to change passwords -.Pq Fn pam_sm_chauthtok . -The username supplied (the -user running the -.Xr passwd 1 -command, or the username given as an argument) is mapped into -a Kerberos principal name, using the same technique as in -the authentication module. -Note that if a realm name was -explicitly supplied during authentication, but not during -a password change, the mapping -done by the password management module may not result in the -same principal as was used for authentication. -.Pp -Unlike when -changing a -.Ux -password, the password management module will -allow any user to change any principal's password (if the user knows -the principal's old password, of course). -Also unlike -.Ux , -root -is always prompted for the principal's old password. -.Pp -The password management module uses the same heuristics as -.Xr kpasswd 1 -to determine how to contact the Kerberos password server. -.Pp -The following options may be passed to the password management -module: -.Bl -tag -width ".Cm use_first_pass" -.It Cm debug -.Xr syslog 3 -debugging information at -.Dv LOG_DEBUG -level. -.It Cm use_first_pass -If the password management module is not the first in the stack, -and a previous module obtained the user's old password, that password is -used to authenticate the user. -If this fails, the password -management -module returns failure without prompting the user for the old password. -If successful, the new password entered to the previous module is also -used as the new Kerberos password. -If the new password fails, -the password management module returns failure without -prompting the user for a new password. -.It Cm try_first_pass -This option is similar to the -.Cm use_first_pass -option, except that if the previously obtained old or new passwords fail, -the user is prompted for them. -.El -.Ss Kerberos 5 Session Management Module -The Kerberos 5 session management component -provides functions to initiate -.Pq Fn pam_sm_open_session -and terminate -.Pq Fn pam_sm_close_session -sessions. -Since session management is not defined under Kerberos 5, -both of these functions simply return success. -They are provided -only because of the naming conventions for PAM modules. -.Sh ENVIRONMENT -.Bl -tag -width "KRB5CCNAME" -.It Ev KRB5CCNAME -Location of the credentials cache. -.El -.Sh FILES -.Bl -tag -width ".Pa /tmp/krb5cc_ Ns Ar uid" -compact -.It Pa /tmp/krb5cc_ Ns Ar uid -default credentials cache -.Ar ( uid -is the decimal UID of the user). -.It Pa $HOME/.k5login -file containing Kerberos principals that are allowed access. -.El -.Sh SEE ALSO -.Xr kdestroy 1 , -.Xr passwd 1 , -.Xr syslog 3 , -.Xr pam.conf 5 , -.Xr pam 8 -.Sh NOTES -Applications should not call -.Fn pam_authenticate -more than once between calls to -.Fn pam_start -and -.Fn pam_end -when using the Kerberos 5 PAM module. diff --git a/lib/pam_module/pam_krb5/pam_krb5.c b/lib/pam_module/pam_krb5/pam_krb5.c deleted file mode 100644 index a30a877be0..0000000000 --- a/lib/pam_module/pam_krb5/pam_krb5.c +++ /dev/null @@ -1,970 +0,0 @@ -/*- - * This pam_krb5 module contains code that is: - * Copyright (c) Derrick J. Brashear, 1996. All rights reserved. - * Copyright (c) Frank Cusack, 1999-2001. All rights reserved. - * Copyright (c) Jacques A. Vidrine, 2000-2001. All rights reserved. - * Copyright (c) Nicolas Williams, 2001. All rights reserved. - * Copyright (c) Perot Systems Corporation, 2001. All rights reserved. - * Copyright (c) Mark R V Murray, 2001. All rights reserved. - * Copyright (c) Networks Associates Technology, Inc., 2002-2005. - * All rights reserved. - * - * Portions of this software were developed for the FreeBSD Project by - * ThinkSec AS and NAI Labs, the Security Research Division of Network - * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 - * ("CBOSS"), as part of the DARPA CHATS research program. - * - * 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 - * notices, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. - * - * $FreeBSD: src/lib/libpam/modules/pam_krb5/pam_krb5.c,v 1.23 2005/07/07 14:16:38 kensmith Exp $ - * $DragonFly: src/lib/pam_module/pam_krb5/pam_krb5.c,v 1.2 2006/08/03 16:40:46 swildner Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#define PAM_SM_PASSWORD - -#include -#include -#include -#include - -#define COMPAT_HEIMDAL -/* #define COMPAT_MIT */ - -static int verify_krb_v5_tgt(krb5_context, krb5_ccache, char *, int); -static void cleanup_cache(pam_handle_t *, void *, int); -static const char *compat_princ_component(krb5_context, krb5_principal, int); -static void compat_free_data_contents(krb5_context, krb5_data *); - -#define USER_PROMPT "Username: " -#define PASSWORD_PROMPT "Password:" -#define NEW_PASSWORD_PROMPT "New Password:" - -#define PAM_OPT_CCACHE "ccache" -#define PAM_OPT_DEBUG "debug" -#define PAM_OPT_FORWARDABLE "forwardable" -#define PAM_OPT_NO_CCACHE "no_ccache" -#define PAM_OPT_REUSE_CCACHE "reuse_ccache" - -/* - * authentication management - */ -PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, - int argc __unused, const char *argv[] __unused) -{ - krb5_error_code krbret; - krb5_context pam_context; - krb5_creds creds; - krb5_principal princ; - krb5_ccache ccache; - krb5_get_init_creds_opt opts; - struct passwd *pwd; - int retval; - const void *ccache_data; - const char *user, *pass; - const void *sourceuser, *service; - char *principal, *princ_name, *ccache_name, luser[32], *srvdup; - - retval = pam_get_user(pamh, &user, USER_PROMPT); - if (retval != PAM_SUCCESS) - return (retval); - - PAM_LOG("Got user: %s", user); - - retval = pam_get_item(pamh, PAM_RUSER, &sourceuser); - if (retval != PAM_SUCCESS) - return (retval); - - PAM_LOG("Got ruser: %s", (const char *)sourceuser); - - service = NULL; - pam_get_item(pamh, PAM_SERVICE, &service); - if (service == NULL) - service = "unknown"; - - PAM_LOG("Got service: %s", (const char *)service); - - krbret = krb5_init_context(&pam_context); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - return (PAM_SERVICE_ERR); - } - - PAM_LOG("Context initialised"); - - krb5_get_init_creds_opt_init(&opts); - - if (openpam_get_option(pamh, PAM_OPT_FORWARDABLE)) - krb5_get_init_creds_opt_set_forwardable(&opts, 1); - - PAM_LOG("Credentials initialised"); - - krbret = krb5_cc_register(pam_context, &krb5_mcc_ops, FALSE); - if (krbret != 0 && krbret != KRB5_CC_TYPE_EXISTS) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - retval = PAM_SERVICE_ERR; - goto cleanup3; - } - - PAM_LOG("Done krb5_cc_register()"); - - /* Get principal name */ - if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) - asprintf(&principal, "%s/%s", (const char *)sourceuser, user); - else - principal = strdup(user); - - PAM_LOG("Created principal: %s", principal); - - krbret = krb5_parse_name(pam_context, principal, &princ); - free(principal); - if (krbret != 0) { - PAM_LOG("Error krb5_parse_name(): %s", - krb5_get_err_text(pam_context, krbret)); - PAM_VERBOSE_ERROR("Kerberos 5 error"); - retval = PAM_SERVICE_ERR; - goto cleanup3; - } - - PAM_LOG("Done krb5_parse_name()"); - - /* Now convert the principal name into something human readable */ - princ_name = NULL; - krbret = krb5_unparse_name(pam_context, princ, &princ_name); - if (krbret != 0) { - PAM_LOG("Error krb5_unparse_name(): %s", - krb5_get_err_text(pam_context, krbret)); - PAM_VERBOSE_ERROR("Kerberos 5 error"); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - - PAM_LOG("Got principal: %s", princ_name); - - /* Get password */ - retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, PASSWORD_PROMPT); - if (retval != PAM_SUCCESS) - goto cleanup2; - - PAM_LOG("Got password"); - - /* Verify the local user exists (AFTER getting the password) */ - if (strchr(user, '@')) { - /* get a local account name for this principal */ - krbret = krb5_aname_to_localname(pam_context, princ, - sizeof(luser), luser); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - PAM_LOG("Error krb5_aname_to_localname(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_USER_UNKNOWN; - goto cleanup2; - } - - retval = pam_set_item(pamh, PAM_USER, luser); - if (retval != PAM_SUCCESS) - goto cleanup2; - - PAM_LOG("PAM_USER Redone"); - } - - pwd = getpwnam(user); - if (pwd == NULL) { - retval = PAM_USER_UNKNOWN; - goto cleanup2; - } - - PAM_LOG("Done getpwnam()"); - - /* Get a TGT */ - memset(&creds, 0, sizeof(krb5_creds)); - krbret = krb5_get_init_creds_password(pam_context, &creds, princ, - pass, NULL, pamh, 0, NULL, &opts); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - PAM_LOG("Error krb5_get_init_creds_password(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_AUTH_ERR; - goto cleanup2; - } - - PAM_LOG("Got TGT"); - - /* Generate a temporary cache */ - krbret = krb5_cc_gen_new(pam_context, &krb5_mcc_ops, &ccache); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - PAM_LOG("Error krb5_cc_gen_new(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup; - } - krbret = krb5_cc_initialize(pam_context, ccache, princ); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - PAM_LOG("Error krb5_cc_initialize(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup; - } - krbret = krb5_cc_store_cred(pam_context, ccache, &creds); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - PAM_LOG("Error krb5_cc_store_cred(): %s", - krb5_get_err_text(pam_context, krbret)); - krb5_cc_destroy(pam_context, ccache); - retval = PAM_SERVICE_ERR; - goto cleanup; - } - - PAM_LOG("Credentials stashed"); - - /* Verify them */ - if ((srvdup = strdup(service)) == NULL) { - retval = PAM_BUF_ERR; - goto cleanup; - } - krbret = verify_krb_v5_tgt(pam_context, ccache, srvdup, - openpam_get_option(pamh, PAM_OPT_DEBUG) ? 1 : 0); - free(srvdup); - if (krbret == -1) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - krb5_cc_destroy(pam_context, ccache); - retval = PAM_AUTH_ERR; - goto cleanup; - } - - PAM_LOG("Credentials stash verified"); - - retval = pam_get_data(pamh, "ccache", &ccache_data); - if (retval == PAM_SUCCESS) { - krb5_cc_destroy(pam_context, ccache); - PAM_VERBOSE_ERROR("Kerberos 5 error"); - retval = PAM_AUTH_ERR; - goto cleanup; - } - - PAM_LOG("Credentials stash not pre-existing"); - - asprintf(&ccache_name, "%s:%s", krb5_cc_get_type(pam_context, - ccache), krb5_cc_get_name(pam_context, ccache)); - if (ccache_name == NULL) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - retval = PAM_BUF_ERR; - goto cleanup; - } - retval = pam_set_data(pamh, "ccache", ccache_name, cleanup_cache); - if (retval != 0) { - krb5_cc_destroy(pam_context, ccache); - PAM_VERBOSE_ERROR("Kerberos 5 error"); - retval = PAM_SERVICE_ERR; - goto cleanup; - } - - PAM_LOG("Credentials stash saved"); - -cleanup: - krb5_free_cred_contents(pam_context, &creds); - PAM_LOG("Done cleanup"); -cleanup2: - krb5_free_principal(pam_context, princ); - PAM_LOG("Done cleanup2"); -cleanup3: - if (princ_name) - free(princ_name); - - krb5_free_context(pam_context); - - PAM_LOG("Done cleanup3"); - - if (retval != PAM_SUCCESS) - PAM_VERBOSE_ERROR("Kerberos 5 refuses you"); - - return (retval); -} - -PAM_EXTERN int -pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc __unused, const char *argv[] __unused) -{ -#ifdef _FREEFALL_CONFIG - return (PAM_SUCCESS); -#else - - krb5_error_code krbret; - krb5_context pam_context; - krb5_principal princ; - krb5_creds creds; - krb5_ccache ccache_temp, ccache_perm; - krb5_cc_cursor cursor; - struct passwd *pwd = NULL; - int retval; - const char *cache_name, *q; - const void *user; - const void *cache_data; - char *cache_name_buf = NULL, *p; - - uid_t euid; - gid_t egid; - - if (flags & PAM_DELETE_CRED) - return (PAM_SUCCESS); - - if (flags & PAM_REFRESH_CRED) - return (PAM_SUCCESS); - - if (flags & PAM_REINITIALIZE_CRED) - return (PAM_SUCCESS); - - if (!(flags & PAM_ESTABLISH_CRED)) - return (PAM_SERVICE_ERR); - - /* If a persistent cache isn't desired, stop now. */ - if (openpam_get_option(pamh, PAM_OPT_NO_CCACHE)) - return (PAM_SUCCESS); - - PAM_LOG("Establishing credentials"); - - /* Get username */ - retval = pam_get_item(pamh, PAM_USER, &user); - if (retval != PAM_SUCCESS) - return (retval); - - PAM_LOG("Got user: %s", (const char *)user); - - krbret = krb5_init_context(&pam_context); - if (krbret != 0) { - PAM_LOG("Error krb5_init_context() failed"); - return (PAM_SERVICE_ERR); - } - - PAM_LOG("Context initialised"); - - euid = geteuid(); /* Usually 0 */ - egid = getegid(); - - PAM_LOG("Got euid, egid: %d %d", euid, egid); - - /* Retrieve the temporary cache */ - retval = pam_get_data(pamh, "ccache", &cache_data); - if (retval != PAM_SUCCESS) { - retval = PAM_CRED_UNAVAIL; - goto cleanup3; - } - krbret = krb5_cc_resolve(pam_context, cache_data, &ccache_temp); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_resolve(\"%s\"): %s", (const char *)cache_data, - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup3; - } - - /* Get the uid. This should exist. */ - pwd = getpwnam(user); - if (pwd == NULL) { - retval = PAM_USER_UNKNOWN; - goto cleanup3; - } - - PAM_LOG("Done getpwnam()"); - - /* Avoid following a symlink as root */ - if (setegid(pwd->pw_gid)) { - retval = PAM_SERVICE_ERR; - goto cleanup3; - } - if (seteuid(pwd->pw_uid)) { - retval = PAM_SERVICE_ERR; - goto cleanup3; - } - - PAM_LOG("Done setegid() & seteuid()"); - - /* Get the cache name */ - cache_name = openpam_get_option(pamh, PAM_OPT_CCACHE); - if (cache_name == NULL) { - asprintf(&cache_name_buf, "FILE:/tmp/krb5cc_%d", pwd->pw_uid); - cache_name = cache_name_buf; - } - - p = calloc(PATH_MAX + 16, sizeof(char)); - q = cache_name; - - if (p == NULL) { - PAM_LOG("Error malloc(): failure"); - retval = PAM_BUF_ERR; - goto cleanup3; - } - cache_name = p; - - /* convert %u and %p */ - while (*q) { - if (*q == '%') { - q++; - if (*q == 'u') { - sprintf(p, "%d", pwd->pw_uid); - p += strlen(p); - } - else if (*q == 'p') { - sprintf(p, "%d", getpid()); - p += strlen(p); - } - else { - /* Not a special token */ - *p++ = '%'; - q--; - } - q++; - } - else { - *p++ = *q++; - } - } - - PAM_LOG("Got cache_name: %s", cache_name); - - /* Initialize the new ccache */ - krbret = krb5_cc_get_principal(pam_context, ccache_temp, &princ); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_get_principal(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup3; - } - krbret = krb5_cc_resolve(pam_context, cache_name, &ccache_perm); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_resolve(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - krbret = krb5_cc_initialize(pam_context, ccache_perm, princ); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_initialize(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - - PAM_LOG("Cache initialised"); - - /* Prepare for iteration over creds */ - krbret = krb5_cc_start_seq_get(pam_context, ccache_temp, &cursor); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_start_seq_get(): %s", - krb5_get_err_text(pam_context, krbret)); - krb5_cc_destroy(pam_context, ccache_perm); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - - PAM_LOG("Prepared for iteration"); - - /* Copy the creds (should be two of them) */ - while ((krbret = krb5_cc_next_cred(pam_context, ccache_temp, - &cursor, &creds) == 0)) { - krbret = krb5_cc_store_cred(pam_context, ccache_perm, &creds); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_store_cred(): %s", - krb5_get_err_text(pam_context, krbret)); - krb5_cc_destroy(pam_context, ccache_perm); - krb5_free_cred_contents(pam_context, &creds); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - krb5_free_cred_contents(pam_context, &creds); - PAM_LOG("Iteration"); - } - krb5_cc_end_seq_get(pam_context, ccache_temp, &cursor); - - PAM_LOG("Done iterating"); - - if (strstr(cache_name, "FILE:") == cache_name) { - if (chown(&cache_name[5], pwd->pw_uid, pwd->pw_gid) == -1) { - PAM_LOG("Error chown(): %s", strerror(errno)); - krb5_cc_destroy(pam_context, ccache_perm); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - PAM_LOG("Done chown()"); - - if (chmod(&cache_name[5], (S_IRUSR | S_IWUSR)) == -1) { - PAM_LOG("Error chmod(): %s", strerror(errno)); - krb5_cc_destroy(pam_context, ccache_perm); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - PAM_LOG("Done chmod()"); - } - - krb5_cc_close(pam_context, ccache_perm); - - PAM_LOG("Cache closed"); - - retval = pam_setenv(pamh, "KRB5CCNAME", cache_name, 1); - if (retval != PAM_SUCCESS) { - PAM_LOG("Error pam_setenv(): %s", pam_strerror(pamh, retval)); - krb5_cc_destroy(pam_context, ccache_perm); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - - PAM_LOG("Environment done: KRB5CCNAME=%s", cache_name); - -cleanup2: - krb5_free_principal(pam_context, princ); - PAM_LOG("Done cleanup2"); -cleanup3: - krb5_free_context(pam_context); - PAM_LOG("Done cleanup3"); - - seteuid(euid); - setegid(egid); - - PAM_LOG("Done seteuid() & setegid()"); - - if (cache_name_buf != NULL) - free(cache_name_buf); - - return (retval); -#endif -} - -/* - * account management - */ -PAM_EXTERN int -pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, - int argc __unused, const char *argv[] __unused) -{ - krb5_error_code krbret; - krb5_context pam_context; - krb5_ccache ccache; - krb5_principal princ; - int retval; - const void *user; - const void *ccache_name; - - retval = pam_get_item(pamh, PAM_USER, &user); - if (retval != PAM_SUCCESS) - return (retval); - - PAM_LOG("Got user: %s", (const char *)user); - - retval = pam_get_data(pamh, "ccache", &ccache_name); - if (retval != PAM_SUCCESS) - return (PAM_SUCCESS); - - PAM_LOG("Got credentials"); - - krbret = krb5_init_context(&pam_context); - if (krbret != 0) { - PAM_LOG("Error krb5_init_context() failed"); - return (PAM_PERM_DENIED); - } - - PAM_LOG("Context initialised"); - - krbret = krb5_cc_resolve(pam_context, (const char *)ccache_name, &ccache); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_resolve(\"%s\"): %s", (const char *)ccache_name, - krb5_get_err_text(pam_context, krbret)); - krb5_free_context(pam_context); - return (PAM_PERM_DENIED); - } - - PAM_LOG("Got ccache %s", (const char *)ccache_name); - - - krbret = krb5_cc_get_principal(pam_context, ccache, &princ); - if (krbret != 0) { - PAM_LOG("Error krb5_cc_get_principal(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_PERM_DENIED; - goto cleanup; - } - - PAM_LOG("Got principal"); - - if (krb5_kuserok(pam_context, princ, (const char *)user)) - retval = PAM_SUCCESS; - else - retval = PAM_PERM_DENIED; - krb5_free_principal(pam_context, princ); - - PAM_LOG("Done kuserok()"); - -cleanup: - krb5_free_context(pam_context); - PAM_LOG("Done cleanup"); - - return (retval); - -} - -/* - * password management - */ -PAM_EXTERN int -pam_sm_chauthtok(pam_handle_t *pamh, int flags, - int argc __unused, const char *argv[] __unused) -{ - krb5_error_code krbret; - krb5_context pam_context; - krb5_creds creds; - krb5_principal princ; - krb5_get_init_creds_opt opts; - krb5_data result_code_string, result_string; - int result_code, retval; - const char *pass; - const void *user; - char *princ_name, *passdup; - - if (!(flags & PAM_UPDATE_AUTHTOK)) - return (PAM_AUTHTOK_ERR); - - retval = pam_get_item(pamh, PAM_USER, &user); - if (retval != PAM_SUCCESS) - return (retval); - - PAM_LOG("Got user: %s", (const char *)user); - - krbret = krb5_init_context(&pam_context); - if (krbret != 0) { - PAM_LOG("Error krb5_init_context() failed"); - return (PAM_SERVICE_ERR); - } - - PAM_LOG("Context initialised"); - - krb5_get_init_creds_opt_init(&opts); - - PAM_LOG("Credentials options initialised"); - - /* Get principal name */ - krbret = krb5_parse_name(pam_context, (const char *)user, &princ); - if (krbret != 0) { - PAM_LOG("Error krb5_parse_name(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_USER_UNKNOWN; - goto cleanup3; - } - - /* Now convert the principal name into something human readable */ - princ_name = NULL; - krbret = krb5_unparse_name(pam_context, princ, &princ_name); - if (krbret != 0) { - PAM_LOG("Error krb5_unparse_name(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_SERVICE_ERR; - goto cleanup2; - } - - PAM_LOG("Got principal: %s", princ_name); - - /* Get password */ - retval = pam_get_authtok(pamh, PAM_OLDAUTHTOK, &pass, PASSWORD_PROMPT); - if (retval != PAM_SUCCESS) - goto cleanup2; - - PAM_LOG("Got password"); - - memset(&creds, 0, sizeof(krb5_creds)); - krbret = krb5_get_init_creds_password(pam_context, &creds, princ, - pass, NULL, pamh, 0, "kadmin/changepw", &opts); - if (krbret != 0) { - PAM_LOG("Error krb5_get_init_creds_password(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_AUTH_ERR; - goto cleanup2; - } - - PAM_LOG("Credentials established"); - - /* Now get the new password */ - for (;;) { - retval = pam_get_authtok(pamh, - PAM_AUTHTOK, &pass, NEW_PASSWORD_PROMPT); - if (retval != PAM_TRY_AGAIN) - break; - pam_error(pamh, "Mismatch; try again, EOF to quit."); - } - if (retval != PAM_SUCCESS) - goto cleanup; - - PAM_LOG("Got new password"); - - /* Change it */ - if ((passdup = strdup(pass)) == NULL) { - retval = PAM_BUF_ERR; - goto cleanup; - } - krbret = krb5_change_password(pam_context, &creds, passdup, - &result_code, &result_code_string, &result_string); - free(passdup); - if (krbret != 0) { - PAM_LOG("Error krb5_change_password(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_AUTHTOK_ERR; - goto cleanup; - } - if (result_code) { - PAM_LOG("Error krb5_change_password(): (result_code)"); - retval = PAM_AUTHTOK_ERR; - goto cleanup; - } - - PAM_LOG("Password changed"); - - if (result_string.data) - free(result_string.data); - if (result_code_string.data) - free(result_code_string.data); - -cleanup: - krb5_free_cred_contents(pam_context, &creds); - PAM_LOG("Done cleanup"); -cleanup2: - krb5_free_principal(pam_context, princ); - PAM_LOG("Done cleanup2"); -cleanup3: - if (princ_name) - free(princ_name); - - krb5_free_context(pam_context); - - PAM_LOG("Done cleanup3"); - - return (retval); -} - -PAM_MODULE_ENTRY("pam_krb5"); - -/* - * This routine with some modification is from the MIT V5B6 appl/bsd/login.c - * Modified by Sam Hartman to support PAM services - * for Debian. - * - * 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/ service is unknown (i.e., - * 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. - */ -/* ARGSUSED */ -static int -verify_krb_v5_tgt(krb5_context context, krb5_ccache ccache, - char *pam_service, int debug) -{ - krb5_error_code retval; - krb5_principal princ; - krb5_keyblock *keyblock; - krb5_data packet; - krb5_auth_context auth_context; - char phost[BUFSIZ]; - const char *services[3], **service; - - packet.data = 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; - keyblock = 0; - retval = -1; - for (service = &services[0]; *service != NULL; service++) { - retval = krb5_sname_to_principal(context, NULL, *service, - KRB5_NT_SRV_HST, &princ); - if (retval != 0) { - if (debug) - syslog(LOG_DEBUG, - "pam_krb5: verify_krb_v5_tgt(): %s: %s", - "krb5_sname_to_principal()", - krb5_get_err_text(context, retval)); - return -1; - } - - /* Extract the name directly. */ - strncpy(phost, compat_princ_component(context, princ, 1), - BUFSIZ); - phost[BUFSIZ - 1] = '\0'; - - /* - * Do we have service/ keys? - * (use default/configured keytab, kvno IGNORE_VNO to get the - * first match, and ignore enctype.) - */ - retval = krb5_kt_read_service_key(context, NULL, princ, 0, 0, - &keyblock); - if (retval != 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", - "krb5_kt_read_service_key()", - krb5_get_err_text(context, retval)); - retval = 0; - goto cleanup; - } - if (keyblock) - krb5_free_keyblock(context, keyblock); - - /* Talk to the kdc and construct the ticket. */ - auth_context = NULL; - retval = krb5_mk_req(context, &auth_context, 0, *service, phost, - NULL, ccache, &packet); - if (auth_context) { - krb5_auth_con_free(context, auth_context); - auth_context = NULL; /* setup for rd_req */ - } - if (retval) { - if (debug) - syslog(LOG_DEBUG, - "pam_krb5: verify_krb_v5_tgt(): %s: %s", - "krb5_mk_req()", - krb5_get_err_text(context, retval)); - retval = -1; - goto cleanup; - } - - /* Try to use the ticket. */ - retval = krb5_rd_req(context, &auth_context, &packet, princ, NULL, - NULL, NULL); - if (retval) { - if (debug) - syslog(LOG_DEBUG, - "pam_krb5: verify_krb_v5_tgt(): %s: %s", - "krb5_rd_req()", - krb5_get_err_text(context, retval)); - retval = -1; - } - else - retval = 1; - -cleanup: - if (packet.data) - compat_free_data_contents(context, &packet); - krb5_free_principal(context, princ); - return retval; -} - -/* Free the memory for cache_name. Called by pam_end() */ -/* ARGSUSED */ -static void -cleanup_cache(pam_handle_t *pamh __unused, void *data, int pam_end_status __unused) -{ - krb5_context pam_context; - krb5_ccache ccache; - krb5_error_code krbret; - - if (krb5_init_context(&pam_context)) - return; - - krbret = krb5_cc_resolve(pam_context, data, &ccache); - if (krbret == 0) - krb5_cc_destroy(pam_context, ccache); - krb5_free_context(pam_context); - free(data); -} - -#ifdef COMPAT_HEIMDAL -#ifdef COMPAT_MIT -#error This cannot be MIT and Heimdal compatible! -#endif -#endif - -#ifndef COMPAT_HEIMDAL -#ifndef COMPAT_MIT -#error One of COMPAT_MIT and COMPAT_HEIMDAL must be specified! -#endif -#endif - -#ifdef COMPAT_HEIMDAL -/* ARGSUSED */ -static const char * -compat_princ_component(krb5_context context __unused, krb5_principal princ, int n) -{ - return princ->name.name_string.val[n]; -} - -/* ARGSUSED */ -static void -compat_free_data_contents(krb5_context context __unused, krb5_data * data) -{ - krb5_xfree(data->data); -} -#endif - -#ifdef COMPAT_MIT -static const char * -compat_princ_component(krb5_context context, krb5_principal princ, int n) -{ - return krb5_princ_component(context, princ, n)->data; -} - -static void -compat_free_data_contents(krb5_context context, krb5_data * data) -{ - krb5_free_data_contents(context, data); -} -#endif diff --git a/lib/pam_module/pam_ksu/Makefile b/lib/pam_module/pam_ksu/Makefile deleted file mode 100644 index c000e19b5b..0000000000 --- a/lib/pam_module/pam_ksu/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2002 FreeBSD, Inc. -# 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. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. -# -# $FreeBSD: src/lib/libpam/modules/pam_ksu/Makefile,v 1.6 2004/08/06 07:27:04 cperciva Exp $ - -LIB= pam_ksu -SRCS= pam_ksu.c -MAN= pam_ksu.8 - -DPADD= ${LIBKRB5} ${LIBASN1} ${LIBROKEN} ${LIBCOM_ERR} ${LIBCRYPT} ${LIBCRYPTO} -LDADD= -lkrb5 -lasn1 -lroken -lcom_err -lcrypt -lcrypto - -.include diff --git a/lib/pam_module/pam_ksu/pam_ksu.8 b/lib/pam_module/pam_ksu/pam_ksu.8 deleted file mode 100644 index 08322b79eb..0000000000 --- a/lib/pam_module/pam_ksu/pam_ksu.8 +++ /dev/null @@ -1,122 +0,0 @@ -.\" Copyright (c) 2001 Mark R V Murray -.\" All rights reserved. -.\" Copyright (c) 2001 Networks Associates Technology, Inc. -.\" All rights reserved. -.\" -.\" This software was developed for the FreeBSD Project by ThinkSec AS and -.\" NAI Labs, the Security Research Division of Network Associates, Inc. -.\" under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the -.\" DARPA CHATS research program. -.\" -.\" 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. The name of the author may not be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. -.\" -.\" $FreeBSD: src/lib/libpam/modules/pam_ksu/pam_ksu.8,v 1.3 2002/12/12 08:19:47 ru Exp $ -.\" -.Dd May 15, 2002 -.Dt PAM_KSU 8 -.Os -.Sh NAME -.Nm pam_ksu -.Nd Kerberos 5 SU PAM module -.Sh SYNOPSIS -.Op Ar service-name -.Ar module-type -.Ar control-flag -.Pa pam_ksu -.Op Ar options -.Sh DESCRIPTION -The Kerberos 5 SU authentication service module for PAM, -.Nm -for only one PAM category: authentication. -In terms of the -.Ar module-type -parameter, this is the -.Dq Li auth -feature. -The module is specifically designed to be used with the -.Xr su 1 -utility. -.\" It also provides a null function for session management. -.Ss Kerberos 5 SU Authentication Module -The Kerberos 5 SU authentication component provides functions to verify -the identity of a user -.Pq Fn pam_sm_authenticate , -and determine whether or not the user is authorized to obtain the -privileges of the target account. -If the target account is -.Dq root , -then the Kerberos 5 principal used -for authentication and authorization will be the -.Dq root -instance of -the current user, e.g.\& -.Dq Li user/root@REAL.M . -Otherwise, the principal will simply be the current user's default -principal, e.g.\& -.Dq Li user@REAL.M . -.Pp -The user is prompted for a password if necessary. -Authorization is performed -by comparing the Kerberos 5 principal with those listed in the -.Pa .k5login -file in the target account's home directory -(e.g.\& -.Pa /root/.k5login -for root). -.Pp -The following options may be passed to the authentication module: -.Bl -tag -width ".Cm use_first_pass" -.It Cm debug -.Xr syslog 3 -debugging information at -.Dv LOG_DEBUG -level. -.It Cm use_first_pass -If the authentication module -is not the first in the stack, -and a previous module -obtained the user's password, -that password is used -to authenticate the user. -If this fails, -the authentication module returns failure -without prompting the user for a password. -This option has no effect -if the authentication module -is the first in the stack, -or if no previous modules -obtained the user's password. -.It Cm try_first_pass -This option is similar to the -.Cm use_first_pass -option, -except that if the previously obtained password fails, -the user is prompted for another password. -.El -.Sh SEE ALSO -.Xr su 1 , -.Xr syslog 3 , -.Xr pam.conf 5 , -.Xr pam 8 diff --git a/lib/pam_module/pam_ksu/pam_ksu.c b/lib/pam_module/pam_ksu/pam_ksu.c deleted file mode 100644 index 8194cad28a..0000000000 --- a/lib/pam_module/pam_ksu/pam_ksu.c +++ /dev/null @@ -1,257 +0,0 @@ -/*- - * Copyright (c) 2002 Jacques A. Vidrine - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. - * - * $FreeBSD: src/lib/libpam/modules/pam_ksu/pam_ksu.c,v 1.5 2004/02/10 10:13:21 des Exp $ - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define PAM_SM_AUTH -#define PAM_SM_CRED -#include -#include -#include - -static const char superuser[] = "root"; - -static long get_su_principal(krb5_context, const char *, const char *, - char **, krb5_principal *); -static int auth_krb5(pam_handle_t *, krb5_context, const char *, - krb5_principal); - -PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, - int argc __unused, const char *argv[] __unused) -{ - krb5_context context; - krb5_principal su_principal; - const char *user; - const void *ruser; - char *su_principal_name; - long rv; - int pamret; - - pamret = pam_get_user(pamh, &user, NULL); - if (pamret != PAM_SUCCESS) - return (pamret); - PAM_LOG("Got user: %s", user); - pamret = pam_get_item(pamh, PAM_RUSER, &ruser); - if (pamret != PAM_SUCCESS) - return (pamret); - PAM_LOG("Got ruser: %s", (const char *)ruser); - rv = krb5_init_context(&context); - if (rv != 0) { - PAM_LOG("krb5_init_context failed: %s", - krb5_get_err_text(context, rv)); - return (PAM_SERVICE_ERR); - } - rv = get_su_principal(context, user, ruser, &su_principal_name, &su_principal); - if (rv != 0) - return (PAM_AUTH_ERR); - PAM_LOG("kuserok: %s -> %s", su_principal_name, user); - rv = krb5_kuserok(context, su_principal, user); - pamret = rv ? auth_krb5(pamh, context, su_principal_name, su_principal) : PAM_AUTH_ERR; - free(su_principal_name); - krb5_free_principal(context, su_principal); - krb5_free_context(context); - return (pamret); -} - -PAM_EXTERN int -pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, - int ac __unused, const char *av[] __unused) -{ - - return (PAM_SUCCESS); -} - -/* Authenticate using Kerberos 5. - * pamh -- The PAM handle. - * context -- An initialized krb5_context. - * su_principal_name -- The target principal name, used only for password prompts. - * If NULL, the password prompts will not include a principal - * name. - * su_principal -- The target krb5_principal. - * Note that a valid keytab in the default location with a host entry - * must be available, and that the PAM application must have sufficient - * privileges to access it. - * Returns PAM_SUCCESS if authentication was successful, or an appropriate - * PAM error code if it was not. - */ -static int -auth_krb5(pam_handle_t *pamh, krb5_context context, const char *su_principal_name, - krb5_principal su_principal) -{ - krb5_creds creds; - krb5_get_init_creds_opt gic_opt; - krb5_verify_init_creds_opt vic_opt; - const char *pass; - char *prompt; - long rv; - int pamret; - - prompt = NULL; - krb5_get_init_creds_opt_init(&gic_opt); - krb5_verify_init_creds_opt_init(&vic_opt); - if (su_principal_name != NULL) - asprintf(&prompt, "Password for %s:", su_principal_name); - else - asprintf(&prompt, "Password:"); - if (prompt == NULL) - return (PAM_BUF_ERR); - pass = NULL; - pamret = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt); - free(prompt); - if (pamret != PAM_SUCCESS) - return (pamret); - rv = krb5_get_init_creds_password(context, &creds, su_principal, - pass, NULL, NULL, 0, NULL, &gic_opt); - if (rv != 0) { - PAM_LOG("krb5_get_init_creds_password: %s", - krb5_get_err_text(context, rv)); - return (PAM_AUTH_ERR); - } - krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_opt, 1); - rv = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, - &vic_opt); - krb5_free_cred_contents(context, &creds); - if (rv != 0) { - PAM_LOG("krb5_verify_init_creds: %s", - krb5_get_err_text(context, rv)); - return (PAM_AUTH_ERR); - } - return (PAM_SUCCESS); -} - -/* Determine the target principal given the current user and the target user. - * context -- An initialized krb5_context. - * target_user -- The target username. - * current_user -- The current username. - * su_principal_name -- (out) The target principal name. - * su_principal -- (out) The target krb5_principal. - * When the target user is `root', the target principal will be a `root - * instance', e.g. `luser/root@REA.LM'. Otherwise, the target principal - * will simply be the current user's default principal name. Note that - * in any case, if KRB5CCNAME is set and a credentials cache exists, the - * principal name found there will be the `starting point', rather than - * the ruser parameter. - * - * Returns 0 for success, or a com_err error code on failure. - */ -static long -get_su_principal(krb5_context context, const char *target_user, - const char *current_user, char **su_principal_name, - krb5_principal *su_principal) -{ - krb5_principal default_principal; - krb5_ccache ccache; - char *principal_name, *ccname, *p; - long rv; - uid_t euid, ruid; - - *su_principal = NULL; - default_principal = NULL; - /* Unless KRB5CCNAME was explicitly set, we won't really be able - * to look at the credentials cache since krb5_cc_default will - * look at getuid(). - */ - ruid = getuid(); - euid = geteuid(); - rv = seteuid(ruid); - if (rv != 0) - return (errno); - p = getenv("KRB5CCNAME"); - if (p != NULL) - ccname = strdup(p); - else - asprintf(&ccname, "%s%lu", KRB5_DEFAULT_CCROOT, (unsigned long)ruid); - if (ccname == NULL) - return (errno); - rv = krb5_cc_resolve(context, ccname, &ccache); - free(ccname); - if (rv == 0) { - rv = krb5_cc_get_principal(context, ccache, &default_principal); - krb5_cc_close(context, ccache); - if (rv != 0) - default_principal = NULL; /* just to be safe */ - } - rv = seteuid(euid); - if (rv != 0) - return (errno); - if (default_principal == NULL) { - rv = krb5_make_principal(context, &default_principal, NULL, current_user, NULL); - if (rv != 0) { - PAM_LOG("Could not determine default principal name."); - return (rv); - } - } - /* Now that we have some principal, if the target account is - * `root', then transform it into a `root' instance, e.g. - * `user@REA.LM' -> `user/root@REA.LM'. - */ - rv = krb5_unparse_name(context, default_principal, &principal_name); - krb5_free_principal(context, default_principal); - if (rv != 0) { - PAM_LOG("krb5_unparse_name: %s", - krb5_get_err_text(context, rv)); - return (rv); - } - PAM_LOG("Default principal name: %s", principal_name); - if (strcmp(target_user, superuser) == 0) { - p = strrchr(principal_name, '@'); - if (p == NULL) { - PAM_LOG("malformed principal name `%s'", principal_name); - free(principal_name); - return (rv); - } - *p++ = '\0'; - *su_principal_name = NULL; - asprintf(su_principal_name, "%s/%s@%s", principal_name, superuser, p); - free(principal_name); - } else - *su_principal_name = principal_name; - - if (*su_principal_name == NULL) - return (errno); - rv = krb5_parse_name(context, *su_principal_name, &default_principal); - if (rv != 0) { - PAM_LOG("krb5_parse_name `%s': %s", *su_principal_name, - krb5_get_err_text(context, rv)); - free(*su_principal_name); - return (rv); - } - PAM_LOG("Target principal name: %s", *su_principal_name); - *su_principal = default_principal; - return (0); -} - -PAM_MODULE_ENTRY("pam_ksu");