diff options
author | markm <markm@FreeBSD.org> | 2001-05-14 11:23:58 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2001-05-14 11:23:58 +0000 |
commit | 8f01d4f9a21b42822e22a8a94f5d7baa665bd832 (patch) | |
tree | 8bff886b0f81c1fac698127dc43ca0d5625ad1f2 /lib | |
parent | db6c759b2bfe8ec70c6b73ef3453944939489372 (diff) | |
download | FreeBSD-src-8f01d4f9a21b42822e22a8a94f5d7baa665bd832.zip FreeBSD-src-8f01d4f9a21b42822e22a8a94f5d7baa665bd832.tar.gz |
Bring in a few useful PAM modules.
pam_krb5 is a Kerberos 5 (Heimdal) authentication module.
pam_nologin checks for /etc/nologin and does the "usual stuff"
if it is found, otherwise it silently succeeds.
pam_rootok silently succeeds if the user is root, otherwise
it fails.
pam_wheel silently succeeds if the user is a member of group
"wheel" (or another nominated group), and fails
otherwise.
There is an issue with kerberosIV and kerberos5 - if both are
being built, then static linking fails with duplicate symbols.
This will take a bit of work to sort out in the kerberii.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libpam/libpam/Makefile | 7 | ||||
-rw-r--r-- | lib/libpam/modules/Makefile | 7 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/COPYRIGHT | 195 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/Makefile | 44 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/README | 72 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/TODO | 16 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/compat_heimdal.c | 141 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/pam_krb5.8 | 191 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/pam_krb5.h | 23 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/pam_krb5_acct.c | 83 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/pam_krb5_auth.c | 505 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/pam_krb5_pass.c | 200 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/pam_krb5_sess.c | 28 | ||||
-rw-r--r-- | lib/libpam/modules/pam_krb5/support.c | 185 | ||||
-rw-r--r-- | lib/libpam/modules/pam_nologin/Makefile | 39 | ||||
-rw-r--r-- | lib/libpam/modules/pam_rootok/Makefile | 39 | ||||
-rw-r--r-- | lib/libpam/modules/pam_wheel/Makefile | 39 |
17 files changed, 1810 insertions, 4 deletions
diff --git a/lib/libpam/libpam/Makefile b/lib/libpam/libpam/Makefile index f44f727..455a7d9 100644 --- a/lib/libpam/libpam/Makefile +++ b/lib/libpam/libpam/Makefile @@ -70,15 +70,18 @@ STATIC_MODULES+= ${MODOBJDIR}/pam_deny/libpam_deny.a .if defined(MAKE_KERBEROS4) && !defined(NOCRYPT) && !defined(NO_OPENSSL) STATIC_MODULES+= ${MODOBJDIR}/pam_kerberosIV/libpam_kerberosIV.a .endif -.if defined(MAKE_KERBEROS5__) && !defined(NOCRYPT) && !defined(NO_OPENSSL) -STATIC_MODULES+= ${MODOBJDIR}/pam_kerberos5/libpam_kerberos5.a +.if defined(MAKE_KERBEROS5) && !defined(NOCRYPT) && !defined(NO_OPENSSL) +STATIC_MODULES+= ${MODOBJDIR}/pam_krb5/libpam_krb5.a .endif +STATIC_MODULES+= ${MODOBJDIR}/pam_nologin/libpam_nologin.a STATIC_MODULES+= ${MODOBJDIR}/pam_opie/libpam_opie.a STATIC_MODULES+= ${MODOBJDIR}/pam_permit/libpam_permit.a STATIC_MODULES+= ${MODOBJDIR}/pam_radius/libpam_radius.a +STATIC_MODULES+= ${MODOBJDIR}/pam_rootok/libpam_rootok.a STATIC_MODULES+= ${MODOBJDIR}/pam_skey/libpam_skey.a STATIC_MODULES+= ${MODOBJDIR}/pam_tacplus/libpam_tacplus.a STATIC_MODULES+= ${MODOBJDIR}/pam_unix/libpam_unix.a +STATIC_MODULES+= ${MODOBJDIR}/pam_wheel/libpam_wheel.a STATICOBJS+= pam_static_modules.o CLEANFILES+= pam_static.o diff --git a/lib/libpam/modules/Makefile b/lib/libpam/modules/Makefile index 1b3635d..f722e7c 100644 --- a/lib/libpam/modules/Makefile +++ b/lib/libpam/modules/Makefile @@ -29,14 +29,17 @@ SUBDIR+= pam_deny .if defined(MAKE_KERBEROS4) && !defined(NOCRYPT) && !defined(NO_OPENSSL) SUBDIR+= pam_kerberosIV .endif -.if defined(MAKE_KERBEROS5__) && !defined(NOCRYPT) && !defined(NO_OPENSSL) -SUBDIR+= pam_kerberos5 +.if defined(MAKE_KERBEROS5) && !defined(NOCRYPT) && !defined(NO_OPENSSL) +SUBDIR+= pam_krb5 .endif +SUBDIR+= pam_nologin SUBDIR+= pam_opie SUBDIR+= pam_permit SUBDIR+= pam_radius +SUBDIR+= pam_rootok SUBDIR+= pam_skey SUBDIR+= pam_tacplus SUBDIR+= pam_unix +SUBDIR+= pam_wheel .include <bsd.subdir.mk> diff --git a/lib/libpam/modules/pam_krb5/COPYRIGHT b/lib/libpam/modules/pam_krb5/COPYRIGHT new file mode 100644 index 0000000..42fb642 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/COPYRIGHT @@ -0,0 +1,195 @@ +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 <itoi@eecs.umich.edu>, 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 new file mode 100644 index 0000000..43f3a77 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/Makefile @@ -0,0 +1,44 @@ +# Copyright 2001 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$ + +PAMDIR= ${.CURDIR}/../../../../contrib/libpam + +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 +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +DPADD+= ${LIBKRB5} ${LIBGSSAPI} ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} \ + ${LIBCOM_ERR} +LDADD+= -lkrb5 -lgssapi -lasn1 -lroken -lcrypto -lcrypt -lcom_err \ + -L${.OBJDIR}/../../../../kerberos5/lib/libroken +INTERNALLIB= yes +INTERNALSTATICLIB=yes +MAN= pam_krb5.8 + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_krb5/README b/lib/libpam/modules/pam_krb5/README new file mode 100644 index 0000000..ee97421 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/README @@ -0,0 +1,72 @@ +$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 +<fcusack@fcusack.com> + + +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 +or 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 <itoi@eecs.umich.edu>, +Curtis King <curtis.king@cul.ca>, and Derrick Brashear <shadow@dementia.org>, +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 new file mode 100644 index 0000000..1f0939f --- /dev/null +++ b/lib/libpam/modules/pam_krb5/TODO @@ -0,0 +1,16 @@ +$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 new file mode 100644 index 0000000..fb4e102 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/compat_heimdal.c @@ -0,0 +1,141 @@ +/* + * compat_heimdal.c + * + * Heimdal compatability layer. + * + * $FreeBSD$ + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <krb5.h> +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#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); +} + +krb5_error_code +compat_cc_next_cred(krb5_context context, const krb5_ccache id, + krb5_cc_cursor *cursor, krb5_creds *creds) +{ + return krb5_cc_next_cred(context, id, creds, cursor); +} + + +static krb5_error_code +heimdal_pam_prompter(krb5_context context, void *data, 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.8 b/lib/libpam/modules/pam_krb5/pam_krb5.8 new file mode 100644 index 0000000..7ef1211 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5.8 @@ -0,0 +1,191 @@ +.\" +.\" $Id: pam_krb5.5,v 1.5 2000/01/05 00:59:56 fcusack Exp $ +.\" $FreeBSD$ +.TH pam_krb5 8 "15 Jan 1999" +.SH NAME +pam_krb5 \- Kerberos 5 PAM module +.SH SYNOPSIS +.LP +.B /usr/lib/pam_krb5.so +.LP +.SH DESCRIPTION +.IX "pam_krb5" "" "\fLpam_krb5\fP \(em Kerberos 5 PAM module" +.PP +The Kerberos 5 service module for PAM, typically +.BR /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 +.B 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 +.SM PAM +configuration file. +.SH Kerberos 5 Authentication Module +The Kerberos 5 authentication component +provides functions to verify the identity of a user. +(\f3pam_sm_authenticate(\|)\f1) +and to set user specific credentials +(\f3pam_sm_setcred(\|)\f1). +.B 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 sucessful return, it +changes the username by mapping the principal name into a local username +(calling \f3krb5_aname_to_localname()\f1). This typically just means +the realm name is stripped. +.LP +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. +.LP +When prompting for the current password, the authentication +module will use the prompt "Password for <principal>: ". +.LP +The +.B pam_sm_setcred(\|) +function stores the newly acquired credentials in a credentials cache, +and sets the environment variable +.B KRB5CCNAME +appropriately. +The credentials cache should be destroyed by the user at logout with +.BR kdestroy (1) . +.LP +The following options may be passed to the authentication module: +.TP 15 +.B debug +.BR syslog (3) +debugging information at +.SB LOG_DEBUG +level. +.TP +.B 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. +.TP +.B try_first_pass +This option is similar to the +.B use_first_pass +option, except that if the previously obtained password fails, the +user is prompted for another password. +.TP +.B forwardable +Obtain forwardable Kerberos credentials for the user. +.TP +.B 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.] +.TP +.B ccache=<name> +Use <name> as the credentials cache. <name> must be in the form +.IR type:residual . +The special tokens +.BR %u , +to designate the decimal uid of the user; +and +.BR %p , +to designate the current process id; can be used in <name>. +.SH Kerberos 5 Account Management Module +The Kerberos 5 account management component +provides a function to perform account management, +.BR pam_sm_acct_mgmt(\|) . +The function verifies that the authenticated principal is allowed +to login to the local user account by calling +.B krb5_kuserok() +(which checks the user's \&.k5login file). +.SH Kerberos 5 Password Management Module +The Kerberos 5 password management component +provides a function to change passwords +(\f3pam_sm_chauthtok(\|)\f1). The username supplied (the +user running the +.BR 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. +.LP +Unlike when +changing a unix 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 unix, root +is always prompted for the principal's old password. +.LP +The password management module uses the same heuristics as +.BR kpasswd (1) +to determine how to contact the Kerberos password server. +.LP +The following options may be passed to the password management +module: +.TP 15 +.B debug +.BR syslog (3) +debugging information at +.SB LOG_DEBUG +level. +.TP +.B 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. +.TP +.B try_first_pass +This option is similar to the +.B use_first_pass +option, except that if the previously obtained old or new passwords fail, +the user is prompted for them. +.SH Kerberos 5 Session Management Module +The Kerberos 5 session management component +provides functions to initiate +(\f3pam_sm_open_session(\|)\f1) +and terminate +(\f3pam_sm_close_session(\|)\f1) +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 +.TP "\w'.SM KRB5CCNAME\ \ 'u" +.SM KRB5CCNAME +Location of the credentials cache. +.SH FILES +.TP "\w'/tmp/krb5cc_[uid]\ \ 'u" +/tmp/krb5cc_[uid] +default credentials cache ([uid] is the decimal UID of the user). +.TP +~/\&.k5login +file containing Kerberos principals that are allowed access. +.SH SEE ALSO +.BR kdestroy (1), +.BR passwd (1), +.BR pam (8), +.BR syslog (3), +.BR pam.conf (5). +.SH NOTES +Applications should not call +.B pam_authenticate() +more than once between calls to +.B pam_start() +and +.B pam_end() +when using the Kerberos 5 PAM module. diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.h b/lib/libpam/modules/pam_krb5/pam_krb5.h new file mode 100644 index 0000000..ff02373 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5.h @@ -0,0 +1,23 @@ +/* + * 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 *); +krb5_error_code compat_cc_next_cred(krb5_context, const krb5_ccache, + krb5_cc_cursor *, krb5_creds *); + +#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 new file mode 100644 index 0000000..1a2910b --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_acct.c @@ -0,0 +1,83 @@ +/* + * 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.h> /* syslog */ +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <krb5.h> +#include <com_err.h> +#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 new file mode 100644 index 0000000..fd4270b --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_auth.c @@ -0,0 +1,505 @@ +/* + * 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 <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <limits.h> /* PATH_MAX */ +#include <pwd.h> /* getpwnam */ +#include <stdio.h> /* tmpnam */ +#include <stdlib.h> /* malloc */ +#include <strings.h> /* strchr */ +#include <syslog.h> /* syslog */ +#include <unistd.h> /* chown */ + +#include <security/pam_appl.h> +#include <security/pam_modules.h> + +#include <krb5.h> +#include <com_err.h> +#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 *source_princ = NULL; + 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; + uid_t ruid; + + 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 */ + /* This case is for use mainly by su. + If non-root is authenticating as "root", use "source_user/root". */ + if (!strcmp(name, "root") && (ruid = getuid()) != 0) { + pw = getpwuid(ruid); + if (pw != NULL) + source_princ = (char *)malloc(strlen(pw->pw_name) + 6); + if (source_princ) + sprintf(source_princ, "%s/root", pw->pw_name); + } else { + source_princ = strdup(name); + } + if (!source_princ) { + DLOG("malloc()", "failure"); + pamret = PAM_BUF_ERR; + goto cleanup2; + } + + if ((krbret = krb5_parse_name(pam_context, source_princ, &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); + } + + /* get a local account name for this principal */ + if ((krbret = krb5_aname_to_localname(pam_context, princ, + sizeof(lname), lname)) == 0) { + 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; + } + } else { + DLOG("krb5_aname_to_localname()", error_message(krbret)); + /* Not an error. */ + } + + /* Verify the local user exists (AFTER getting the password) */ + 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); + if (source_princ) + free(source_princ); + + 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 && flags != PAM_DELETE_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) { + /* User did not use krb5 to login */ + DLOG("ccache", "not found"); + pamret = PAM_SUCCESS; + 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++; + } + } + } + + if ((krbret = krb5_cc_resolve(pam_context, cache_name, &ccache_perm)) + != 0) { + DLOG("krb5_cc_resolve()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + if (flags == PAM_ESTABLISH_CRED) { + /* 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_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 = compat_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; + } + } else { + /* flag == PAM_DELETE_CRED */ + if ((krbret = krb5_cc_destroy(pam_context, ccache_perm)) != 0) { + /* log error, but otherwise ignore it */ + DLOG("krb5_cc_destroy()", error_message(krbret)); + } + goto cleanup3; + } + +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 new file mode 100644 index 0000000..994c7f4 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_pass.c @@ -0,0 +1,200 @@ +/* + * 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 <errno.h> +#include <stdio.h> /* sprintf */ +#include <stdlib.h> /* malloc */ +#include <syslog.h> /* syslog */ +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <krb5.h> +#include <com_err.h> +#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 new file mode 100644 index 0000000..b2df064 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_sess.c @@ -0,0 +1,28 @@ +/* + * 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 <security/pam_appl.h> +#include <security/pam_modules.h> + +/* 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 new file mode 100644 index 0000000..8e1aecd --- /dev/null +++ b/lib/libpam/modules/pam_krb5/support.c @@ -0,0 +1,185 @@ +/* + * 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 <errno.h> +#include <stdio.h> /* BUFSIZ */ +#include <stdlib.h> /* malloc */ +#include <string.h> /* strncpy */ +#include <syslog.h> /* syslog */ +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <krb5.h> +#include <com_err.h> +#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 <hartmans@mit.edu> 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/<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/<host> keys? + * (use default/configured keytab, kvno IGNORE_VNO to get the + * first match, and ignore enctype.) + */ + if ((retval = krb5_kt_read_service_key(context, NULL, princ, 0, + 0, &keyblock)) != 0) + continue; + break; + } + if (retval != 0 ) { /* failed to find key */ + /* Keytab or service key does not exist */ + if (debug) + syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", + "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); +} diff --git a/lib/libpam/modules/pam_nologin/Makefile b/lib/libpam/modules/pam_nologin/Makefile new file mode 100644 index 0000000..f6911b7 --- /dev/null +++ b/lib/libpam/modules/pam_nologin/Makefile @@ -0,0 +1,39 @@ +# Copyright 2001 Mark R V Murray +# 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$ + +PAMDIR= ${.CURDIR}/../../../../contrib/libpam + +.PATH: ${PAMDIR}/modules/pam_nologin + +LIB= pam_nologin +SHLIB_NAME= pam_nologin.so +SRCS= pam_nologin.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_rootok/Makefile b/lib/libpam/modules/pam_rootok/Makefile new file mode 100644 index 0000000..c04afb8 --- /dev/null +++ b/lib/libpam/modules/pam_rootok/Makefile @@ -0,0 +1,39 @@ +# Copyright 2001 Mark R V Murray +# 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$ + +PAMDIR= ${.CURDIR}/../../../../contrib/libpam + +.PATH: ${PAMDIR}/modules/pam_rootok + +LIB= pam_rootok +SHLIB_NAME= pam_rootok.so +SRCS= pam_rootok.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_wheel/Makefile b/lib/libpam/modules/pam_wheel/Makefile new file mode 100644 index 0000000..96cea74 --- /dev/null +++ b/lib/libpam/modules/pam_wheel/Makefile @@ -0,0 +1,39 @@ +# Copyright 2001 Mark R V Murray +# 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$ + +PAMDIR= ${.CURDIR}/../../../../contrib/libpam + +.PATH: ${PAMDIR}/modules/pam_wheel + +LIB= pam_wheel +SHLIB_NAME= pam_wheel.so +SRCS= pam_wheel.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> |