diff --git a/lib/libpam/modules/pam_krb5/COPYRIGHT b/lib/libpam/modules/pam_krb5/COPYRIGHT deleted file mode 100644 index 42fb642c7230..000000000000 --- a/lib/libpam/modules/pam_krb5/COPYRIGHT +++ /dev/null @@ -1,195 +0,0 @@ -pam_krb5: - -$FreeBSD$ - -Copyright (c) Frank Cusack, 1999-2000. -fcusack@fcusack.com -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, 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. - ---------------------------------------------------------------------------- - -This software may contain code from Naomaru Itoi: - -PAM-kerberos5 module Copyright notice. -Naomaru Itoi , June 24, 1997. - ----------------------------------------------------------------------------- -COPYRIGHT (c) 1997 -THE REGENTS OF THE UNIVERSITY OF MICHIGAN -ALL RIGHTS RESERVED - -PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS AND REDISTRIBUTE -THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR ANY PURPOSE, SO LONG AS THE NAME -OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY ADVERTISING OR PUBLICITY -PERTAINING TO THE USE OR DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, -WRITTEN PRIOR AUTHORIZATION. IF THE ABOVE COPYRIGHT NOTICE OR ANY OTHER -IDENTIFICATION OF THE UNIVERSITY OF MICHIGAN IS INCLUDED IN ANY COPY OF ANY -PORTION OF THIS SOFTWARE, THEN THE DISCLAIMER BELOW MUST ALSO BE INCLUDED. - -THE SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY OF -MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE -UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING -WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABITILY AND FITNESS FOR A -PARTICULAR PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE -LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR -CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN -CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -PAM-kerberos5 module is written based on PAM-kerberos4 module -by Derrick J. Brashear and kerberos5-1.0pl1 by M.I.T. kerberos team. -Permission to use, copy, modify, distribute this software is hereby -granted, as long as it is granted by Derrick J. Brashear and -M.I.T. kerberos team. Followings are their copyright information. ----------------------------------------------------------------------------- - -This software may contain code from Derrick J. Brashear: - - -Copyright (c) Derrick J. Brashear, 1996. 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, 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. - ----------------------------------------------------------------------------- - -This software may contain code from MIT Kerberos 5: - -Copyright Notice and Legal Administrivia ----------------------------------------- - -Copyright (C) 1996 by the Massachusetts Institute of Technology. - -All rights reserved. - -Export of this software from the United States of America may require -a specific license from the United States Government. It is the -responsibility of any person or organization contemplating export to -obtain such a license before exporting. - -WITHIN THAT CONSTRAINT, permission to use, copy, modify, and -distribute this software and its documentation for any purpose and -without fee is hereby granted, provided that the above copyright -notice appear in all copies and that both that copyright notice and -this permission notice appear in supporting documentation, and that -the name of M.I.T. not be used in advertising or publicity pertaining -to distribution of the software without specific, written prior -permission. M.I.T. makes no representations about the suitability of -this software for any purpose. It is provided "as is" without express -or implied warranty. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -Individual source code files are copyright MIT, Cygnus Support, -OpenVision, Oracle, Sun Soft, and others. - -Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, -and Zephyr are trademarks of the Massachusetts Institute of Technology -(MIT). No commercial use of these trademarks may be made without -prior written permission of MIT. - -"Commercial use" means use of a name in a product or other for-profit -manner. It does NOT prevent a commercial firm from referring to the -MIT trademarks in order to convey information (although in doing so, -recognition of their trademark status should be given). - -The following copyright and permission notice applies to the -OpenVision Kerberos Administration system located in kadmin/create, -kadmin/dbutil, kadmin/passwd, kadmin/server, lib/kadm5, and portions -of lib/rpc: - - Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved - - WARNING: Retrieving the OpenVision Kerberos Administration system - source code, as described below, indicates your acceptance of the - following terms. If you do not agree to the following terms, do not - retrieve the OpenVision Kerberos administration system. - - You may freely use and distribute the Source Code and Object Code - compiled from it, with or without modification, but this Source - Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, - INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR - FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER - EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY - FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR - CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, - WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE - CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY - OTHER REASON. - - OpenVision retains all copyrights in the donated Source Code. OpenVision - also retains copyright to derivative works of the Source Code, whether - created by OpenVision or by a third party. The OpenVision copyright - notice must be preserved if derivative works are made based on the - donated Source Code. - - OpenVision Technologies, Inc. has donated this Kerberos - Administration system to MIT for inclusion in the standard - Kerberos 5 distribution. This donation underscores our - commitment to continuing Kerberos technology development - and our gratitude for the valuable work which has been - performed by MIT and the Kerberos community. - - diff --git a/lib/libpam/modules/pam_krb5/Makefile b/lib/libpam/modules/pam_krb5/Makefile index 4a83e66a12e9..0e0cbaf3ec4e 100644 --- a/lib/libpam/modules/pam_krb5/Makefile +++ b/lib/libpam/modules/pam_krb5/Makefile @@ -26,8 +26,7 @@ LIB= pam_krb5 SHLIB_NAME= pam_krb5.so -SRCS= pam_krb5_auth.c pam_krb5_pass.c pam_krb5_acct.c \ - pam_krb5_sess.c support.c compat_heimdal.c +SRCS= pam_krb5.c DPADD= ${LIBKRB5} ${LIBGSSAPI} ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} \ ${LIBCOM_ERR} ${LIBROKEN} LDADD= -lkrb5 -lgssapi -lasn1 -lcrypto -lcrypt -lcom_err \ diff --git a/lib/libpam/modules/pam_krb5/README b/lib/libpam/modules/pam_krb5/README deleted file mode 100644 index fa9a19acf82a..000000000000 --- a/lib/libpam/modules/pam_krb5/README +++ /dev/null @@ -1,72 +0,0 @@ -$FreeBSD$ - -This is the README for pam_krb5, a PAM module which support Kerberos 5 -authentication. - -This software is Copyright (c) 1999-2000 Frank Cusack. -All Rights Reserved. - -See the COPYRIGHT file, included with this distribution, for copyright -and redistribution information. - -Author: -Frank Cusack - - - -I. Kerberos notes - -This PAM module requires the MIT 1.1+ release of Kerberos, or the Cygnus -CNS distribution. It has not been tested against heimdal or any other -Kerberos distributions. - -Unlike other PAM Kerberos 5 modules out there, this one does not -use any private Kerberos interfaces. Thus, you need only the -header files and libraries that are part of the Kerberos distribution. - - -II. OS notes - -This software has been tested against Solaris 2.6. It should compile -against Linux (distributions?) with minimal (if any) changes. Reports -of OS [in]compatibilities are welcomed. - -dtlogin on Solaris doesn't support xrealm logins (probably a good thing). - -III. PAM notes/open issues - -auth module: -When is pam_sm_setcred() ever called with flags other than PAM_ESTABLISH_CRED? -It would be fairly easy to support PAM_DELETE_CRED. - -acct module: -I believe this to be complete. - -session module: -This is complete (both functions just return success). - -passwd module: -When is pam_sm_chauthtok() ever called with flags other than -PAM_UPDATE_AUTHTOK? - - -IV. Usage - -Simply change /etc/pam.conf to include this module. Make sure to include -the acct category whenever you use the auth category, or .k5login will -not get checked. - -You probably want to make this module "sufficient", before your unix -(or other) module(s). - - -V. Acknowledgements - -Thanks to Naomaru Itoi , -Curtis King , and Derrick Brashear , -all of whom have written and made available Kerberos 4/5 modules. -Although no code in this module is directly from these author's modules, -(except the get_user_info() routine in support.c; derived from whichever -of these authors originally wrote the first module the other 2 copied from), -it was extremely helpful to look over their code which aided in my design. - diff --git a/lib/libpam/modules/pam_krb5/TODO b/lib/libpam/modules/pam_krb5/TODO deleted file mode 100644 index 1f0939f256c8..000000000000 --- a/lib/libpam/modules/pam_krb5/TODO +++ /dev/null @@ -1,16 +0,0 @@ -$FreeBSD$ - -Things for 1.1, in no particular order: - -Check against Solaris 7, Solaris 8 beta. Check SEAM compatibility. -Check against Linux (Redhat, others?). -Check against HPUX. -Fix PAM flags checking. -Add more debugging for successful calls. -Move "entry" debugging up. -Check bounds on str* calls. [paranoia] - -Get defaults from krb5.conf? -** Allow no-xrealm, this module typically used for local login ** -** Add notes about runtime text relocation on Solaris ** - diff --git a/lib/libpam/modules/pam_krb5/compat_heimdal.c b/lib/libpam/modules/pam_krb5/compat_heimdal.c deleted file mode 100644 index 926b5338040f..000000000000 --- a/lib/libpam/modules/pam_krb5/compat_heimdal.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * compat_heimdal.c - * - * Heimdal compatability layer. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include - -#include -#include -#include -#include "pam_krb5.h" - -const char * -compat_princ_component(krb5_context context, krb5_principal princ, int n) -{ - return princ->name.name_string.val[n]; -} - -void -compat_free_data_contents(krb5_context context, krb5_data *data) -{ - krb5_xfree(data->data); -} - -static krb5_error_code -heimdal_pam_prompter(krb5_context context, void *data, const char *name, - const char *banner, int num_prompts, krb5_prompt prompts[]) -{ - int pam_prompts = num_prompts; - int pamret, i; - - struct pam_message *msg; - struct pam_response *resp = NULL; - struct pam_conv *conv; - pam_handle_t *pamh = (pam_handle_t *) data; - - if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0) - return KRB5KRB_ERR_GENERIC; - - if (banner) - pam_prompts++; - - msg = calloc(sizeof(struct pam_message) * pam_prompts, 1); - if (!msg) - return ENOMEM; - - /* Now use pam_prompts as an index */ - pam_prompts = 0; - - if (banner) { - msg[pam_prompts].msg = malloc(strlen(banner) + 1); - if (!msg[pam_prompts].msg) - goto cleanup; - strcpy((char *) msg[pam_prompts].msg, banner); - msg[pam_prompts].msg_style = PAM_TEXT_INFO; - pam_prompts++; - } - - for (i = 0; i < num_prompts; i++) { - msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3); - if (!msg[pam_prompts].msg) - goto cleanup; - sprintf((char *) msg[pam_prompts].msg, "%s: ", prompts[i].prompt); - msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF - : PAM_PROMPT_ECHO_ON; - pam_prompts++; - } - - if ((pamret = conv->conv(pam_prompts, (const struct pam_message **) &msg, - &resp, conv->appdata_ptr)) != 0) - goto cleanup; - - if (!resp) - goto cleanup; - - /* Reuse pam_prompts as a starting index */ - pam_prompts = 0; - if (banner) - pam_prompts++; - - for (i = 0; i < num_prompts; i++, pam_prompts++) { - register int len; - if (!resp[pam_prompts].resp) { - pamret = PAM_AUTH_ERR; - goto cleanup; - } - len = strlen(resp[pam_prompts].resp); /* Help out the compiler */ - if (len > prompts[i].reply->length) { - pamret = PAM_AUTH_ERR; - goto cleanup; - } - memcpy(prompts[i].reply->data, resp[pam_prompts].resp, len); - prompts[i].reply->length = len; - } - -cleanup: - /* pam_prompts is correct at this point */ - - for (i = 0; i < pam_prompts; i++) { - if (msg[i].msg) - free((char *) msg[i].msg); - } - free(msg); - - if (resp) { - for (i = 0; i < pam_prompts; i++) { - /* - * Note that PAM is underspecified wrt free()'ing resp[i].resp. - * It's not clear if I should free it, or if the application - * has to. Therefore most (all?) apps won't free() it, and I - * can't either, as I am not sure it was malloc()'d. All PAM - * implementations I've seen leak memory here. Not so bad, IFF - * you fork/exec for each PAM authentication (as is typical). - */ -#if 0 - if (resp[i].resp) - free(resp[i].resp); -#endif /* 0 */ - } - /* This does not lose resp[i].resp if the application saved a copy. */ - free(resp); - } - - return (pamret ? KRB5KRB_ERR_GENERIC : 0); -} - -krb5_prompter_fct pam_prompter = heimdal_pam_prompter; diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.c b/lib/libpam/modules/pam_krb5/pam_krb5.c new file mode 100644 index 000000000000..af6e4f435f88 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5.c @@ -0,0 +1,1100 @@ +/*- + * Copyright 2001 Mark R V Murray + * Copyright Frank Cusack fcusack@fcusack.com 1999-2000 + * 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, 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$ + * --------------------------------------------------------------------------- + * + * This software may contain code from Naomaru Itoi: + * + * PAM-kerberos5 module Copyright notice. + * Naomaru Itoi , June 24, 1997. + * + * ---------------------------------------------------------------------------- + * COPYRIGHT (c) 1997 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS AND REDISTRIBUTE + * THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR ANY PURPOSE, SO LONG AS THE NAME + * OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY ADVERTISING OR PUBLICITY + * PERTAINING TO THE USE OR DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, + * WRITTEN PRIOR AUTHORIZATION. IF THE ABOVE COPYRIGHT NOTICE OR ANY OTHER + * IDENTIFICATION OF THE UNIVERSITY OF MICHIGAN IS INCLUDED IN ANY COPY OF ANY + * PORTION OF THIS SOFTWARE, THEN THE DISCLAIMER BELOW MUST ALSO BE INCLUDED. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY OF + * MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE + * UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABITILY AND FITNESS FOR A + * PARTICULAR PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE + * LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN + * CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * PAM-kerberos5 module is written based on PAM-kerberos4 module + * by Derrick J. Brashear and kerberos5-1.0pl1 by M.I.T. kerberos team. + * Permission to use, copy, modify, distribute this software is hereby + * granted, as long as it is granted by Derrick J. Brashear and + * M.I.T. kerberos team. Followings are their copyright information. + * ---------------------------------------------------------------------------- + * + * This software may contain code from Derrick J. Brashear: + * + * + * Copyright (c) Derrick J. Brashear, 1996. 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, 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. + * + * ---------------------------------------------------------------------------- + * + * This software may contain code from MIT Kerberos 5: + * + * Copyright Notice and Legal Administrivia + * ---------------------------------------- + * + * Copyright (C) 1996 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Individual source code files are copyright MIT, Cygnus Support, + * OpenVision, Oracle, Sun Soft, and others. + * + * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, + * and Zephyr are trademarks of the Massachusetts Institute of Technology + * (MIT). No commercial use of these trademarks may be made without + * prior written permission of MIT. + * + * "Commercial use" means use of a name in a product or other for-profit + * manner. It does NOT prevent a commercial firm from referring to the + * MIT trademarks in order to convey information (although in doing so, + * recognition of their trademark status should be given). + * + * The following copyright and permission notice applies to the + * OpenVision Kerberos Administration system located in kadmin/create, + * kadmin/dbutil, kadmin/passwd, kadmin/server, lib/kadm5, and portions + * of lib/rpc: + * + * Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved + * + * WARNING: Retrieving the OpenVision Kerberos Administration system + * source code, as described below, indicates your acceptance of the + * following terms. If you do not agree to the following terms, do not + * retrieve the OpenVision Kerberos administration system. + * + * You may freely use and distribute the Source Code and Object Code + * compiled from it, with or without modification, but this Source + * Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, + * INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER + * EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY + * FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, + * WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE + * CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY + * OTHER REASON. + * + * OpenVision retains all copyrights in the donated Source Code. OpenVision + * also retains copyright to derivative works of the Source Code, whether + * created by OpenVision or by a third party. The OpenVision copyright + * notice must be preserved if derivative works are made based on the + * donated Source Code. + * + * OpenVision Technologies, Inc. has donated this Kerberos + * Administration system to MIT for inclusion in the standard + * Kerberos 5 distribution. This donation underscores our + * commitment to continuing Kerberos technology development + * and our gratitude for the valuable work which has been + * performed by MIT and the Kerberos community. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_SESSION +#define PAM_SM_PASSWORD + +#include +#include + +#include "pam_mod_misc.h" + +#define COMPAT_HEIMDAL +/* #define COMPAT_MIT */ + +extern krb5_cc_ops krb5_mcc_ops; + +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 NEW_PASSWORD_PROMPT_2 "New Password (again): " + +enum { PAM_OPT_AUTH_AS_SELF=PAM_OPT_STD_MAX, PAM_OPT_CCACHE, PAM_OPT_FORWARDABLE, PAM_OPT_NO_CCACHE, PAM_OPT_REUSE_CCACHE }; + +static struct opttab other_options[] = { + { "auth_as_self", PAM_OPT_AUTH_AS_SELF }, + { "ccache", PAM_OPT_CCACHE }, + { "forwardable", PAM_OPT_FORWARDABLE }, + { "no_ccache", PAM_OPT_NO_CCACHE }, + { "reuse_ccache", PAM_OPT_REUSE_CCACHE }, + { NULL, 0 } +}; + +/* + * authentication management + */ +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + krb5_error_code krbret; + krb5_context pam_context; + krb5_creds creds; + krb5_principal princ; + krb5_ccache ccache, ccache_check; + krb5_get_init_creds_opt opts; + struct options options; + struct passwd *pwd; + int retval; + const char *sourceuser, *user, *pass; + char *principal, *princ_name, *service, *cache_name, luser[32]; + + pam_std_option(&options, other_options, argc, argv); + + PAM_LOG("Options processed"); + + retval = pam_get_user(pamh, &user, USER_PROMPT); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + + PAM_LOG("Got user: %s", user); + + retval = pam_get_item(pamh, PAM_RUSER, (const void **)&sourceuser); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + + PAM_LOG("Got ruser: %s", sourceuser); + + service = NULL; + pam_get_item(pamh, PAM_SERVICE, (const void **)&service); + if (service == NULL) + service = "unknown"; + + PAM_LOG("Got service: %s", service); + + krbret = krb5_init_context(&pam_context); + if (krbret != 0) { + PAM_VERBOSE_ERROR("Kerberos 5 error"); + PAM_RETURN(PAM_SERVICE_ERR); + } + + PAM_LOG("Context initialised"); + + krb5_get_init_creds_opt_init(&opts); + + if (pam_test_option(&options, PAM_OPT_FORWARDABLE, NULL)) + 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 (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL)) + asprintf(&principal, "%s/%s", 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", error_message(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", error_message(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_pass(pamh, &pass, PASSWORD_PROMPT, &options); + 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", + error_message(krbret)); + retval = PAM_USER_UNKNOWN; + goto cleanup2; + } + + retval = pam_set_item(pamh, PAM_USER, luser); + if (retval != PAM_SUCCESS) + goto cleanup2; + + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + 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", + error_message(krbret)); + retval = PAM_AUTH_ERR; + goto cleanup2; + } + + PAM_LOG("Got TGT"); + + /* Generate a unique cache_name */ + asprintf(&cache_name, "MEMORY:/tmp/%s.%d", service, getpid()); + krbret = krb5_cc_resolve(pam_context, cache_name, &ccache); + free(cache_name); + if (krbret != 0) { + PAM_VERBOSE_ERROR("Kerberos 5 error"); + PAM_LOG("Error krb5_cc_resolve(): %s", error_message(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", error_message(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", error_message(krbret)); + krb5_cc_destroy(pam_context, ccache); + retval = PAM_SERVICE_ERR; + goto cleanup; + } + + PAM_LOG("Credentials stashed"); + + /* Verify them */ + if (verify_krb_v5_tgt(pam_context, ccache, service, + pam_test_option(&options, PAM_OPT_FORWARDABLE, NULL)) == -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", (const void **)&ccache_check); + 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"); + + retval = pam_set_data(pamh, "ccache", ccache, 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"); + + PAM_RETURN(retval); +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + + 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 options options; + struct passwd *pwd = NULL; + int retval; + char *user; + char *cache_name, *cache_env_name, *p, *q; + + uid_t euid; + gid_t egid; + + pam_std_option(&options, other_options, argc, argv); + + PAM_LOG("Options processed"); + + if (flags & PAM_DELETE_CRED) + PAM_RETURN(PAM_SUCCESS); + + if (flags & PAM_REFRESH_CRED) + PAM_RETURN(PAM_SUCCESS); + + if (flags & PAM_REINITIALIZE_CRED) + PAM_RETURN(PAM_SUCCESS); + + if (!(flags & PAM_ESTABLISH_CRED)) + PAM_RETURN(PAM_SERVICE_ERR); + + PAM_LOG("Establishing credentials"); + + /* Get username */ + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + + PAM_LOG("Got user: %s", user); + + krbret = krb5_init_context(&pam_context); + if (krbret != 0) { + PAM_LOG("Error krb5_init_context(): %s", error_message(krbret)); + PAM_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 cache name */ + retval = pam_get_data(pamh, "ccache", (const void **)&ccache_temp); + if (retval != PAM_SUCCESS) + 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 = NULL; + pam_test_option(&options, PAM_OPT_CCACHE, &cache_name); + if (cache_name == NULL) + asprintf(&cache_name, "FILE:/tmp/krb5cc_%d", pwd->pw_uid); + + 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", + error_message(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", error_message(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", error_message(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", error_message(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", + error_message(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"); + + cache_env_name = malloc(strlen(cache_name) + 12); + if (!cache_env_name) { + PAM_LOG("Error malloc(): failure"); + krb5_cc_destroy(pam_context, ccache_perm); + retval = PAM_BUF_ERR; + goto cleanup2; + } + + sprintf(cache_env_name, "KRB5CCNAME=%s", cache_name); + if ((retval = pam_putenv(pamh, cache_env_name)) != 0) { + PAM_LOG("Error pam_putenv(): %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()"); + + PAM_RETURN(retval); +} + +/* + * account management + */ +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + krb5_error_code krbret; + krb5_context pam_context; + krb5_ccache ccache; + krb5_principal princ; + struct options options; + int retval; + const char *user; + + pam_std_option(&options, other_options, argc, argv); + + PAM_LOG("Options processed"); + + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + + PAM_LOG("Got user: %s", user); + + retval = pam_get_data(pamh, "ccache", (const void **)&ccache); + if (retval != PAM_SUCCESS) + PAM_RETURN(PAM_SUCCESS); + + PAM_LOG("Got ccache"); + + krbret = krb5_init_context(&pam_context); + if (krbret != 0) { + PAM_LOG("Error krb5_init_context(): %s", error_message(krbret)); + PAM_RETURN(PAM_PERM_DENIED); + } + + PAM_LOG("Context initialised"); + + krbret = krb5_cc_get_principal(pam_context, ccache, &princ); + if (krbret != 0) { + PAM_LOG("Error krb5_cc_get_principal(): %s", error_message(krbret)); + retval = PAM_PERM_DENIED;; + goto cleanup; + } + + PAM_LOG("Got principal"); + + if (krb5_kuserok(pam_context, princ, 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"); + + PAM_RETURN(retval); + +} + +/* + * session management + * + * logging only + */ +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + struct options options; + + pam_std_option(&options, NULL, argc, argv); + + PAM_LOG("Options processed"); + + PAM_RETURN(PAM_SUCCESS); +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + struct options options; + + pam_std_option(&options, NULL, argc, argv); + + PAM_LOG("Options processed"); + + PAM_RETURN(PAM_SUCCESS); +} + +/* + * password management + */ +PAM_EXTERN int +pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + 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; + struct options options; + int result_code, retval; + const char *user, *pass, *pass2; + char *princ_name; + + pam_std_option(&options, other_options, argc, argv); + + PAM_LOG("Options processed"); + + if (!(flags & PAM_UPDATE_AUTHTOK)) + PAM_RETURN(PAM_AUTHTOK_ERR); + + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + + PAM_LOG("Got user: %s", user); + + krbret = krb5_init_context(&pam_context); + if (krbret != 0) { + PAM_LOG("Error krb5_init_context(): %s", error_message(krbret)); + PAM_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, user, &princ); + if (krbret != 0) { + PAM_LOG("Error krb5_parse_name(): %s", error_message(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", error_message(krbret)); + retval = PAM_SERVICE_ERR; + goto cleanup2; + } + + PAM_LOG("Got principal: %s", princ_name); + + /* Get password */ + retval = pam_get_pass(pamh, &pass, PASSWORD_PROMPT, &options); + 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()", + error_message(krbret)); + retval = PAM_AUTH_ERR; + goto cleanup2; + } + + PAM_LOG("Credentials established"); + + /* Now get the new password */ + retval = pam_get_pass(pamh, &pass, NEW_PASSWORD_PROMPT, &options); + if (retval != PAM_SUCCESS) + goto cleanup; + + retval = pam_get_pass(pamh, &pass2, NEW_PASSWORD_PROMPT_2, &options); + if (retval != PAM_SUCCESS) + goto cleanup; + + PAM_LOG("Got new password twice"); + + if (strcmp(pass, pass2) != 0) { + PAM_LOG("Error strcmp(): passwords are different"); + retval = PAM_AUTHTOK_ERR; + goto cleanup; + } + + PAM_LOG("New passwords are the same"); + + /* Change it */ + krbret = krb5_change_password(pam_context, &creds, (char *)pass, + &result_code, &result_code_string, &result_string); + if (krbret != 0) { + PAM_LOG("Error krb5_change_password(): %s", + error_message(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"); + + PAM_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. + */ +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], *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()", error_message(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()", error_message(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()", error_message(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()", error_message(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() */ +static void +cleanup_cache(pam_handle_t *pamh, void *data, int pam_end_status) +{ + krb5_context pam_context; + krb5_ccache ccache; + + if (krb5_init_context(&pam_context)) + return; + + ccache = (krb5_ccache)data; + krb5_cc_destroy(pam_context, ccache); + krb5_free_context(pam_context); +} + +#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 +static const char * +compat_princ_component(krb5_context context, krb5_principal princ, int n) +{ + return princ->name.name_string.val[n]; +} + +static void +compat_free_data_contents(krb5_context context, 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/libpam/modules/pam_krb5/pam_krb5.h b/lib/libpam/modules/pam_krb5/pam_krb5.h deleted file mode 100644 index d14c62e2af3a..000000000000 --- a/lib/libpam/modules/pam_krb5/pam_krb5.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * pam_krb5.h - * - * $Id: pam_krb5.h,v 1.5 1999/01/19 23:43:10 fcusack Exp $ - * $FreeBSD$ - */ - -int get_user_info(pam_handle_t *, char *, int, char **); -int verify_krb_v5_tgt(krb5_context, krb5_ccache, char *, int); -void cleanup_cache(pam_handle_t *, void *, int); - -krb5_prompter_fct pam_prompter; - -const char *compat_princ_component(krb5_context, krb5_principal, int); -void compat_free_data_contents(krb5_context, krb5_data *); - -#ifndef ENCTYPE_DES_CBC_MD5 -#define ENCTYPE_DES_CBC_MD5 ETYPE_DES_CBC_MD5 -#endif - - diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_acct.c b/lib/libpam/modules/pam_krb5/pam_krb5_acct.c deleted file mode 100644 index 1a2910bc1d8e..000000000000 --- a/lib/libpam/modules/pam_krb5/pam_krb5_acct.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * pam_krb5_acct.c - * - * PAM account management functions for pam_krb5 - * - * $FreeBSD$ - */ - -static const char rcsid[] = "$Id: pam_krb5_acct.c,v 1.3 1999/01/19 21:26:44 fcusack Exp $"; - -#include /* syslog */ -#include -#include -#include -#include -#include "pam_krb5.h" - -/* A useful logging macro */ -#define DLOG(error_func, error_msg) \ -if (debug) \ - syslog(LOG_DEBUG, "pam_krb5: pam_sm_acct_mgmt(%s %s): %s: %s", \ - service, name, error_func, error_msg) - -/* Check authorization of user */ -int -pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) -{ - krb5_error_code krbret; - krb5_context pam_context; - krb5_ccache ccache; - krb5_principal princ; - - char *service, *name; - int debug = 0; - int i, pamret; - - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "debug") == 0) - debug = 1; - } - - /* Get username */ - if (pam_get_item(pamh, PAM_USER, (const void **) &name)) { - return PAM_PERM_DENIED;; - } - - /* Get service name */ - (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); - if (!service) - service = "unknown"; - - DLOG("entry", ""); - - if (pam_get_data(pamh, "ccache", (const void **) &ccache)) { - /* User did not use krb5 to login */ - DLOG("ccache", "not found"); - return PAM_SUCCESS; - } - - if ((krbret = krb5_init_context(&pam_context)) != 0) { - DLOG("krb5_init_context()", error_message(krbret)); - return PAM_PERM_DENIED;; - } - - if ((krbret = krb5_cc_get_principal(pam_context, ccache, &princ)) != 0) { - DLOG("krb5_cc_get_principal()", error_message(krbret)); - pamret = PAM_PERM_DENIED;; - goto cleanup; - } - - if (krb5_kuserok(pam_context, princ, name)) - pamret = PAM_SUCCESS; - else - pamret = PAM_PERM_DENIED; - krb5_free_principal(pam_context, princ); - -cleanup: - krb5_free_context(pam_context); - DLOG("exit", pamret ? "failure" : "success"); - return pamret; - -} - diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_auth.c b/lib/libpam/modules/pam_krb5/pam_krb5_auth.c deleted file mode 100644 index 00d6ab77b27e..000000000000 --- a/lib/libpam/modules/pam_krb5/pam_krb5_auth.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * pam_krb5_auth.c - * - * PAM authentication management functions for pam_krb5 - * - * $FreeBSD$ - */ - -static const char rcsid[] = "$Id: pam_krb5_auth.c,v 1.18 2000/01/04 08:44:08 fcusack Exp $"; - -#include -#include -#include -#include /* PATH_MAX */ -#include /* getpwnam */ -#include /* tmpnam */ -#include /* malloc */ -#include /* strchr */ -#include /* syslog */ -#include /* chown */ - -#include -#include - -#include -#include -#include "pam_krb5.h" - -extern krb5_cc_ops krb5_mcc_ops; - -/* A useful logging macro */ -#define DLOG(error_func, error_msg) \ -if (debug) \ - syslog(LOG_DEBUG, "pam_krb5: pam_sm_authenticate(%s %s): %s: %s", \ - service, name, error_func, error_msg) - -/* Authenticate a user via krb5 */ -int -pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, - const char **argv) -{ - krb5_error_code krbret; - krb5_context pam_context; - krb5_creds creds; - krb5_principal princ; - krb5_ccache ccache, ccache_check; - krb5_get_init_creds_opt opts; - - int pamret, i; - const char *name; - char *princ_name = NULL; - char *pass = NULL, *service = NULL; - char *prompt = NULL; - char cache_name[L_tmpnam + 8]; - char lname[64]; /* local acct name */ - struct passwd *pw; - - int debug = 0, try_first_pass = 0, use_first_pass = 0; - int forwardable = 0, reuse_ccache = 0, no_ccache = 0; - - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "debug") == 0) - debug = 1; - else if (strcmp(argv[i], "try_first_pass") == 0) - try_first_pass = 1; - else if (strcmp(argv[i], "use_first_pass") == 0) - use_first_pass = 1; - else if (strcmp(argv[i], "forwardable") == 0) - forwardable = 1; - else if (strcmp(argv[i], "reuse_ccache") == 0) - reuse_ccache = 1; - else if (strcmp(argv[i], "no_ccache") == 0) - no_ccache = 1; - } - - /* Get username */ - if ((pamret = pam_get_user(pamh, &name, "login: ")) != PAM_SUCCESS) { - return PAM_SERVICE_ERR; - } - - /* Get service name */ - (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); - if (!service) - service = "unknown"; - - DLOG("entry", ""); - - if ((krbret = krb5_init_context(&pam_context)) != 0) { - DLOG("krb5_init_context()", error_message(krbret)); - return PAM_SERVICE_ERR; - } - krb5_get_init_creds_opt_init(&opts); - memset(&creds, 0, sizeof(krb5_creds)); - memset(cache_name, 0, sizeof(cache_name)); - memset(lname, 0, sizeof(lname)); - - if (forwardable) - krb5_get_init_creds_opt_set_forwardable(&opts, 1); - - /* For CNS */ - if ((krbret = krb5_cc_register(pam_context, &krb5_mcc_ops, FALSE)) != 0) { - /* Solaris dtlogin doesn't call pam_end() on failure */ - if (krbret != KRB5_CC_TYPE_EXISTS) { - DLOG("krb5_cc_register()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup3; - } - } - - /* Get principal name */ - if ((krbret = krb5_parse_name(pam_context, name, &princ)) != 0) { - DLOG("krb5_parse_name()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup3; - } - - /* Now convert the principal name into something human readable */ - if ((krbret = krb5_unparse_name(pam_context, princ, &princ_name)) != 0) { - DLOG("krb5_unparse_name()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - - /* Get password */ - prompt = malloc(16 + strlen(princ_name)); - if (!prompt) { - DLOG("malloc()", "failure"); - pamret = PAM_BUF_ERR; - goto cleanup2; - } - (void) sprintf(prompt, "Password for %s: ", princ_name); - - if (try_first_pass || use_first_pass) - (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); - -get_pass: - if (!pass) { - try_first_pass = 0; - if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, - &pass)) != 0) { - DLOG("get_user_info()", pam_strerror(pamh, pamret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - /* We have to free pass. */ - if ((pamret = pam_set_item(pamh, PAM_AUTHTOK, pass)) != 0) { - DLOG("pam_set_item()", pam_strerror(pamh, pamret)); - free(pass); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - free(pass); - /* Now we get it back from the library. */ - (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); - } - - /* Verify the local user exists (AFTER getting the password) */ - if (strchr(name, '@')) { - /* get a local account name for this principal */ - if ((krbret = krb5_aname_to_localname(pam_context, princ, - sizeof(lname), lname)) != 0) { - DLOG("krb5_aname_to_localname()", error_message(krbret)); - pamret = PAM_USER_UNKNOWN; - goto cleanup2; - } - DLOG("changing PAM_USER to", lname); - if ((pamret = pam_set_item(pamh, PAM_USER, lname)) != 0) { - DLOG("pam_set_item()", pam_strerror(pamh, pamret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - if ((pamret = pam_get_item(pamh, PAM_USER, (const void **) &name) - != 0)) { - DLOG("pam_get_item()", pam_strerror(pamh, pamret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - } - pw = getpwnam(name); - if (!pw) { - DLOG("getpwnam()", lname); - pamret = PAM_USER_UNKNOWN; - goto cleanup2; - } - - /* Get a TGT */ - if ((krbret = krb5_get_init_creds_password(pam_context, &creds, princ, - pass, pam_prompter, pamh, 0, NULL, &opts)) != 0) { - DLOG("krb5_get_init_creds_password()", error_message(krbret)); - if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { - pass = NULL; - goto get_pass; - } - pamret = PAM_AUTH_ERR; - goto cleanup2; - } - - /* Generate a unique cache_name */ - strcpy(cache_name, "MEMORY:"); - (void) tmpnam(&cache_name[7]); - - if ((krbret = krb5_cc_resolve(pam_context, cache_name, &ccache)) != 0) { - DLOG("krb5_cc_resolve()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup; - } - if ((krbret = krb5_cc_initialize(pam_context, ccache, princ)) != 0) { - DLOG("krb5_cc_initialize()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup; - } - if ((krbret = krb5_cc_store_cred(pam_context, ccache, &creds)) != 0) { - DLOG("krb5_cc_store_cred()", error_message(krbret)); - (void) krb5_cc_destroy(pam_context, ccache); - pamret = PAM_SERVICE_ERR; - goto cleanup; - } - - /* Verify it */ - if (verify_krb_v5_tgt(pam_context, ccache, service, debug) == -1) { - (void) krb5_cc_destroy(pam_context, ccache); - pamret = PAM_AUTH_ERR; - goto cleanup; - } - - /* A successful authentication, store ccache for sm_setcred() */ - if (!pam_get_data(pamh, "ccache", (const void **) &ccache_check)) { - DLOG("pam_get_data()", "ccache data already present"); - (void) krb5_cc_destroy(pam_context, ccache); - pamret = PAM_AUTH_ERR; - goto cleanup; - } - if ((pamret = pam_set_data(pamh, "ccache", ccache, cleanup_cache)) != 0) { - DLOG("pam_set_data()", pam_strerror(pamh, pamret)); - (void) krb5_cc_destroy(pam_context, ccache); - pamret = PAM_SERVICE_ERR; - goto cleanup; - } - -cleanup: - krb5_free_cred_contents(pam_context, &creds); -cleanup2: - krb5_free_principal(pam_context, princ); -cleanup3: - if (prompt) - free(prompt); - if (princ_name) - free(princ_name); - - krb5_free_context(pam_context); - DLOG("exit", pamret ? "failure" : "success"); - return pamret; -} - - - -/* redefine this for pam_sm_setcred() */ -#undef DLOG -#define DLOG(error_func, error_msg) \ -if (debug) \ - syslog(LOG_DEBUG, "pam_krb5: pam_sm_setcred(%s %s): %s: %s", \ - service, name, error_func, error_msg) - -/* Called after a successful authentication. Set user credentials. */ -int -pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, - const char **argv) -{ - - krb5_error_code krbret; - krb5_context pam_context; - krb5_principal princ; - krb5_creds creds; - krb5_ccache ccache_temp, ccache_perm; - krb5_cc_cursor cursor; - - int i, pamret; - char *name, *service = NULL; - char *cache_name = NULL, *cache_env_name; - struct passwd *pw = NULL; - - int debug = 0; - uid_t euid; - gid_t egid; - - if (flags == PAM_REINITIALIZE_CRED) - return PAM_SUCCESS; /* XXX Incorrect behavior */ - - if (flags != PAM_ESTABLISH_CRED) - return PAM_SERVICE_ERR; - - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "debug") == 0) - debug = 1; - else if (strcmp(argv[i], "no_ccache") == 0) - return PAM_SUCCESS; - else if (strstr(argv[i], "ccache=") == argv[i]) - cache_name = (char *) &argv[i][7]; /* save for later */ - } - - /* Get username */ - if (pam_get_item(pamh, PAM_USER, (const void **) &name)) { - return PAM_SERVICE_ERR; - } - - /* Get service name */ - (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); - if (!service) - service = "unknown"; - - DLOG("entry", ""); - - if ((krbret = krb5_init_context(&pam_context)) != 0) { - DLOG("krb5_init_context()", error_message(krbret)); - return PAM_SERVICE_ERR; - } - - euid = geteuid(); /* Usually 0 */ - egid = getegid(); - - /* Retrieve the cache name */ - if ((pamret = pam_get_data(pamh, "ccache", (const void **) &ccache_temp)) - != 0) { - DLOG("pam_get_data()", pam_strerror(pamh, pamret)); - pamret = PAM_CRED_UNAVAIL; - goto cleanup3; - } - - /* Get the uid. This should exist. */ - pw = getpwnam(name); - if (!pw) { - DLOG("getpwnam()", name); - pamret = PAM_USER_UNKNOWN; - goto cleanup3; - } - - /* 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; - goto cleanup3; - } - - /* Get the cache name */ - if (!cache_name) { - cache_name = malloc(64); /* plenty big */ - if (!cache_name) { - DLOG("malloc()", "failure"); - pamret = PAM_BUF_ERR; - goto cleanup3; - } - sprintf(cache_name, "FILE:/tmp/krb5cc_%d", pw->pw_uid); - } else { - /* cache_name was supplied */ - char *p = calloc(PATH_MAX + 10, 1); /* should be plenty */ - char *q = cache_name; - if (!p) { - DLOG("malloc()", "failure"); - pamret = PAM_BUF_ERR; - goto cleanup3; - } - cache_name = p; - - /* convert %u and %p */ - while (*q) { - if (*q == '%') { - q++; - if (*q == 'u') { - sprintf(p, "%d", pw->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++; - } - } - } - - /* Initialize the new ccache */ - if ((krbret = krb5_cc_get_principal(pam_context, ccache_temp, &princ)) - != 0) { - DLOG("krb5_cc_get_principal()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup3; - } - if ((krbret = krb5_cc_resolve(pam_context, cache_name, &ccache_perm)) - != 0) { - DLOG("krb5_cc_resolve()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - if ((krbret = krb5_cc_initialize(pam_context, ccache_perm, princ)) != 0) { - DLOG("krb5_cc_initialize()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - - /* Prepare for iteration over creds */ - if ((krbret = krb5_cc_start_seq_get(pam_context, ccache_temp, &cursor)) - != 0) { - DLOG("krb5_cc_start_seq_get()", error_message(krbret)); - (void) krb5_cc_destroy(pam_context, ccache_perm); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - - /* Copy the creds (should be two of them) */ - while ((krbret = krb5_cc_next_cred(pam_context, ccache_temp, - &cursor, &creds) == 0)) { - if ((krbret = krb5_cc_store_cred(pam_context, ccache_perm, - &creds)) != 0) { - DLOG("krb5_cc_store_cred()", error_message(krbret)); - (void) krb5_cc_destroy(pam_context, ccache_perm); - krb5_free_cred_contents(pam_context, &creds); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - krb5_free_cred_contents(pam_context, &creds); - } - (void) krb5_cc_end_seq_get(pam_context, ccache_temp, &cursor); - - if (strstr(cache_name, "FILE:") == cache_name) { - if (chown(&cache_name[5], pw->pw_uid, pw->pw_gid) == -1) { - DLOG("chown()", strerror(errno)); - (void) krb5_cc_destroy(pam_context, ccache_perm); - 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); - - cache_env_name = malloc(strlen(cache_name) + 12); - if (!cache_env_name) { - DLOG("malloc()", "failure"); - (void) krb5_cc_destroy(pam_context, ccache_perm); - pamret = PAM_BUF_ERR; - goto cleanup2; - } - - sprintf(cache_env_name, "KRB5CCNAME=%s", cache_name); - if ((pamret = pam_putenv(pamh, cache_env_name)) != 0) { - DLOG("pam_putenv()", pam_strerror(pamh, pamret)); - (void) krb5_cc_destroy(pam_context, ccache_perm); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - -cleanup2: - krb5_free_principal(pam_context, princ); -cleanup3: - krb5_free_context(pam_context); - DLOG("exit", pamret ? "failure" : "success"); - (void) seteuid(euid); - (void) setegid(egid); - return pamret; -} - diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_pass.c b/lib/libpam/modules/pam_krb5/pam_krb5_pass.c deleted file mode 100644 index 994c7f4720c6..000000000000 --- a/lib/libpam/modules/pam_krb5/pam_krb5_pass.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * pam_krb5_pass.c - * - * PAM password management functions for pam_krb5 - * - * $FreeBSD$ - */ - -static const char rcsid[] = "$Id: pam_krb5_pass.c,v 1.3 1999/01/19 23:43:11 fcusack Exp $"; - -#include -#include /* sprintf */ -#include /* malloc */ -#include /* syslog */ -#include -#include -#include -#include -#include "pam_krb5.h" - -/* A useful logging macro */ -#define DLOG(error_func, error_msg) \ -if (debug) \ - syslog(LOG_DEBUG, "pam_krb5: pam_sm_chauthtok(%s %s): %s: %s", \ - service, name, error_func, error_msg) - -/* Change a user's password */ -int -pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) -{ - krb5_error_code krbret; - krb5_context pam_context; - krb5_creds creds; - krb5_principal princ; - krb5_get_init_creds_opt opts; - - int result_code; - krb5_data result_code_string, result_string; - - int pamret, i; - char *name, *service = NULL, *pass = NULL, *pass2; - char *princ_name = NULL; - char *prompt = NULL; - - int debug = 0; - int try_first_pass = 0, use_first_pass = 0; - - if (!(flags & PAM_UPDATE_AUTHTOK)) - return PAM_AUTHTOK_ERR; - - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "debug") == 0) - debug = 1; - else if (strcmp(argv[i], "try_first_pass") == 0) - try_first_pass = 1; - else if (strcmp(argv[i], "use_first_pass") == 0) - use_first_pass = 1; - } - - /* Get username */ - if ((pam_get_item(pamh, PAM_USER, (const void **) &name)) != 0) { - return PAM_SERVICE_ERR; - } - - /* Get service name */ - (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); - if (!service) - service = "unknown"; - - DLOG("entry", ""); - - if ((krbret = krb5_init_context(&pam_context)) != 0) { - DLOG("krb5_init_context()", error_message(krbret)); - return PAM_SERVICE_ERR; - } - - if ((krbret = krb5_init_context(&pam_context)) != 0) { - DLOG("krb5_init_context()", error_message(krbret)); - return PAM_SERVICE_ERR; - } - krb5_get_init_creds_opt_init(&opts); - memset(&creds, 0, sizeof(krb5_creds)); - - /* Get principal name */ - if ((krbret = krb5_parse_name(pam_context, name, &princ)) != 0) { - DLOG("krb5_parse_name()", error_message(krbret)); - pamret = PAM_USER_UNKNOWN; - goto cleanup3; - } - - /* Now convert the principal name into something human readable */ - if ((krbret = krb5_unparse_name(pam_context, princ, &princ_name)) != 0) { - DLOG("krb5_unparse_name()", error_message(krbret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - - /* Get password */ - prompt = malloc(16 + strlen(princ_name)); - if (!prompt) { - DLOG("malloc()", "failure"); - pamret = PAM_BUF_ERR; - goto cleanup2; - } - (void) sprintf(prompt, "Password for %s: ", princ_name); - - if (try_first_pass || use_first_pass) - (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); - -get_pass: - if (!pass) { - try_first_pass = 0; - if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, - &pass)) != 0) { - DLOG("get_user_info()", pam_strerror(pamh, pamret)); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - /* We have to free pass. */ - if ((pamret = pam_set_item(pamh, PAM_AUTHTOK, pass)) != 0) { - DLOG("pam_set_item()", pam_strerror(pamh, pamret)); - free(pass); - pamret = PAM_SERVICE_ERR; - goto cleanup2; - } - free(pass); - /* Now we get it back from the library. */ - (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); - } - - if ((krbret = krb5_get_init_creds_password(pam_context, &creds, princ, - pass, pam_prompter, pamh, 0, "kadmin/changepw", &opts)) != 0) { - DLOG("krb5_get_init_creds_password()", error_message(krbret)); - if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { - pass = NULL; - goto get_pass; - } - pamret = PAM_AUTH_ERR; - goto cleanup2; - } - - /* Now get the new password */ - free(prompt); - prompt = "Enter new password: "; - if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass)) - != 0) { - DLOG("get_user_info()", pam_strerror(pamh, pamret)); - prompt = NULL; - pamret = PAM_SERVICE_ERR; - goto cleanup; - } - prompt = "Enter it again: "; - if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass2)) - != 0) { - DLOG("get_user_info()", pam_strerror(pamh, pamret)); - prompt = NULL; - pamret = PAM_SERVICE_ERR; - goto cleanup; - } - prompt = NULL; - - if (strcmp(pass, pass2) != 0) { - DLOG("strcmp()", "passwords not equal"); - pamret = PAM_AUTHTOK_ERR; - goto cleanup; - } - - /* Change it */ - if ((krbret = krb5_change_password(pam_context, &creds, pass, - &result_code, &result_code_string, &result_string)) != 0) { - DLOG("krb5_change_password()", error_message(krbret)); - pamret = PAM_AUTHTOK_ERR; - goto cleanup; - } - if (result_code) { - DLOG("krb5_change_password() (result_code)", ""); - pamret = PAM_AUTHTOK_ERR; - goto cleanup; - } - - 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); -cleanup2: - krb5_free_principal(pam_context, princ); -cleanup3: - if (prompt) - free(prompt); - if (princ_name) - free(princ_name); - - krb5_free_context(pam_context); - DLOG("exit", pamret ? "failure" : "success"); - return pamret; -} - diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_sess.c b/lib/libpam/modules/pam_krb5/pam_krb5_sess.c deleted file mode 100644 index b2df06434fa6..000000000000 --- a/lib/libpam/modules/pam_krb5/pam_krb5_sess.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * pam_krb5_sess.c - * - * PAM session management functions for pam_krb5 - * (null functions) - * - * $FreeBSD$ - */ - -static const char rcsid[] = "$Id: pam_krb5_sess.c,v 1.3 1999/01/19 20:49:44 fcusack Exp $"; - -#include -#include - -/* Initiate session management */ -int -pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) -{ - return PAM_SUCCESS; -} - - -/* Terminate session management */ -int -pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) -{ - return PAM_SUCCESS; -} diff --git a/lib/libpam/modules/pam_krb5/support.c b/lib/libpam/modules/pam_krb5/support.c deleted file mode 100644 index 8e1aecda640f..000000000000 --- a/lib/libpam/modules/pam_krb5/support.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * support.c - * - * Support functions for pam_krb5 - * - * $FreeBSD$ - */ - -static const char rcsid[] = "$Id: support.c,v 1.8 2000/01/04 09:50:03 fcusack Exp $"; - -#include -#include /* BUFSIZ */ -#include /* malloc */ -#include /* strncpy */ -#include /* syslog */ -#include -#include -#include -#include -#include "pam_krb5.h" - -/* - * Get info from the user. Disallow null responses (regardless of flags). - * response gets allocated and filled in on successful return. Caller - * is responsible for freeing it. - */ -int -get_user_info(pam_handle_t *pamh, char *prompt, int type, char **response) -{ - int pamret; - struct pam_message msg; - const struct pam_message *pmsg; - struct pam_response *resp = NULL; - struct pam_conv *conv; - - if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0) - return pamret; - - /* set up conversation call */ - pmsg = &msg; - msg.msg_style = type; - msg.msg = prompt; - - if ((pamret = conv->conv(1, &pmsg, &resp, conv->appdata_ptr)) != 0) - return pamret; - - /* Caller should ignore errors for non-response conversations */ - if (!resp) - return PAM_CONV_ERR; - - if (!(resp->resp && resp->resp[0])) { - free(resp); - return PAM_AUTH_ERR; - } - - *response = resp->resp; - free(resp); - return pamret; -} - -/* - * 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. - */ -int -verify_krb_v5_tgt(krb5_context context, krb5_ccache ccache, - char * pam_service, int debug) -{ - char phost[BUFSIZ]; - 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; - - 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; - 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)); - 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.) - */ - 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", - "krb5_kt_read_service_key()", error_message(retval)); - retval = 0; - goto cleanup; - } - if (keyblock) - krb5_free_keyblock(context, keyblock); - - /* Talk to the kdc and construct the ticket. */ - 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()", error_message(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()", error_message(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() */ -void -cleanup_cache(pam_handle_t *pamh, void *data, int pam_end_status) -{ - krb5_context pam_context; - krb5_ccache ccache; - - if (krb5_init_context(&pam_context)) - return; - - ccache = (krb5_ccache) data; - (void) krb5_cc_destroy(pam_context, ccache); - krb5_free_context(pam_context); -}