diff options
Diffstat (limited to 'lib/libpam/modules')
20 files changed, 2327 insertions, 0 deletions
diff --git a/lib/libpam/modules/Makefile b/lib/libpam/modules/Makefile new file mode 100644 index 0000000..8018dbd --- /dev/null +++ b/lib/libpam/modules/Makefile @@ -0,0 +1,38 @@ +# Copyright 1998 Juniper Networks, 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$ + +SUBDIR+= pam_cleartext_pass_ok +SUBDIR+= pam_deny +.if defined(MAKE_KERBEROS4) && !defined(NOCRYPT) +SUBDIR+= pam_kerberosIV +.endif +SUBDIR+= pam_permit +SUBDIR+= pam_radius +SUBDIR+= pam_skey +SUBDIR+= pam_tacplus +SUBDIR+= pam_unix + +.include <bsd.subdir.mk> diff --git a/lib/libpam/modules/pam_cleartext_pass_ok/Makefile b/lib/libpam/modules/pam_cleartext_pass_ok/Makefile new file mode 100644 index 0000000..2336ea3 --- /dev/null +++ b/lib/libpam/modules/pam_cleartext_pass_ok/Makefile @@ -0,0 +1,39 @@ +# Copyright 1998 Juniper Networks, 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_cleartext_pass_ok +SHLIB_NAME= pam_cleartext_pass_ok.so +SRCS= pam_cleartext_pass_ok.c +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -Wall +DPADD+= ${LIBSKEY} +LDADD+= -lskey -lgcc_pic +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_cleartext_pass_ok/pam_cleartext_pass_ok.c b/lib/libpam/modules/pam_cleartext_pass_ok/pam_cleartext_pass_ok.c new file mode 100644 index 0000000..437225c --- /dev/null +++ b/lib/libpam/modules/pam_cleartext_pass_ok/pam_cleartext_pass_ok.c @@ -0,0 +1,67 @@ +/*- + * Copyright 1998 Juniper Networks, 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$ + */ + +#include <stdio.h> +#include <skey.h> + +#define PAM_SM_AUTH +#include <security/pam_modules.h> + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval; + const void *item; + const char *user; + const char *tty; + const char *rhost; + + if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) + return retval; + if ((retval = pam_get_item(pamh, PAM_TTY, &item)) != PAM_SUCCESS) + return retval; + tty = (const char *)item; + if ((retval = pam_get_item(pamh, PAM_RHOST, &item)) != PAM_SUCCESS) + return retval; + rhost = (const char *)item; + /* + * The cast in the next statement is necessary only because the + * declaration of skeyaccess is wrong. + */ + return skeyaccess((char *)user, tty, rhost, NULL) ? + PAM_SUCCESS : PAM_AUTH_ERR; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_MODULE_ENTRY("pam_cleartext_pass_ok"); diff --git a/lib/libpam/modules/pam_deny/Makefile b/lib/libpam/modules/pam_deny/Makefile new file mode 100644 index 0000000..17b1447 --- /dev/null +++ b/lib/libpam/modules/pam_deny/Makefile @@ -0,0 +1,41 @@ +# Copyright 1999 Max Khon. +# 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_deny + +LIB= pam_deny +SHLIB_NAME= pam_deny.so +SRCS= pam_deny.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +DPADD+= ${LIBGCC_PIC} +LDADD+= -lgcc_pic +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_kerberosIV/Makefile b/lib/libpam/modules/pam_kerberosIV/Makefile new file mode 100644 index 0000000..ee4e6a6 --- /dev/null +++ b/lib/libpam/modules/pam_kerberosIV/Makefile @@ -0,0 +1,47 @@ +# Copyright 1998 Juniper Networks, 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_kerberosIV +SHLIB_NAME= pam_kerberosIV.so +SRCS= pam_kerberosIV.c klogin.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +CFLAGS+= -DKERBEROS +DPADD+= ${LIBKRB} +LDADD+= -lkrb +.if !defined(NOSECURE) +DPADD+= ${LIBDES} +LDADD+= -ldes +.endif +DPADD+= ${LIBGCC_PIC} ${LIBCOM_ERR} +LDADD+= -lgcc_pic -lcom_err +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_kerberosIV/klogin.c b/lib/libpam/modules/pam_kerberosIV/klogin.c new file mode 100644 index 0000000..7c61b84 --- /dev/null +++ b/lib/libpam/modules/pam_kerberosIV/klogin.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static const char sccsid[] = "@(#)klogin.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#ifdef KERBEROS +#include <sys/param.h> +#include <sys/syslog.h> +#include <des.h> +#include <krb.h> + +#include <err.h> +#include <netdb.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define INITIAL_TICKET "krbtgt" +#define VERIFY_SERVICE "rcmd" + +extern int notickets; +extern char *krbtkfile_env; + +/* + * Attempt to log the user in using Kerberos authentication + * + * return 0 on success (will be logged in) + * 1 if Kerberos failed (try local password in login) + */ +int +klogin(pw, instance, localhost, password) + struct passwd *pw; + char *instance, *localhost, *password; +{ + int kerror; + char realm[REALM_SZ], savehost[MAXHOSTNAMELEN]; + char tkt_location[MAXPATHLEN]; + char *krb_get_phost(); + extern int noticketsdontcomplain; + +#ifdef KLOGIN_PARANOID + AUTH_DAT authdata; + KTEXT_ST ticket; + struct hostent *hp; + unsigned long faddr; + + noticketsdontcomplain = 0; /* enable warning message */ +#endif + + /* + * Root logins don't use Kerberos. + * If we have a realm, try getting a ticket-granting ticket + * and using it to authenticate. Otherwise, return + * failure so that we can try the normal passwd file + * for a password. If that's ok, log the user in + * without issuing any tickets. + */ + if (strcmp(pw->pw_name, "root") == 0 || + krb_get_lrealm(realm, 0) != KSUCCESS) + return (1); + + noticketsdontcomplain = 0; /* enable warning message */ + + /* + * get TGT for local realm + * tickets are stored in a file named TKT_ROOT plus uid + * except for user.root tickets. + */ + + if (strcmp(instance, "root") != 0) + (void)sprintf(tkt_location, "%s%d", TKT_ROOT, pw->pw_uid); + else { + (void)sprintf(tkt_location, "%s_root_%d", TKT_ROOT, pw->pw_uid); + krbtkfile_env = tkt_location; + } + (void)krb_set_tkt_string(tkt_location); + + /* + * Set real as well as effective ID to 0 for the moment, + * to make the kerberos library do the right thing. + */ + if (setuid(0) < 0) { + warnx("setuid"); + return (1); + } + kerror = krb_get_pw_in_tkt(pw->pw_name, instance, + realm, INITIAL_TICKET, realm, DEFAULT_TKT_LIFE, password); + + /* + * If we got a TGT, get a local "rcmd" ticket and check it so as to + * ensure that we are not talking to a bogus Kerberos server. + * + * There are 2 cases where we still allow a login: + * 1: the VERIFY_SERVICE doesn't exist in the KDC + * 2: local host has no srvtab, as (hopefully) indicated by a + * return value of RD_AP_UNDEC from krb_rd_req(). + */ + if (kerror != INTK_OK) { + if (kerror != INTK_BADPW && kerror != KDC_PR_UNKNOWN) { + syslog(LOG_ERR, "Kerberos intkt error: %s", + krb_err_txt[kerror]); + dest_tkt(); + } + return (1); + } + + if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0) + syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE); + + (void)strncpy(savehost, krb_get_phost(localhost), sizeof(savehost)); + savehost[sizeof(savehost)-1] = NULL; + +#ifdef KLOGIN_PARANOID + /* + * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host, + * still allow login with tickets, but log the error condition. + */ + + kerror = krb_mk_req(&ticket, VERIFY_SERVICE, savehost, realm, 33); + if (kerror == KDC_PR_UNKNOWN) { + syslog(LOG_NOTICE, + "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?", + krb_err_txt[kerror], VERIFY_SERVICE, savehost); + notickets = 0; + return (0); + } + + if (kerror != KSUCCESS) { + warnx("unable to use TGT: (%s)", krb_err_txt[kerror]); + syslog(LOG_NOTICE, "unable to use TGT: (%s)", + krb_err_txt[kerror]); + dest_tkt(); + return (1); + } + + if (!(hp = gethostbyname(localhost))) { + syslog(LOG_ERR, "couldn't get local host address"); + dest_tkt(); + return (1); + } + + memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr)); + + kerror = krb_rd_req(&ticket, VERIFY_SERVICE, savehost, faddr, + &authdata, ""); + + if (kerror == KSUCCESS) { + notickets = 0; + return (0); + } + + /* undecipherable: probably didn't have a srvtab on the local host */ + if (kerror == RD_AP_UNDEC) { + syslog(LOG_NOTICE, "krb_rd_req: (%s)\n", krb_err_txt[kerror]); + dest_tkt(); + return (1); + } + /* failed for some other reason */ + warnx("unable to verify %s ticket: (%s)", VERIFY_SERVICE, + krb_err_txt[kerror]); + syslog(LOG_NOTICE, "couldn't verify %s ticket: %s", VERIFY_SERVICE, + krb_err_txt[kerror]); + dest_tkt(); + return (1); +#else + notickets = 0; + return (0); +#endif +} +#endif diff --git a/lib/libpam/modules/pam_kerberosIV/pam_kerberosIV.c b/lib/libpam/modules/pam_kerberosIV/pam_kerberosIV.c new file mode 100644 index 0000000..403f8d6 --- /dev/null +++ b/lib/libpam/modules/pam_kerberosIV/pam_kerberosIV.c @@ -0,0 +1,108 @@ +/*- + * Copyright 1998 Juniper Networks, 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$ + */ + +#include <sys/param.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define PAM_SM_AUTH +#include <security/pam_modules.h> + +#include "pam_mod_misc.h" + +#define PASSWORD_PROMPT "Password:" + +extern int klogin(struct passwd *, char *, char *, char *); + +/* Globals used by klogin.c */ +int notickets = 1; +int noticketsdontcomplain = 1; +char *krbtkfile_env; + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval; + const char *user; + char *principal; + char *instance; + const char *password; + char localhost[MAXHOSTNAMELEN + 1]; + struct passwd *pwd; + int options; + int i; + + options = 0; + for (i = 0; i < argc; i++) + pam_std_option(&options, argv[i]); + if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) + return retval; + if ((retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, + options)) != PAM_SUCCESS) + return retval; + if (gethostname(localhost, sizeof localhost - 1) == -1) + return PAM_SYSTEM_ERR; + if ((principal = strdup(user)) == NULL) + return PAM_BUF_ERR; + if ((instance = strchr(principal, '.')) != NULL) + *instance++ = '\0'; + else + instance = ""; + if ((pwd = getpwnam(user)) != NULL && + klogin(pwd, instance, localhost, (char *)password) == 0) { + if (!(flags & PAM_SILENT) && notickets && + !noticketsdontcomplain) + pam_prompt(pamh, PAM_ERROR_MSG, + "Warning: no Kerberos tickets issued", NULL); + /* + * XXX - I think the ticket file really isn't supposed to + * be even created until pam_sm_setcred() is called. + */ + if (krbtkfile_env != NULL) + setenv("KRBTKFILE", krbtkfile_env, 1); + retval = PAM_SUCCESS; + } else + retval = PAM_AUTH_ERR; + /* + * The PAM infrastructure will obliterate the cleartext + * password before returning to the application. + */ + free(principal); + return retval; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_MODULE_ENTRY("pam_kerberosIV"); diff --git a/lib/libpam/modules/pam_login_access/login.access.5 b/lib/libpam/modules/pam_login_access/login.access.5 new file mode 100644 index 0000000..10788ed --- /dev/null +++ b/lib/libpam/modules/pam_login_access/login.access.5 @@ -0,0 +1,54 @@ +.\" +.\" $FreeBSD$ +.\" +.\" this is comment +.Dd April 30, 1994 +.Dt LOGIN.ACCESS 5 +.Os FreeBSD 1.2 +.Sh NAME +.Nm login.access +.Nd login access control table +.Sh DESCRIPTION +The +.Nm +file specifies (user, host) combinations and/or (user, tty) +combinations for which a login will be either accepted or refused. +.Pp +When someone logs in, the +.Nm +is scanned for the first entry that +matches the (user, host) combination, or, in case of non-networked +logins, the first entry that matches the (user, tty) combination. The +permissions field of that table entry determines whether the login will +be accepted or refused. +.Pp +Each line of the login access control table has three fields separated by a +":" character: permission : users : origins +.Pp +The first field should be a "+" (access granted) or "-" (access denied) +character. The second field should be a list of one or more login names, +group names, or ALL (always matches). The third field should be a list +of one or more tty names (for non-networked logins), host names, domain +names (begin with "."), host addresses, internet network numbers (end +with "."), ALL (always matches) or LOCAL (matches any string that does +not contain a "." character). If you run NIS you can use @netgroupname +in host or user patterns. +.Pp +The EXCEPT operator makes it possible to write very compact rules. +.Pp +The group file is searched only when a name does not match that of the +logged-in user. Only groups are matched in which users are explicitly +listed: the program does not look at a user's primary group id value. +.Sh FILES +.Bl -tag -width /etc/login.access -compact +.It Pa /etc/login.access +The +.Nm +file resides in +.Pa /etc . +.El +.Sh SEE ALSO +.Xr login 1 , +.Xr pam 8 +.Sh AUTHORS +.An Guido van Rooij diff --git a/lib/libpam/modules/pam_login_access/login_access.c b/lib/libpam/modules/pam_login_access/login_access.c new file mode 100644 index 0000000..cfb24d2 --- /dev/null +++ b/lib/libpam/modules/pam_login_access/login_access.c @@ -0,0 +1,239 @@ + /* + * This module implements a simple but effective form of login access + * control based on login names and on host (or domain) names, internet + * addresses (or network numbers), or on terminal line names in case of + * non-networked logins. Diagnostics are reported through syslog(3). + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + +#ifdef LOGIN_ACCESS +#ifndef lint +static const char sccsid[] = "%Z% %M% %I% %E% %U%"; +#endif + +#include <stdio.h> +#include <syslog.h> +#include <ctype.h> +#include <sys/types.h> +#include <grp.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> + +#include "pathnames.h" + + /* Delimiters for fields and for lists of users, ttys or hosts. */ + +static char fs[] = ":"; /* field separator */ +static char sep[] = ", \t"; /* list-element separator */ + + /* Constants to be used in assignments only, not in comparisons... */ + +#define YES 1 +#define NO 0 + +static int list_match(); +static int user_match(); +static int from_match(); +static int string_match(); + +/* login_access - match username/group and host/tty with access control file */ + +int +login_access(user, from) +char *user; +char *from; +{ + FILE *fp; + char line[BUFSIZ]; + char *perm; /* becomes permission field */ + char *users; /* becomes list of login names */ + char *froms; /* becomes list of terminals or hosts */ + int match = NO; + int end; + int lineno = 0; /* for diagnostics */ + + /* + * Process the table one line at a time and stop at the first match. + * Blank lines and lines that begin with a '#' character are ignored. + * Non-comment lines are broken at the ':' character. All fields are + * mandatory. The first field should be a "+" or "-" character. A + * non-existing table means no access control. + */ + + if ((fp = fopen(_PATH_LOGACCESS, "r")) != NULL) { + while (!match && fgets(line, sizeof(line), fp)) { + lineno++; + if (line[end = strlen(line) - 1] != '\n') { + syslog(LOG_ERR, "%s: line %d: missing newline or line too long", + _PATH_LOGACCESS, lineno); + continue; + } + if (line[0] == '#') + continue; /* comment line */ + while (end > 0 && isspace(line[end - 1])) + end--; + line[end] = 0; /* strip trailing whitespace */ + if (line[0] == 0) /* skip blank lines */ + continue; + if (!(perm = strtok(line, fs)) + || !(users = strtok((char *) 0, fs)) + || !(froms = strtok((char *) 0, fs)) + || strtok((char *) 0, fs)) { + syslog(LOG_ERR, "%s: line %d: bad field count", _PATH_LOGACCESS, + lineno); + continue; + } + if (perm[0] != '+' && perm[0] != '-') { + syslog(LOG_ERR, "%s: line %d: bad first field", _PATH_LOGACCESS, + lineno); + continue; + } + match = (list_match(froms, from, from_match) + && list_match(users, user, user_match)); + } + (void) fclose(fp); + } else if (errno != ENOENT) { + syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS); + } + return (match == 0 || (line[0] == '+')); +} + +/* list_match - match an item against a list of tokens with exceptions */ + +static int list_match(list, item, match_fn) +char *list; +char *item; +int (*match_fn) (); +{ + char *tok; + int match = NO; + + /* + * Process tokens one at a time. We have exhausted all possible matches + * when we reach an "EXCEPT" token or the end of the list. If we do find + * a match, look for an "EXCEPT" list and recurse to determine whether + * the match is affected by any exceptions. + */ + + for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) { + if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ + break; + if ((match = (*match_fn)(tok, item)) != NULL) /* YES */ + break; + } + /* Process exceptions to matches. */ + + if (match != NO) { + while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT")) + /* VOID */ ; + if (tok == 0 || list_match((char *) 0, item, match_fn) == NO) + return (match); + } + return (NO); +} + +/* netgroup_match - match group against machine or user */ + +static int netgroup_match(group, machine, user) +gid_t group; +char *machine; +char *user; +{ +#ifdef NIS + static char *mydomain = 0; + + if (mydomain == 0) + yp_get_default_domain(&mydomain); + return (innetgr(group, machine, user, mydomain)); +#else + syslog(LOG_ERR, "NIS netgroup support not configured"); + return 0; +#endif +} + +/* user_match - match a username against one token */ + +static int user_match(tok, string) +char *tok; +char *string; +{ + struct group *group; + int i; + + /* + * If a token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the username, or if + * the token is a group that contains the username. + */ + + if (tok[0] == '@') { /* netgroup */ + return (netgroup_match(tok + 1, (char *) 0, string)); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if ((group = getgrnam(tok)) != NULL) {/* try group membership */ + for (i = 0; group->gr_mem[i]; i++) + if (strcasecmp(string, group->gr_mem[i]) == 0) + return (YES); + } + return (NO); +} + +/* from_match - match a host or tty against a list of tokens */ + +static int from_match(tok, string) +char *tok; +char *string; +{ + int tok_len; + int str_len; + + /* + * If a token has the magic value "ALL" the match always succeeds. Return + * YES if the token fully matches the string. If the token is a domain + * name, return YES if it matches the last fields of the string. If the + * token has the magic value "LOCAL", return YES if the string does not + * contain a "." character. If the token is a network number, return YES + * if it matches the head of the string. + */ + + if (tok[0] == '@') { /* netgroup */ + return (netgroup_match(tok + 1, string, (char *) 0)); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if (tok[0] == '.') { /* domain: match last fields */ + if ((str_len = strlen(string)) > (tok_len = strlen(tok)) + && strcasecmp(tok, string + str_len - tok_len) == 0) + return (YES); + } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ + if (strchr(string, '.') == 0) + return (YES); + } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */ + && strncmp(tok, string, tok_len) == 0) { + return (YES); + } + return (NO); +} + +/* string_match - match a string against one token */ + +static int string_match(tok, string) +char *tok; +char *string; +{ + + /* + * If the token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the string. + */ + + if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ + return (YES); + } else if (strcasecmp(tok, string) == 0) { /* try exact match */ + return (YES); + } + return (NO); +} +#endif /* LOGIN_ACCES */ diff --git a/lib/libpam/modules/pam_permit/Makefile b/lib/libpam/modules/pam_permit/Makefile new file mode 100644 index 0000000..8863ff5 --- /dev/null +++ b/lib/libpam/modules/pam_permit/Makefile @@ -0,0 +1,42 @@ +# Copyright 1999 Max Khon. +# 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_permit + +LIB= pam_permit +SHLIB_NAME= pam_permit.so +SRCS= pam_permit.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +DPADD+= ${LIBGCC_PIC} +LDADD+= -lgcc_pic +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_radius/Makefile b/lib/libpam/modules/pam_radius/Makefile new file mode 100644 index 0000000..48bd39a --- /dev/null +++ b/lib/libpam/modules/pam_radius/Makefile @@ -0,0 +1,42 @@ +# Copyright 1998 Juniper Networks, 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_radius +SHLIB_NAME= pam_radius.so +SRCS= pam_radius.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +DPADD+= ${LIBRADIUS} ${LIBGCC_PIC} +LDADD+= -lradius -lgcc_pic +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +MAN8= pam_radius.8 + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_radius/pam_radius.8 b/lib/libpam/modules/pam_radius/pam_radius.8 new file mode 100644 index 0000000..ffaa074 --- /dev/null +++ b/lib/libpam/modules/pam_radius/pam_radius.8 @@ -0,0 +1,128 @@ +.\" Copyright (c) 1999 +.\" Andrzej Bialecki <abial@FreeBSD.org>. All rights reserved. +.\" +.\" Copyright (c) 1992, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" All rights reserved. +.\" +.\" This code is derived from software donated to Berkeley by +.\" Jan-Simon Pendry. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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$ +.\" +.Dd August 2, 1999 +.Dt pam_radius 8 +.Os FreeBSD 3.3 +.Sh NAME +.Nm pam_radius +.Nd RADIUS authentication PAM module +.Sh SYNOPSIS +.Nm pam_radius.so +.Op Cm use_first_pass +.Op Cm try_first_pass +.Op Cm echo_pass +.Op Cm conf Ns No = Ns Ar pathname +.Op Cm template_user Ns No = Ns Ar username +.Sh DESCRIPTION +The +.Nm +module provides authentication services based +upon the RADIUS (Remote Authentication Dial In User Service) protocol +for the PAM (Pluggable Authentication Module) framework. +.Pp +The +.Nm +module accepts these optional parameters: +.Bl -tag -width Fl +.It Cm use_first_pass +causes +.Nm +to use a previously entered password instead of prompting for a new one. +If no password has been entered then authentication fails. +.It Cm try_first_pass +causes +.Nm +to use a previously entered password, if one is available. If no +password has been entered, +.Nm +prompts for one as usual. +.It Cm echo_pass +causes echoing to be left on if +.Nm +prompts for a password. +.It Cm conf Ns No = Ns Ar pathname +specifies a non-standard location for the RADIUS client configuration file +(normally located in /etc/radius.conf). +.It Cm template_user Ns No = Ns Ar username +specifies a user whose +.Xr passwd 5 +entry will be used as a template to create the session environment +if the supplied username doesn't exist in local password database. The user +will be authenticated with the supplied username and password, but his +credentials to the system will be presented as the ones for +.Ar username , +i.e., his login class, home directory, resource limits, etc. will be set to ones +defined for +.Ar username . +.Pp +If this option is omitted, and there is no username +in the system databases equal to the supplied one (as determined by call to +.Xr getpwnam 3 Ns ), +the authentication will fail. +.Sh FILES +.Bl -tag -width /etc/radius.conf -compact +.It Pa /etc/radius.conf +The standard RADIUS client configuration file for +.Nm +.El +.Sh SEE ALSO +.Xr pam 8 , +.Xr passwd 5 , +.Xr radius.conf 5 +.Sh HISTORY +The +.Nm +module first appeared in +.Fx 3.1 . +The +.Nm +manual page first appeared in +.Fx 3.3 . +.Sh AUTHORS +The +.Nm +manual page was written by +.An Andrzej Bialecki Aq abial@FreeBSD.org . +.Pp +The +.Nm +module was written by +.An John D. Polstra Aq jdp@FreeBSD.org . diff --git a/lib/libpam/modules/pam_radius/pam_radius.c b/lib/libpam/modules/pam_radius/pam_radius.c new file mode 100644 index 0000000..c04d8f2 --- /dev/null +++ b/lib/libpam/modules/pam_radius/pam_radius.c @@ -0,0 +1,300 @@ +/*- + * Copyright 1998 Juniper Networks, 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$ + */ + +#include <sys/param.h> +#include <pwd.h> +#include <radlib.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#define PAM_SM_AUTH +#include <security/pam_modules.h> + +#include "pam_mod_misc.h" + +#define MAX_CHALLENGE_MSGS 10 +#define PASSWORD_PROMPT "RADIUS password:" + +/* Option names, including the "=" sign. */ +#define OPT_CONF "conf=" +#define OPT_TMPL "template_user=" + +static int build_access_request(struct rad_handle *, const char *, + const char *, const void *, size_t); +static int do_accept(pam_handle_t *, struct rad_handle *); +static int do_challenge(pam_handle_t *, struct rad_handle *, + const char *); + +/* + * Construct an access request, but don't send it. Returns 0 on success, + * -1 on failure. + */ +static int +build_access_request(struct rad_handle *radh, const char *user, + const char *pass, const void *state, size_t state_len) +{ + char host[MAXHOSTNAMELEN]; + + if (rad_create_request(radh, RAD_ACCESS_REQUEST) == -1) { + syslog(LOG_CRIT, "rad_create_request: %s", rad_strerror(radh)); + return -1; + } + if ((user != NULL && + rad_put_string(radh, RAD_USER_NAME, user) == -1) || + (pass != NULL && + rad_put_string(radh, RAD_USER_PASSWORD, pass) == -1) || + (gethostname(host, sizeof host) != -1 && + rad_put_string(radh, RAD_NAS_IDENTIFIER, host) == -1)) { + syslog(LOG_CRIT, "rad_put_string: %s", rad_strerror(radh)); + return -1; + } + if (state != NULL && rad_put_attr(radh, RAD_STATE, state, + state_len) == -1) { + syslog(LOG_CRIT, "rad_put_attr: %s", rad_strerror(radh)); + return -1; + } + if (rad_put_int(radh, RAD_SERVICE_TYPE, RAD_AUTHENTICATE_ONLY) == -1) { + syslog(LOG_CRIT, "rad_put_int: %s", rad_strerror(radh)); + return -1; + } + return 0; +} + +static int +do_accept(pam_handle_t *pamh, struct rad_handle *radh) +{ + int attrtype; + const void *attrval; + size_t attrlen; + char *s; + + while ((attrtype = rad_get_attr(radh, &attrval, &attrlen)) > 0) { + if (attrtype == RAD_USER_NAME) { + s = rad_cvt_string(attrval, attrlen); + if (s == NULL) { + syslog(LOG_CRIT, + "rad_cvt_string: out of memory"); + return -1; + } + pam_set_item(pamh, PAM_USER, s); + free(s); + } + } + if (attrtype == -1) { + syslog(LOG_CRIT, "rad_get_attr: %s", rad_strerror(radh)); + return -1; + } + return 0; +} + +static int +do_challenge(pam_handle_t *pamh, struct rad_handle *radh, const char *user) +{ + int retval; + int attrtype; + const void *attrval; + size_t attrlen; + const void *state; + size_t statelen; + struct pam_message msgs[MAX_CHALLENGE_MSGS]; + const struct pam_message *msg_ptrs[MAX_CHALLENGE_MSGS]; + struct pam_response *resp; + int num_msgs; + const void *item; + const struct pam_conv *conv; + + state = NULL; + statelen = 0; + num_msgs = 0; + while ((attrtype = rad_get_attr(radh, &attrval, &attrlen)) > 0) { + switch (attrtype) { + + case RAD_STATE: + state = attrval; + statelen = attrlen; + break; + + case RAD_REPLY_MESSAGE: + if (num_msgs >= MAX_CHALLENGE_MSGS) { + syslog(LOG_CRIT, + "Too many RADIUS challenge messages"); + return PAM_SERVICE_ERR; + } + msgs[num_msgs].msg = rad_cvt_string(attrval, attrlen); + if (msgs[num_msgs].msg == NULL) { + syslog(LOG_CRIT, + "rad_cvt_string: out of memory"); + return PAM_SERVICE_ERR; + } + msgs[num_msgs].msg_style = PAM_TEXT_INFO; + msg_ptrs[num_msgs] = &msgs[num_msgs]; + num_msgs++; + break; + } + } + if (attrtype == -1) { + syslog(LOG_CRIT, "rad_get_attr: %s", rad_strerror(radh)); + return PAM_SERVICE_ERR; + } + if (num_msgs == 0) { + msgs[num_msgs].msg = strdup("(null RADIUS challenge): "); + if (msgs[num_msgs].msg == NULL) { + syslog(LOG_CRIT, "Out of memory"); + return PAM_SERVICE_ERR; + } + msgs[num_msgs].msg_style = PAM_TEXT_INFO; + msg_ptrs[num_msgs] = &msgs[num_msgs]; + num_msgs++; + } + msgs[num_msgs-1].msg_style = PAM_PROMPT_ECHO_ON; + if ((retval = pam_get_item(pamh, PAM_CONV, &item)) != PAM_SUCCESS) { + syslog(LOG_CRIT, "do_challenge: cannot get PAM_CONV"); + return retval; + } + conv = (const struct pam_conv *)item; + if ((retval = conv->conv(num_msgs, msg_ptrs, &resp, + conv->appdata_ptr)) != PAM_SUCCESS) + return retval; + if (build_access_request(radh, user, resp[num_msgs-1].resp, state, + statelen) == -1) + return PAM_SERVICE_ERR; + memset(resp[num_msgs-1].resp, 0, strlen(resp[num_msgs-1].resp)); + free(resp[num_msgs-1].resp); + free(resp); + while (num_msgs > 0) + free((void *)msgs[--num_msgs].msg); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + struct rad_handle *radh; + const char *user; + const char *pass; + const char *conf_file = NULL; + const char *template_user = NULL; + int options = 0; + int retval; + int i; + int e; + + for (i = 0; i < argc; i++) { + size_t len; + + pam_std_option(&options, argv[i]); + if (strncmp(argv[i], OPT_CONF, (len = strlen(OPT_CONF))) == 0) + conf_file = argv[i] + len; + else if (strncmp(argv[i], OPT_TMPL, + (len = strlen(OPT_TMPL))) == 0) + template_user = argv[i] + len; + } + if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) + return retval; + if ((retval = pam_get_pass(pamh, &pass, PASSWORD_PROMPT, + options)) != PAM_SUCCESS) + return retval; + + if ((radh = rad_open()) == NULL) { + syslog(LOG_CRIT, "rad_open failed"); + return PAM_SERVICE_ERR; + } + if (rad_config(radh, conf_file) == -1) { + syslog(LOG_ALERT, "rad_config: %s", rad_strerror(radh)); + rad_close(radh); + return PAM_SERVICE_ERR; + } + if (build_access_request(radh, user, pass, NULL, 0) == -1) { + rad_close(radh); + return PAM_SERVICE_ERR; + } + for ( ; ; ) { + switch (rad_send_request(radh)) { + + case RAD_ACCESS_ACCEPT: + e = do_accept(pamh, radh); + rad_close(radh); + if (e == -1) + return PAM_SERVICE_ERR; + if (template_user != NULL) { + const void *item; + const char *user; + + /* + * If the given user name doesn't exist in + * the local password database, change it + * to the value given in the "template_user" + * option. + */ + retval = pam_get_item(pamh, PAM_USER, &item); + if (retval != PAM_SUCCESS) + return retval; + user = (const char *)item; + if (getpwnam(user) == NULL) + pam_set_item(pamh, PAM_USER, + template_user); + } + return PAM_SUCCESS; + + case RAD_ACCESS_REJECT: + rad_close(radh); + return PAM_AUTH_ERR; + + case RAD_ACCESS_CHALLENGE: + if ((retval = do_challenge(pamh, radh, user)) != + PAM_SUCCESS) { + rad_close(radh); + return retval; + } + break; + + case -1: + syslog(LOG_CRIT, "rad_send_request: %s", + rad_strerror(radh)); + rad_close(radh); + return PAM_AUTHINFO_UNAVAIL; + + default: + syslog(LOG_CRIT, + "rad_send_request: unexpected return value"); + rad_close(radh); + return PAM_SERVICE_ERR; + } + } +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_MODULE_ENTRY("pam_radius"); diff --git a/lib/libpam/modules/pam_skey/Makefile b/lib/libpam/modules/pam_skey/Makefile new file mode 100644 index 0000000..bf6af9e --- /dev/null +++ b/lib/libpam/modules/pam_skey/Makefile @@ -0,0 +1,40 @@ +# Copyright 1998 Juniper Networks, 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_skey +SHLIB_NAME= pam_skey.so +SRCS= pam_skey.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +DPADD+= ${LIBSKEY} ${LIBGCC_PIC} +LDADD+= -lskey -lgcc_pic +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_skey/pam_skey.c b/lib/libpam/modules/pam_skey/pam_skey.c new file mode 100644 index 0000000..439591e --- /dev/null +++ b/lib/libpam/modules/pam_skey/pam_skey.c @@ -0,0 +1,108 @@ +/*- + * Copyright 1998 Juniper Networks, 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$ + */ + +#include <syslog.h> /* XXX */ + +#include <stdio.h> +#include <string.h> +#include <skey.h> + +#define PAM_SM_AUTH +#include <security/pam_modules.h> + +#include "pam_mod_misc.h" + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval; + const char *user; + const char *response; + struct skey skey; + char challenge[128]; + char prompt[128]; + char resp_buf[128]; + int options; + int i; + int e; + + options = 0; + for (i = 0; i < argc; i++) + pam_std_option(&options, argv[i]); + /* + * It doesn't make sense to use a password that has already been + * typed in, since we haven't presented the challenge to the user + * yet. + */ + options &= ~(PAM_OPT_USE_FIRST_PASS | PAM_OPT_TRY_FIRST_PASS); + if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) + return retval; + if (skeyinfo(&skey, user, challenge) != 0) + return PAM_AUTH_ERR; + snprintf(prompt, sizeof prompt, "%s\nPassword: ", challenge); + if ((retval = pam_get_pass(pamh, &response, prompt, options)) != + PAM_SUCCESS) + return retval; + if (response[0] == '\0' && !(options & PAM_OPT_ECHO_PASS)) { + options |= PAM_OPT_ECHO_PASS; + snprintf(prompt, sizeof prompt, + "%s\nPassword [echo on]: ", challenge); + if ((retval = pam_get_pass(pamh, &response, prompt, + options)) != PAM_SUCCESS) + return retval; + } + /* + * Skeyinfo closed the database file, so we have to call skeylookup + * to open it again. + */ + if ((e = skeylookup(&skey, user)) != 0) { + if (e == -1) { + syslog(LOG_ERR, "Error opening S/Key database"); + return PAM_SERVICE_ERR; + } else + return PAM_AUTH_ERR; + } + /* We have to copy the response, because skeyverify mucks with it. */ + snprintf(resp_buf, sizeof resp_buf, "%s", response); + /* + * Skeyverify is supposed to return -1 only if an error occurs. + * But it returns -1 even if the response string isn't in the form + * it expects. Thus we can't log an error and can only check for + * success or lack thereof. + */ + return skeyverify(&skey, resp_buf) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_MODULE_ENTRY("pam_skey"); diff --git a/lib/libpam/modules/pam_ssh/pam_ssh.c b/lib/libpam/modules/pam_ssh/pam_ssh.c new file mode 100644 index 0000000..8e22d3f --- /dev/null +++ b/lib/libpam/modules/pam_ssh/pam_ssh.c @@ -0,0 +1,328 @@ +/*- + * Copyright (c) 1999 Andrew J. Korty + * 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$ + * + */ + + +#include <sys/param.h> + +#include <fcntl.h> +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define PAM_SM_AUTH +#define PAM_SM_SESSION +#include <security/pam_modules.h> +#include <security/pam_mod_misc.h> + +#include "includes.h" +#include "rsa.h" +#include "ssh.h" +#include "authfd.h" + +#define MODULE_NAME "pam_ssh" +#define NEED_PASSPHRASE "Need passphrase for %s (%s).\nEnter passphrase: " +#define PATH_SSH_AGENT "__PREFIX__/bin/ssh-agent" + + +void +rsa_cleanup(pam_handle_t *pamh, void *data, int error_status) +{ + if (data) + RSA_free(data); +} + + +void +ssh_cleanup(pam_handle_t *pamh, void *data, int error_status) +{ + if (data) + free(data); +} + + +typedef struct passwd PASSWD; + +PAM_EXTERN int +pam_sm_authenticate( + pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + char *comment_priv; /* on private key */ + char *comment_pub; /* on public key */ + char *identity; /* user's identity file */ + RSA *key; /* user's private key */ + int options; /* module options */ + const char *pass; /* passphrase */ + char *prompt; /* passphrase prompt */ + RSA *public_key; /* user's public key */ + const PASSWD *pwent; /* user's passwd entry */ + PASSWD *pwent_keep; /* our own copy */ + int retval; /* from calls */ + uid_t saved_uid; /* caller's uid */ + const char *user; /* username */ + + options = 0; + while (argc--) + pam_std_option(&options, *argv++); + if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) + return retval; + if (!((pwent = getpwnam(user)) && pwent->pw_dir)) { + /* delay? */ + return PAM_AUTH_ERR; + } + /* locate the user's private key file */ + if (!asprintf(&identity, "%s/%s", pwent->pw_dir, + SSH_CLIENT_IDENTITY)) { + syslog(LOG_CRIT, "%s: %m", MODULE_NAME); + return PAM_SERVICE_ERR; + } + /* + * Fail unless we can load the public key. Change to the + * owner's UID to appease load_public_key(). + */ + key = RSA_new(); + public_key = RSA_new(); + saved_uid = getuid(); + (void)setreuid(pwent->pw_uid, saved_uid); + retval = load_public_key(identity, public_key, &comment_pub); + (void)setuid(saved_uid); + if (!retval) { + free(identity); + return PAM_AUTH_ERR; + } + RSA_free(public_key); + /* build the passphrase prompt */ + retval = asprintf(&prompt, NEED_PASSPHRASE, identity, comment_pub); + free(comment_pub); + if (!retval) { + syslog(LOG_CRIT, "%s: %m", MODULE_NAME); + free(identity); + return PAM_SERVICE_ERR; + } + /* pass prompt message to application and receive passphrase */ + retval = pam_get_pass(pamh, &pass, prompt, options); + free(prompt); + if (retval != PAM_SUCCESS) { + free(identity); + return retval; + } + /* + * Try to decrypt the private key with the passphrase provided. + * If success, the user is authenticated. + */ + (void)setreuid(pwent->pw_uid, saved_uid); + retval = load_private_key(identity, pass, key, &comment_priv); + free(identity); + (void)setuid(saved_uid); + if (!retval) + return PAM_AUTH_ERR; + /* + * Save the key and comment to pass to ssh-agent in the session + * phase. + */ + if ((retval = pam_set_data(pamh, "ssh_private_key", key, + rsa_cleanup)) != PAM_SUCCESS) { + RSA_free(key); + free(comment_priv); + return retval; + } + if ((retval = pam_set_data(pamh, "ssh_key_comment", comment_priv, + ssh_cleanup)) != PAM_SUCCESS) { + free(comment_priv); + return retval; + } + /* + * Copy the passwd entry (in case successive calls are made) + * and save it for the session phase. + */ + if (!(pwent_keep = malloc(sizeof *pwent))) { + syslog(LOG_CRIT, "%m"); + return PAM_SERVICE_ERR; + } + (void)memcpy(pwent_keep, pwent, sizeof *pwent_keep); + if ((retval = pam_set_data(pamh, "ssh_passwd_entry", pwent_keep, + ssh_cleanup)) != PAM_SUCCESS) { + free(pwent_keep); + return retval; + } + return PAM_SUCCESS; +} + + +PAM_EXTERN int +pam_sm_setcred( + pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + + +typedef AuthenticationConnection AC; + +PAM_EXTERN int +pam_sm_open_session( + pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + AC *ac; /* to ssh-agent */ + char *comment; /* on private key */ + char *env_end; /* end of env */ + char *env_file; /* to store env */ + FILE *env_fp; /* env_file handle */ + RSA *key; /* user's private key */ + FILE *pipe; /* ssh-agent handle */ + const PASSWD *pwent; /* user's passwd entry */ + int retval; /* from calls */ + uid_t saved_uid; /* caller's uid */ + const char *tty; /* tty or display name */ + char hname[MAXHOSTNAMELEN]; /* local hostname */ + char parse[BUFSIZ]; /* commands output */ + + /* dump output of ssh-agent in ~/.ssh */ + if ((retval = pam_get_data(pamh, "ssh_passwd_entry", + (const void **)&pwent)) != PAM_SUCCESS) + return retval; + /* use the tty or X display name in the filename */ + if ((retval = pam_get_item(pamh, PAM_TTY, (const void **)&tty)) + != PAM_SUCCESS) + return retval; + if (*tty == ':' && gethostname(hname, sizeof hname) == 0) { + if (asprintf(&env_file, "%s/.ssh/agent-%s%s", + pwent->pw_dir, hname, tty) == -1) { + syslog(LOG_CRIT, "%s: %m", MODULE_NAME); + return PAM_SERVICE_ERR; + } + } else if (asprintf(&env_file, "%s/.ssh/agent-%s", pwent->pw_dir, + tty) == -1) { + syslog(LOG_CRIT, "%s: %m", MODULE_NAME); + return PAM_SERVICE_ERR; + } + /* save the filename so we can delete the file on session close */ + if ((retval = pam_set_data(pamh, "ssh_agent_env", env_file, + ssh_cleanup)) != PAM_SUCCESS) { + free(env_file); + return retval; + } + /* start the agent as the user */ + saved_uid = geteuid(); + (void)seteuid(pwent->pw_uid); + env_fp = fopen(env_file, "w"); + pipe = popen(PATH_SSH_AGENT, "r"); + (void)seteuid(saved_uid); + if (!pipe) { + syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, PATH_SSH_AGENT); + if (env_fp) + (void)fclose(env_fp); + return PAM_SESSION_ERR; + } + while (fgets(parse, sizeof parse, pipe)) { + if (env_fp) + (void)fputs(parse, env_fp); + /* + * Save environment for application with pam_putenv() + * but also with putenv() for our own call to + * ssh_get_authentication_connection(). + */ + if (strchr(parse, '=') && (env_end = strchr(parse, ';'))) { + *env_end = '\0'; + /* pass to the application ... */ + if (!((retval = pam_putenv(pamh, parse)) == + PAM_SUCCESS && putenv(parse) == 0)) { + (void)pclose(pipe); + if (env_fp) + (void)fclose(env_fp); + return PAM_SERVICE_ERR; + } + } + } + if (env_fp) + (void)fclose(env_fp); + retval = pclose(pipe); + if (retval > 0) { + syslog(LOG_ERR, "%s: %s exited with status %d", + MODULE_NAME, PATH_SSH_AGENT, WEXITSTATUS(retval)); + return PAM_SESSION_ERR; + } else if (retval < 0) { + syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, PATH_SSH_AGENT); + return PAM_SESSION_ERR; + } + /* connect to the agent and hand off the private key */ + if ((retval = pam_get_data(pamh, "ssh_private_key", + (const void **)&key)) != PAM_SUCCESS) + return retval; + if ((retval = pam_get_data(pamh, "ssh_key_comment", + (const void **)&comment)) != PAM_SUCCESS) + return retval; + if (!(ac = ssh_get_authentication_connection())) { + syslog(LOG_ERR, "%s: could not connect to agent", + MODULE_NAME); + return PAM_SESSION_ERR; + } + retval = ssh_add_identity(ac, key, comment); + ssh_close_authentication_connection(ac); + return retval ? PAM_SUCCESS : PAM_SESSION_ERR; +} + + +PAM_EXTERN int +pam_sm_close_session( + pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + const char *env_file; /* ssh-agent environment */ + int retval; /* from calls */ + + /* kill the agent */ + if ((retval = system(PATH_SSH_AGENT " -k")) != 0) { + syslog(LOG_ERR, "%s: %s -k exited with status %d", + MODULE_NAME, PATH_SSH_AGENT, WEXITSTATUS(retval)); + return PAM_SESSION_ERR; + } + /* retrieve environment filename, then remove the file */ + if ((retval = pam_get_data(pamh, "ssh_agent_env", + (const void **)&env_file)) != PAM_SUCCESS) + return retval; + (void)unlink(env_file); + return PAM_SUCCESS; +} + + +PAM_MODULE_ENTRY(MODULE_NAME); diff --git a/lib/libpam/modules/pam_tacplus/Makefile b/lib/libpam/modules/pam_tacplus/Makefile new file mode 100644 index 0000000..6430ca8 --- /dev/null +++ b/lib/libpam/modules/pam_tacplus/Makefile @@ -0,0 +1,40 @@ +# Copyright 1998 Juniper Networks, 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_tacplus +SHLIB_NAME= pam_tacplus.so +SRCS= pam_tacplus.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +DPADD+= ${LIBTACPLUS} ${LIBGCC_PIC} +LDADD+= -ltacplus -lgcc_pic +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_tacplus/pam_tacplus.c b/lib/libpam/modules/pam_tacplus/pam_tacplus.c new file mode 100644 index 0000000..0820071 --- /dev/null +++ b/lib/libpam/modules/pam_tacplus/pam_tacplus.c @@ -0,0 +1,258 @@ +/*- + * Copyright 1998 Juniper Networks, 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$ + */ + +#include <sys/param.h> + +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <taclib.h> +#include <unistd.h> + +#define PAM_SM_AUTH +#include <security/pam_modules.h> + +#include "pam_mod_misc.h" + +/* Option names, including the "=" sign. */ +#define OPT_CONF "conf=" +#define OPT_TMPL "template_user=" + +typedef int (*set_func)(struct tac_handle *, const char *); + +static int do_item(pam_handle_t *, struct tac_handle *, int, + set_func, const char *); +static char *get_msg(struct tac_handle *); +static int set_msg(struct tac_handle *, const char *); + +static int +do_item(pam_handle_t *pamh, struct tac_handle *tach, int item, + set_func func, const char *funcname) +{ + int retval; + const void *value; + + if ((retval = pam_get_item(pamh, item, &value)) != PAM_SUCCESS) + return retval; + if (value != NULL && (*func)(tach, (const char *)value) == -1) { + syslog(LOG_CRIT, "%s: %s", funcname, tac_strerror(tach)); + tac_close(tach); + return PAM_SERVICE_ERR; + } + return PAM_SUCCESS; +} + +static char * +get_msg(struct tac_handle *tach) +{ + char *msg; + + if ((msg = tac_get_msg(tach)) == NULL) { + syslog(LOG_CRIT, "tac_get_msg: %s", tac_strerror(tach)); + tac_close(tach); + return NULL; + } + return msg; +} + +static int +set_msg(struct tac_handle *tach, const char *msg) +{ + if (tac_set_msg(tach, msg) == -1) { + syslog(LOG_CRIT, "tac_set_msg: %s", tac_strerror(tach)); + tac_close(tach); + return -1; + } + return 0; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval; + struct tac_handle *tach; + const char *conf_file = NULL; + const char *template_user = NULL; + int options = 0; + int i; + + for (i = 0; i < argc; i++) { + size_t len; + + pam_std_option(&options, argv[i]); + if (strncmp(argv[i], OPT_CONF, (len = strlen(OPT_CONF))) == 0) + conf_file = argv[i] + len; + else if (strncmp(argv[i], OPT_TMPL, + (len = strlen(OPT_TMPL))) == 0) + template_user = argv[i] + len; + } + + if ((tach = tac_open()) == NULL) { + syslog(LOG_CRIT, "tac_open failed"); + return PAM_SERVICE_ERR; + } + if (tac_config(tach, conf_file) == -1) { + syslog(LOG_ALERT, "tac_config: %s", tac_strerror(tach)); + tac_close(tach); + return PAM_SERVICE_ERR; + } + if (tac_create_authen(tach, TAC_AUTHEN_LOGIN, TAC_AUTHEN_TYPE_ASCII, + TAC_AUTHEN_SVC_LOGIN) == -1) { + syslog(LOG_CRIT, "tac_create_authen: %s", tac_strerror(tach)); + tac_close(tach); + return PAM_SERVICE_ERR; + } + if ((retval = do_item(pamh, tach, PAM_USER, + tac_set_user, "tac_set_user")) != PAM_SUCCESS) + return retval; + if ((retval = do_item(pamh, tach, PAM_TTY, + tac_set_port, "tac_set_port")) != PAM_SUCCESS) + return retval; + if ((retval = do_item(pamh, tach, PAM_RHOST, + tac_set_rem_addr, "tac_set_rem_addr")) != PAM_SUCCESS) + return retval; + for ( ; ; ) { + char *srvr_msg; + size_t msg_len; + const char *user_msg; + char *data_msg; + int sflags; + int status; + int echo; + + if ((sflags = tac_send_authen(tach)) == -1) { + syslog(LOG_CRIT, "tac_send_authen: %s", + tac_strerror(tach)); + tac_close(tach); + return PAM_AUTHINFO_UNAVAIL; + } + status = TAC_AUTHEN_STATUS(sflags); + echo = TAC_AUTHEN_NOECHO(sflags) ? 0 : PAM_OPT_ECHO_PASS; + switch (status) { + + case TAC_AUTHEN_STATUS_PASS: + tac_close(tach); + if (template_user != NULL) { + const void *item; + const char *user; + + /* + * If the given user name doesn't exist in + * the local password database, change it + * to the value given in the "template_user" + * option. + */ + retval = pam_get_item(pamh, PAM_USER, &item); + if (retval != PAM_SUCCESS) + return retval; + user = (const char *)item; + if (getpwnam(user) == NULL) + pam_set_item(pamh, PAM_USER, + template_user); + } + return PAM_SUCCESS; + + case TAC_AUTHEN_STATUS_FAIL: + tac_close(tach); + return PAM_AUTH_ERR; + + case TAC_AUTHEN_STATUS_GETUSER: + case TAC_AUTHEN_STATUS_GETPASS: + if ((srvr_msg = get_msg(tach)) == NULL) + return PAM_SERVICE_ERR; + if (status == TAC_AUTHEN_STATUS_GETUSER) + retval = pam_get_user(pamh, &user_msg, + srvr_msg[0] != '\0' ? srvr_msg : NULL); + else if (status == TAC_AUTHEN_STATUS_GETPASS) + retval = pam_get_pass(pamh, &user_msg, + srvr_msg[0] != '\0' ? srvr_msg : + "Password:", options | echo); + free(srvr_msg); + if (retval != PAM_SUCCESS) { + /* XXX - send a TACACS+ abort packet */ + tac_close(tach); + return retval; + } + if (set_msg(tach, user_msg) == -1) + return PAM_SERVICE_ERR; + break; + + case TAC_AUTHEN_STATUS_GETDATA: + if ((srvr_msg = get_msg(tach)) == NULL) + return PAM_SERVICE_ERR; + retval = pam_prompt(pamh, + (options|echo) & PAM_OPT_ECHO_PASS ? + PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF, + srvr_msg[0] != '\0' ? srvr_msg : "Data:", + &data_msg); + free(srvr_msg); + if (retval != PAM_SUCCESS) { + /* XXX - send a TACACS+ abort packet */ + tac_close(tach); + return retval; + } + retval = set_msg(tach, data_msg); + memset(data_msg, 0, strlen(data_msg)); + free(data_msg); + if (retval == -1) + return PAM_SERVICE_ERR; + break; + + case TAC_AUTHEN_STATUS_ERROR: + srvr_msg = (char *)tac_get_data(tach, &msg_len); + if (srvr_msg != NULL && msg_len != 0) { + syslog(LOG_CRIT, "tac_send_authen:" + " server detected error: %s", srvr_msg); + free(srvr_msg); + } else + syslog(LOG_CRIT, + "tac_send_authen: server detected error"); + tac_close(tach); + return PAM_AUTHINFO_UNAVAIL; + break; + + case TAC_AUTHEN_STATUS_RESTART: + case TAC_AUTHEN_STATUS_FOLLOW: + default: + syslog(LOG_CRIT, + "tac_send_authen: unexpected status %#x", status); + tac_close(tach); + return PAM_AUTHINFO_UNAVAIL; + } + } +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_MODULE_ENTRY("pam_tacplus"); diff --git a/lib/libpam/modules/pam_unix/Makefile b/lib/libpam/modules/pam_unix/Makefile new file mode 100644 index 0000000..7ef7ce3 --- /dev/null +++ b/lib/libpam/modules/pam_unix/Makefile @@ -0,0 +1,40 @@ +# Copyright 1998 Juniper Networks, 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_unix +SHLIB_NAME= pam_unix.so +SRCS= pam_unix.c +CFLAGS+= -Wall +CFLAGS+= -I${PAMDIR}/libpam/include +CFLAGS+= -I${.CURDIR}/../../libpam +DPADD+= ${LIBUTIL} ${LIBGCC_PIC} ${LIBCRYPT} +LDADD+= -lutil -lgcc_pic -lcrypt +INTERNALLIB= yes +INTERNALSTATICLIB=yes + +.include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_unix/pam_unix.c b/lib/libpam/modules/pam_unix/pam_unix.c new file mode 100644 index 0000000..329b784 --- /dev/null +++ b/lib/libpam/modules/pam_unix/pam_unix.c @@ -0,0 +1,164 @@ +/*- + * Copyright 1998 Juniper Networks, 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$ + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <login_cap.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#include <security/pam_modules.h> + +#include "pam_mod_misc.h" + +#define PASSWORD_PROMPT "Password:" + +/* + * authentication management + */ + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval; + const char *user; + const char *password; + struct passwd *pwd; + char *encrypted; + int options; + int i; + + options = 0; + for (i = 0; i < argc; i++) + pam_std_option(&options, argv[i]); + if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) + return retval; + if ((retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, + options)) != PAM_SUCCESS) + return retval; + if ((pwd = getpwnam(user)) != NULL) { + encrypted = crypt(password, pwd->pw_passwd); + if (password[0] == '\0' && pwd->pw_passwd[0] != '\0') + encrypted = ":"; + + retval = strcmp(encrypted, pwd->pw_passwd) == 0 ? + PAM_SUCCESS : PAM_AUTH_ERR; + } else { + /* + * User unknown. Encrypt anyway so that it takes the + * same amount of time. + */ + crypt(password, "xx"); + retval = PAM_AUTH_ERR; + } + /* + * The PAM infrastructure will obliterate the cleartext + * password before returning to the application. + */ + return retval; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +/* + * account management + * + * check pw_change and pw_expire fields + */ +PAM_EXTERN +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *user; + struct passwd *pw; + struct timeval tp; + time_t warntime; + login_cap_t *lc = NULL; + char buf[128]; + int retval; + + retval = pam_get_item(pamh, PAM_USER, (const void **)&user); + if (retval != PAM_SUCCESS || user == NULL) + /* some implementations return PAM_SUCCESS here */ + return PAM_USER_UNKNOWN; + + if ((pw = getpwnam(user)) == NULL) + return PAM_USER_UNKNOWN; + + retval = PAM_SUCCESS; + lc = login_getpwclass(pw); + + if (pw->pw_change || pw->pw_expire) + gettimeofday(&tp, NULL); + +#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ + + warntime = login_getcaptime(lc, "warnpassword", DEFAULT_WARN, + DEFAULT_WARN); + + if (pw->pw_change) { + if (tp.tv_sec >= pw->pw_change) + /* some implementations return PAM_AUTHTOK_EXPIRED */ + retval = PAM_NEW_AUTHTOK_REQD; + else if (pw->pw_change - tp.tv_sec < warntime) { + snprintf(buf, sizeof(buf), + "Warning: your password expires on %s", + ctime(&pw->pw_change)); + pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL); + } + } + + warntime = login_getcaptime(lc, "warnexpire", DEFAULT_WARN, + DEFAULT_WARN); + + if (pw->pw_expire) { + if (tp.tv_sec >= pw->pw_expire) + retval = PAM_ACCT_EXPIRED; + else if (pw->pw_expire - tp.tv_sec < warntime) { + snprintf(buf, sizeof(buf), + "Warning: your account expires on %s", + ctime(&pw->pw_expire)); + pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL); + } + } + + login_close(lc); + return retval; +} + +PAM_MODULE_ENTRY("pam_unix"); |