Bring back from the er, dead some useful PAM modules.

This commit is contained in:
Mark Murray 2001-05-29 18:32:17 +00:00
parent 83f1488d6e
commit 13b65deafa
15 changed files with 1748 additions and 0 deletions

View File

@ -0,0 +1,16 @@
#
# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $
# $FreeBSD$
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
# what you are doing!).
#
# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27
#
include ../../Make.Rules
TITLE=pam_ftp
include ../Simple.Rules

View File

@ -0,0 +1,19 @@
$FreeBSD$
This is the README for pam_ftp
------------------------------
This module is an authentication module that does simple ftp
authentication.
Recognized arguments:
"debug" print debug messages
"users=" comma separated list of users which
could login only with email adress
"ignore" allow invalid email adresses
Options for:
auth: for authentication it provides pam_authenticate() and
pam_setcred() hooks.
Thorsten Kukuk <kukuk@suse.de>, 17. June 1999

View File

@ -0,0 +1,298 @@
/* pam_ftp module */
/*
* $Id: pam_ftp.c,v 1.2 2000/11/19 23:54:03 agmorgan Exp $
* $FreeBSD$
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
*
*/
#define PLEASE_ENTER_PASSWORD "Password required for %s."
#define GUEST_LOGIN_PROMPT "Guest login ok, " \
"send your complete e-mail address as password."
/* the following is a password that "can't be correct" */
#define BLOCK_PASSWORD "\177BAD PASSWPRD\177"
#include <security/_pam_aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <stdarg.h>
#include <string.h>
/*
* here, we make a definition for the externally accessible function
* in this file (this definition is required for static a module
* but strongly encouraged generally) it is used to instruct the
* modules include file to define the function prototypes.
*/
#define PAM_SM_AUTH
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
/* some syslogging */
static void _pam_log(int err, const char *format, ...)
{
va_list args;
va_start(args, format);
openlog("PAM-ftp", LOG_CONS|LOG_PID, LOG_AUTH);
vsyslog(err, format, args);
va_end(args);
closelog();
}
static int converse(pam_handle_t *pamh, int nargs
, struct pam_message **message
, struct pam_response **response)
{
int retval;
struct pam_conv *conv;
D(("begin to converse\n"));
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
if ( retval == PAM_SUCCESS ) {
retval = conv->conv(nargs, ( const struct pam_message ** ) message
, response, conv->appdata_ptr);
D(("returned from application's conversation function\n"));
if ((retval != PAM_SUCCESS) && (retval != PAM_CONV_AGAIN)) {
_pam_log(LOG_DEBUG, "conversation failure [%s]"
, pam_strerror(pamh, retval));
}
} else {
_pam_log(LOG_ERR, "couldn't obtain coversation function [%s]"
, pam_strerror(pamh, retval));
}
D(("ready to return from module conversation\n"));
return retval; /* propagate error status */
}
/* argument parsing */
#define PAM_DEBUG_ARG 01
#define PAM_IGNORE_EMAIL 02
#define PAM_NO_ANON 04
static int _pam_parse(int argc, const char **argv, char **users)
{
int ctrl=0;
/* step through arguments */
for (ctrl=0; argc-- > 0; ++argv) {
/* generic options */
if (!strcmp(*argv,"debug"))
ctrl |= PAM_DEBUG_ARG;
else if (!strncmp(*argv,"users=",6)) {
*users = x_strdup(6+*argv);
if (*users == NULL) {
ctrl |= PAM_NO_ANON;
_pam_log(LOG_CRIT, "failed to duplicate user list - anon off");
}
} else if (!strcmp(*argv,"ignore")) {
ctrl |= PAM_IGNORE_EMAIL;
} else {
_pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
}
}
return ctrl;
}
/*
* check if name is in list or default list. place users name in *_user
* return 1 if listed 0 if not.
*/
static int lookup(const char *name, char *list, const char **_user)
{
int anon = 0;
*_user = name; /* this is the default */
if (list) {
const char *l;
char *x;
x = list;
while ((l = strtok(x, ","))) {
x = NULL;
if (!strcmp(name, l)) {
*_user = list;
anon = 1;
}
}
} else {
#define MAX_L 2
static const char *l[MAX_L] = { "ftp", "anonymous" };
int i;
for (i=0; i<MAX_L; ++i) {
if (!strcmp(l[i], name)) {
*_user = l[0];
anon = 1;
break;
}
}
}
return anon;
}
/* --- authentication management functions (only) --- */
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
int retval, anon=0, ctrl;
const char *user;
char *users=NULL;
/*
* this module checks if the user name is ftp or annonymous. If
* this is the case, it can set the PAM_RUSER to the entered email
* address and SUCCEEDS, otherwise it FAILS.
*/
ctrl = _pam_parse(argc, argv, &users);
retval = pam_get_user(pamh, &user, NULL);
if (retval != PAM_SUCCESS || user == NULL) {
_pam_log(LOG_ERR, "no user specified");
return PAM_USER_UNKNOWN;
}
if (!(ctrl & PAM_NO_ANON)) {
anon = lookup(user, users, &user);
}
if (anon) {
retval = pam_set_item(pamh, PAM_USER, (const void *)user);
if (retval != PAM_SUCCESS || user == NULL) {
_pam_log(LOG_ERR, "user resetting failed");
return PAM_USER_UNKNOWN;
}
}
/*
* OK. we require an email address for user or the user's password.
* - build conversation and get their input.
*/
{
struct pam_message msg[1], *mesg[1];
struct pam_response *resp=NULL;
const char *token;
char *prompt=NULL;
int i=0;
if (!anon) {
prompt = malloc(strlen(PLEASE_ENTER_PASSWORD) + strlen(user));
if (prompt == NULL) {
D(("out of memory!?"));
return PAM_BUF_ERR;
} else {
sprintf(prompt, PLEASE_ENTER_PASSWORD, user);
msg[i].msg = prompt;
}
} else {
msg[i].msg = GUEST_LOGIN_PROMPT;
}
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
mesg[i] = &msg[i];
retval = converse(pamh, ++i, mesg, &resp);
if (prompt) {
_pam_overwrite(prompt);
_pam_drop(prompt);
}
if (retval != PAM_SUCCESS) {
if (resp != NULL)
_pam_drop_reply(resp,i);
return ((retval == PAM_CONV_AGAIN)
? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
}
if (anon) {
/* XXX: Some effort should be made to verify this email address! */
if (!(ctrl & PAM_IGNORE_EMAIL)) {
token = strtok(resp->resp, "@");
retval = pam_set_item(pamh, PAM_RUSER, token);
if ((token) && (retval == PAM_SUCCESS)) {
token = strtok(NULL, "@");
retval = pam_set_item(pamh, PAM_RHOST, token);
}
}
/* we are happy to grant annonymous access to the user */
retval = PAM_SUCCESS;
} else {
/*
* we have a password so set AUTHTOK
*/
(void) pam_set_item(pamh, PAM_AUTHTOK, resp->resp);
/*
* this module failed, but the next one might succeed with
* this password.
*/
retval = PAM_AUTH_ERR;
}
if (resp) { /* clean up */
_pam_drop_reply(resp, i);
}
/* success or failure */
return retval;
}
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
return PAM_IGNORE;
}
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_ftp_modstruct = {
"pam_ftp",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif
/* end of module definition */

View File

@ -0,0 +1,16 @@
#
# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
# $FreeBSD$
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
# what you are doing!).
#
# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27
#
include ../../Make.Rules
TITLE=pam_rhosts_auth
include ../Simple.Rules

View File

@ -0,0 +1,58 @@
$FreeBSD$
arguments recognized:
"no_hosts_equiv"
"no_rhosts"
"debug"
"nowarn"
"suppress"
"promiscuous"
.rhosts/hosts.equiv format:
There are positive entries, when one is matched authentication
succeeds and terminates. There are negative entries, when one is
matched authentication fails and terminates. Thus order is
significant.
Entry hosts.equiv .rhosts
<host> All users on <host> are ok Same username from <host> is ok
<host> <user> <user> from <host> is ok ditto
-<host> No users from <host> are ok ditto
<host> -<user> <user> from <host> is not ok ditto
<host> can be ip (IPv4) numbers.
Netgroups may be used in either host or user fields, and then applies
to all hosts, or users, in the netgroup. The syntax is
+@<ng>
The entries
<host> +@<ng>
+@<ng> +@<ng>
+@<ng> <user>
means exactly what you think it does. Negative entries are of the
form
-@<ng>
When the "promiscuous" option is given the special character + may be
used as a wildcard in any field.
+ Allow anyone from any host to connect. DANGEROUS.
+ + Ditto.
+ <user> Allow the user to connect from anywhere. DANGEROUS.
<host> + Allow any user from the host. Dangerous.
These, perhaps more usefull, forms of the + form is also disallowed
unless "promiscuous" is specified:
+ -<user> Disallow the user from any host
+ -@<ng> Disallow all members of the netgroup from any host
When "promiscuous" is not specified a '+' is handled as a negative
match.

View File

@ -0,0 +1,787 @@
/*----------------------------------------------------------------------
* Modified for Linux-PAM by Al Longyear <longyear@netcom.com> 96/5/5
* Modifications, Cristian Gafton 97/2/8
* Modifications, Peter Allgeyer 97/3
* Modifications (netgroups and fixes), Nicolai Langfeldt 97/3/21
* Security fix: 97/10/2 - gethostbyname called repeatedly without care
* Modification (added privategroup option) Andrew <morgan@transmeta.com>
*----------------------------------------------------------------------
* Copyright (c) 1983, 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.
* $FreeBSD$
*/
#define _BSD_SOURCE
#define USER_RHOSTS_FILE "/.rhosts" /* prefixed by user's home dir */
#ifdef linux
#include <endian.h>
#endif
#ifdef NEED_FSUID_H
#include <sys/fsuid.h>
#endif /* NEED_FSUID_H */
#include <sys/types.h>
#include <sys/uio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* This is supposed(?) to contain the following */
int innetgr(const char *, const char *, const char *,const char *);
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <arpa/inet.h>
#ifndef MAXDNAME
#define MAXDNAME 256
#endif
#include <stdarg.h>
#include <ctype.h>
#include <net/if.h>
#ifdef linux
# include <linux/sockios.h>
# ifndef __USE_MISC
# define __USE_MISC
# include <sys/fsuid.h>
# endif /* __USE_MISC */
#endif
#include <pwd.h>
#include <grp.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <syslog.h>
#ifndef _PATH_HEQUIV
#define _PATH_HEQUIV "/etc/hosts.equiv"
#endif /* _PATH_HEQUIV */
#define PAM_SM_AUTH /* only defines this management group */
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
/* to the best of my knowledge, all modern UNIX boxes have 32 bit integers */
#define U32 unsigned int
/*
* Options for this module
*/
struct _options {
int opt_no_hosts_equiv;
int opt_hosts_equiv_rootok;
int opt_no_rhosts;
int opt_debug;
int opt_nowarn;
int opt_disallow_null_authtok;
int opt_silent;
int opt_promiscuous;
int opt_suppress;
int opt_private_group;
int opt_no_uid_check;
const char *superuser;
const char *last_error;
};
/* logging */
static void _pam_log(int err, const char *format, ...)
{
va_list args;
va_start(args, format);
openlog("pam_rhosts_auth", LOG_CONS|LOG_PID, LOG_AUTH);
vsyslog(err, format, args);
va_end(args);
closelog();
}
static void set_option (struct _options *opts, const char *arg)
{
if (strcmp(arg, "no_hosts_equiv") == 0) {
opts->opt_no_hosts_equiv = 1;
return;
}
if (strcmp(arg, "hosts_equiv_rootok") == 0) {
opts->opt_hosts_equiv_rootok = 1;
return;
}
if (strcmp(arg, "no_rhosts") == 0) {
opts->opt_no_rhosts = 1;
return;
}
if (strcmp(arg, "debug") == 0) {
D(("debugging enabled"));
opts->opt_debug = 1;
return;
}
if (strcmp(arg, "no_warn") == 0) {
opts->opt_nowarn = 1;
return;
}
if (strcmp(arg, "promiscuous") == 0) {
opts->opt_promiscuous = 1; /* used to permit '+' in ...hosts file */
return;
}
if (strcmp(arg, "suppress") == 0) {
opts->opt_suppress = 1; /* used to suppress failure warning message */
return;
}
if (strcmp(arg, "privategroup") == 0) {
opts->opt_private_group = 1; /* used to permit group write on .rhosts
file if group has same name as owner */
return;
}
if (strcmp(arg, "no_uid_check") == 0) {
opts->opt_no_uid_check = 1; /* NIS optimization */
return;
}
if (strcmp(arg, "superuser=") == 0) {
opts->superuser = arg+sizeof("superuser=")-1;
return;
}
/*
* All other options are ignored at the present time.
*/
_pam_log(LOG_WARNING, "unrecognized option '%s'", arg);
}
static void set_parameters (struct _options *opts, int flags,
int argc, const char **argv)
{
opts->opt_silent = flags & PAM_SILENT;
opts->opt_disallow_null_authtok = flags & PAM_DISALLOW_NULL_AUTHTOK;
while (argc-- > 0) {
set_option (opts, *argv);
++argv;
}
}
/*
* Obtain the name of the remote host. Currently, this is simply by
* requesting the contents of the PAM_RHOST item.
*/
static int pam_get_rhost(pam_handle_t *pamh, const char **rhost
, const char *prompt)
{
int retval;
const char *current;
retval = pam_get_item (pamh, PAM_RHOST, (const void **)&current);
if (retval != PAM_SUCCESS)
return retval;
if (current == NULL) {
return PAM_AUTH_ERR;
}
*rhost = current;
return retval; /* pass on any error from conversation */
}
/*
* Obtain the name of the remote user. Currently, this is simply by
* requesting the contents of the PAM_RUSER item.
*/
static int pam_get_ruser(pam_handle_t *pamh, const char **ruser
, const char *prompt)
{
int retval;
const char *current;
retval = pam_get_item (pamh, PAM_RUSER, (const void **)&current);
if (retval != PAM_SUCCESS)
return retval;
if (current == NULL) {
return PAM_AUTH_ERR;
}
*ruser = current;
return retval; /* pass on any error from conversation */
}
/*
* Returns 1 if positive match, 0 if no match, -1 if negative match.
*/
static int
__icheckhost (pam_handle_t *pamh, struct _options *opts, U32 raddr
, register char *lhost, const char *rhost)
{
struct hostent *hp;
U32 laddr;
int negate=1; /* Multiply return with this to get -1 instead of 1 */
char **pp, *user;
/* Check nis netgroup. We assume that pam has done all needed
paranoia checking before we are handed the rhost */
if (strncmp("+@",lhost,2) == 0)
return(innetgr(&lhost[2],rhost,NULL,NULL));
if (strncmp("-@",lhost,2) == 0)
return(-innetgr(&lhost[2],rhost,NULL,NULL));
/* -host */
if (strncmp("-",lhost,1) == 0) {
negate=-1;
lhost++;
} else if (strcmp("+",lhost) == 0) {
(void) pam_get_item(pamh, PAM_USER, (const void **)&user);
D(("user %s has a `+' host entry", user));
if (opts->opt_promiscuous)
return (1); /* asking for trouble, but ok.. */
/* If not promiscuous: handle as negative */
return (-1);
}
/* Try for raw ip address first. */
if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
return (negate*(! (raddr ^ laddr)));
/* Better be a hostname. */
hp = gethostbyname(lhost);
if (hp == NULL)
return (0);
/* Spin through ip addresses. */
for (pp = hp->h_addr_list; *pp; ++pp)
if (!memcmp (&raddr, *pp, sizeof (U32)))
return (negate);
/* No match. */
return (0);
}
/* Returns 1 on positive match, 0 on no match, -1 on negative match */
static int __icheckuser(pam_handle_t *pamh, struct _options *opts
, const char *luser, const char *ruser
, const char *rhost)
{
/*
luser is user entry from .rhosts/hosts.equiv file
ruser is user id on remote host
rhost is the remote host name
*/
char *user;
/* [-+]@netgroup */
if (strncmp("+@",luser,2) == 0)
return (innetgr(&luser[2],NULL,ruser,NULL));
if (strncmp("-@",luser,2) == 0)
return (-innetgr(&luser[2],NULL,ruser,NULL));
/* -user */
if (strncmp("-",luser,1) == 0)
return(-(strcmp(&luser[1],ruser) == 0));
/* + */
if (strcmp("+",luser) == 0) {
(void) pam_get_item(pamh, PAM_USER, (const void **)&user);
_pam_log(LOG_WARNING, "user %s has a `+' user entry", user);
if (opts->opt_promiscuous)
return(1);
/* If not promiscuous we handle it as a negative match */
return(-1);
}
/* simple string match */
return (strcmp(ruser, luser) == 0);
}
/*
* Returns 1 for blank lines (or only comment lines) and 0 otherwise
*/
static int __isempty(char *p)
{
while (*p && isspace(*p)) {
++p;
}
return (*p == '\0' || *p == '#') ? 1:0 ;
}
/*
* Returns 0 if positive match, 1 if _not_ ok.
*/
static int
__ivaliduser (pam_handle_t *pamh, struct _options *opts,
FILE *hostf, U32 raddr,
const char *luser, const char *ruser, const char *rhost)
{
register const char *user;
register char *p;
int hcheck, ucheck;
char buf[MAXHOSTNAMELEN + 128]; /* host + login */
buf[sizeof (buf)-1] = '\0'; /* terminate line */
while (fgets(buf, sizeof(buf), hostf) != NULL) { /* hostf file line */
p = buf; /* from beginning of file.. */
/* Skip empty or comment lines */
if (__isempty(p)) {
continue;
}
/* Skip lines that are too long. */
if (strchr(p, '\n') == NULL) {
int ch = getc(hostf);
while (ch != '\n' && ch != EOF)
ch = getc(hostf);
continue;
}
/*
* If there is a hostname at the start of the line. Set it to
* lower case. A leading ' ' or '\t' indicates no hostname
*/
for (;*p && !isspace(*p); ++p) {
*p = tolower(*p);
}
/*
* next we want to find the permitted name for the remote user
*/
if (*p == ' ' || *p == '\t') {
/* <nul> terminate hostname and skip spaces */
for (*p++='\0'; *p && isspace(*p); ++p);
user = p; /* this is the user's name */
while (*p && !isspace(*p))
++p; /* find end of user's name */
} else
user = p;
*p = '\0'; /* <nul> terminate username (+host?) */
/* buf -> host(?) ; user -> username(?) */
/* First check host part */
hcheck=__icheckhost(pamh, opts, raddr, buf, rhost);
if (hcheck<0)
return(1);
if (hcheck) {
/* Then check user part */
if (! (*user))
user = luser;
ucheck=__icheckuser(pamh, opts, user, ruser, rhost);
/* Positive 'host user' match? */
if (ucheck>0)
return(0);
/* Negative 'host -user' match? */
if (ucheck<0)
return(1);
/* Neither, go on looking for match */
}
}
return (1);
}
/*
* New .rhosts strategy: We are passed an ip address. We spin through
* hosts.equiv and .rhosts looking for a match. When the .rhosts only
* has ip addresses, we don't have to trust a nameserver. When it
* contains hostnames, we spin through the list of addresses the nameserver
* gives us and look for a match.
*
* Returns 0 if ok, -1 if not ok.
*/
static int
pam_iruserok(pam_handle_t *pamh,
struct _options *opts, U32 raddr, int superuser,
const char *ruser, const char *luser, const char *rhost)
{
const char *cp;
struct stat sbuf;
struct passwd *pwd;
FILE *hostf;
uid_t uid;
int answer;
char pbuf[MAXPATHLEN]; /* potential buffer overrun */
if ((!superuser||opts->opt_hosts_equiv_rootok) && !opts->opt_no_hosts_equiv ) {
/* try to open system hosts.equiv file */
hostf = fopen (_PATH_HEQUIV, "r");
if (hostf) {
answer = __ivaliduser(pamh, opts, hostf, raddr, luser
, ruser, rhost);
(void) fclose(hostf);
if (answer == 0)
return 0; /* remote host is equivalent to localhost */
} /* else {
No hosts.equiv file on system.
} */
}
if ( opts->opt_no_rhosts )
return 1;
/*
* Identify user's local .rhosts file
*/
pwd = getpwnam(luser);
if (pwd == NULL) {
/*
* luser is assumed to be valid because of an earlier check for uid = 0
* we don't log this error twice. However, this shouldn't happen !
* --cristiang
*/
return(1);
}
/* check for buffer overrun */
if (strlen(pwd->pw_dir) + sizeof(USER_RHOSTS_FILE) + 2 >= MAXPATHLEN) {
if (opts->opt_debug)
_pam_log(LOG_DEBUG,"home directory for `%s' is too long", luser);
return 1; /* to dangerous to try */
}
(void) strcpy(pbuf, pwd->pw_dir);
(void) strcat(pbuf, USER_RHOSTS_FILE);
/*
* Change effective uid while _reading_ .rhosts. (not just
* opening). If root and reading an NFS mounted file system,
* can't read files that are 0600 as .rhosts files should be.
*/
/* We are root, this will not fail */
#ifdef linux
/* If we are on linux the better way is setfsuid */
uid = setfsuid(pwd->pw_uid);
hostf = fopen(pbuf, "r");
#else
uid = geteuid();
(void) seteuid(pwd->pw_uid);
hostf = fopen(pbuf, "r");
#endif
if (hostf == NULL) {
if (opts->opt_debug)
_pam_log(LOG_DEBUG,"Could not open %s file",pbuf);
answer = 1;
goto exit_function;
}
/*
* If not a regular file, or is owned by someone other than
* user or root or if writeable by anyone but the owner, quit.
*/
cp = NULL;
if (lstat(pbuf, &sbuf) < 0 || !S_ISREG(sbuf.st_mode))
cp = ".rhosts not regular file";
else if (fstat(fileno(hostf), &sbuf) < 0)
cp = ".rhosts fstat failed";
else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
cp = "bad .rhosts owner";
else if (sbuf.st_mode & S_IWOTH)
cp = ".rhosts writable by other!";
else if (sbuf.st_mode & S_IWGRP) {
/* private group caveat */
if (opts->opt_private_group) {
struct group *grp = getgrgid(sbuf.st_gid);
if (NULL == grp || NULL == grp->gr_name
|| strcmp(luser,grp->gr_name)) {
cp = ".rhosts writable by public group";
} else if (grp->gr_mem) {
int gcount;
/* require at most one member (luser) of this group */
for (gcount=0; grp->gr_mem[gcount]; ++gcount) {
if (strcmp(grp->gr_mem[gcount], luser)) {
gcount = -1;
break;
}
}
if (gcount < 0) {
cp = ".rhosts writable by other members of group";
}
}
} else {
cp = ".rhosts writable by group";
}
} /* It is _NOT_ safe to append an else here... Do so prior to
* S_IWGRP check */
/* If there were any problems, quit. */
if (cp) {
opts->last_error = cp;
answer = 1;
goto exit_function;
}
answer = __ivaliduser (pamh, opts, hostf, raddr, luser, ruser, rhost);
exit_function:
/*
* Go here to exit after the fsuid/euid has been adjusted so that
* they are reset before we exit.
*/
#ifdef linux
setfsuid(uid);
#else
(void)seteuid(uid);
#endif
if (hostf != NULL)
(void) fclose(hostf);
return answer;
}
static int
pam_ruserok (pam_handle_t *pamh,
struct _options *opts, const char *rhost, int superuser,
const char *ruser, const char *luser)
{
struct hostent *hp;
int answer = 1; /* default to failure */
U32 *addrs;
int n, i;
opts->last_error = (char *) 0;
hp = gethostbyname(rhost); /* identify host */
if (hp != NULL) {
/* First of all check the address length */
if (hp->h_length != 4) {
_pam_log(LOG_ALERT, "pam_rhosts module can't work with not IPv4 "
"addresses");
return 1; /* not allowed */
}
/* loop though address list */
for (n = 0; hp->h_addr_list[n]; n++);
D(("rhosts: %d addresses", n));
if (n) {
addrs = calloc (n, hp->h_length);
for (i = 0; i < n; i++)
memcpy (addrs+i, hp->h_addr_list[i], hp->h_length);
for (i = 0; i < n && answer; i++) {
D(("rhosts: address %d is %04x", i, addrs[i]));
answer = pam_iruserok(pamh, opts, addrs[i], superuser,
ruser, luser, rhost);
/* answer == 0 means success */
}
free (addrs);
}
}
return answer;
}
/*
* Internal function to do authentication
*/
static int _pam_auth_rhosts (pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int retval;
const char *luser;
const char *ruser,*rhost;
struct _options opts;
int as_root = 0;
/*
* Look at the options and set the flags accordingly.
*/
memset (&opts, 0, sizeof (opts));
set_parameters (&opts, flags, argc, argv);
/*
* Obtain the parameters for the various items
*/
for (;;) { /* abuse loop to avoid goto */
/* get the remotehost */
retval = pam_get_rhost(pamh, &rhost, NULL);
(void) pam_set_item(pamh, PAM_RHOST, rhost);
if (retval != PAM_SUCCESS) {
if (opts.opt_debug) {
_pam_log(LOG_DEBUG, "could not get the remote host name");
}
break;
}
/* get the remote user */
retval = pam_get_ruser(pamh, &ruser, NULL);
(void) pam_set_item(pamh, PAM_RUSER, ruser);
if (retval != PAM_SUCCESS) {
if (opts.opt_debug)
_pam_log(LOG_DEBUG, "could not get the remote username");
break;
}
/* get the local user */
retval = pam_get_user(pamh, &luser, NULL);
if (retval != PAM_SUCCESS) {
if (opts.opt_debug)
_pam_log(LOG_DEBUG, "could not determine name of local user");
break;
}
if (opts.superuser && !strcmp(opts.superuser, luser)) {
as_root = 1;
}
/* check if the luser uid == 0... --cristiang */
if (! opts.opt_no_uid_check) {
struct passwd *luser_pwd;
luser_pwd = getpwnam(luser);
if (luser_pwd == NULL) {
if (opts.opt_debug)
_pam_log(LOG_DEBUG, "user '%s' unknown to this system",
luser);
retval = PAM_AUTH_ERR;
break;
}
if (luser_pwd->pw_uid == 0)
as_root = 1;
luser_pwd = NULL; /* forget */
}
/*
* Validate the account information.
*/
if (pam_ruserok (pamh, &opts, rhost, as_root, ruser, luser) != 0) {
if ( !opts.opt_suppress ) {
_pam_log(LOG_WARNING, "denied to %s@%s as %s: %s",
ruser, rhost, luser, (opts.last_error==NULL) ?
"access not allowed":opts.last_error);
}
retval = PAM_AUTH_ERR;
} else {
_pam_log(LOG_NOTICE, "allowed to %s@%s as %s",
ruser, rhost, luser);
}
break;
}
return retval;
}
/* --- authentication management functions --- */
PAM_EXTERN
int pam_sm_authenticate (pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int retval;
if (sizeof(U32) != 4) {
_pam_log (LOG_ALERT, "pam_rhosts module can\'t work on this hardware "
"(yet)");
return PAM_AUTH_ERR;
}
sethostent(1);
retval = _pam_auth_rhosts (pamh, flags, argc, argv);
endhostent();
return retval;
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc,
const char **argv)
{
return PAM_SUCCESS;
}
/* end of module definition */
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_rhosts_auth_modstruct = {
"pam_rhosts_auth",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif

View File

@ -0,0 +1,16 @@
#
# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
# $FreeBSD$
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
# what you are doing!).
#
# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27
#
include ../../Make.Rules
TITLE=pam_securetty
include ../Simple.Rules

View File

@ -0,0 +1,10 @@
$FreeBSD$
pam_securetty:
Allows root logins only if the user is logging in on a
"secure" tty, as defined by the listing in /etc/securetty
Also checks to make sure that /etc/securetty is a plain
file and not world writable.
- Elliot Lee <sopwith@redhat.com>, Red Hat Software.
July 25, 1996.

View File

@ -0,0 +1,192 @@
/* pam_securetty module */
#define SECURETTY_FILE "/etc/securetty"
#define TTY_PREFIX "/dev/"
/*
* by Elliot Lee <sopwith@redhat.com>, Red Hat Software.
* July 25, 1996.
* This code shamelessly ripped from the pam_rootok module.
* Slight modifications AGM. 1996/12/3
* $FreeBSD$
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <syslog.h>
#include <stdarg.h>
#include <pwd.h>
#include <string.h>
#define PAM_SM_AUTH
/*
* here, we make a definition for the externally accessible function
* in this file (this definition is required for static a module
* but strongly encouraged generally) it is used to instruct the
* modules include file to define the function prototypes.
*/
#define PAM_SM_AUTH
#include <security/pam_modules.h>
/* some syslogging */
static void _pam_log(int err, const char *format, ...)
{
va_list args;
va_start(args, format);
openlog("PAM-securetty", LOG_CONS|LOG_PID, LOG_AUTH);
vsyslog(err, format, args);
va_end(args);
closelog();
}
/* argument parsing */
#define PAM_DEBUG_ARG 0x0001
static int _pam_parse(int argc, const char **argv)
{
int ctrl=0;
/* step through arguments */
for (ctrl=0; argc-- > 0; ++argv) {
/* generic options */
if (!strcmp(*argv,"debug"))
ctrl |= PAM_DEBUG_ARG;
else {
_pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
}
}
return ctrl;
}
/* --- authentication management functions (only) --- */
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
int retval = PAM_AUTH_ERR;
const char *username;
char *uttyname;
char ttyfileline[256];
struct stat ttyfileinfo;
struct passwd *user_pwd;
FILE *ttyfile;
int ctrl;
/* parse the arguments */
ctrl = _pam_parse(argc, argv);
retval = pam_get_user(pamh, &username, NULL);
if (retval != PAM_SUCCESS || username == NULL) {
if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_WARNING, "cannot determine username");
}
return (retval == PAM_CONV_AGAIN
? PAM_INCOMPLETE:PAM_SERVICE_ERR);
}
retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname);
if (retval != PAM_SUCCESS || uttyname == NULL) {
if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_WARNING, "cannot determine user's tty");
}
return PAM_SERVICE_ERR;
}
/* The PAM_TTY item may be prefixed with "/dev/" - skip that */
if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0)
uttyname += sizeof(TTY_PREFIX)-1;
user_pwd = getpwnam(username);
if (user_pwd == NULL) {
return PAM_IGNORE;
} else if (user_pwd->pw_uid != 0) { /* If the user is not root,
securetty's does not apply
to them */
return PAM_SUCCESS;
}
if (stat(SECURETTY_FILE, &ttyfileinfo)) {
_pam_log(LOG_NOTICE, "Couldn't open " SECURETTY_FILE);
return PAM_SUCCESS; /* for compatibility with old securetty handling,
this needs to succeed. But we still log the
error. */
}
if ((ttyfileinfo.st_mode & S_IWOTH)
|| !S_ISREG(ttyfileinfo.st_mode)) {
/* If the file is world writable or is not a
normal file, return error */
_pam_log(LOG_ERR, SECURETTY_FILE
" is either world writable or not a normal file");
return PAM_AUTH_ERR;
}
ttyfile = fopen(SECURETTY_FILE,"r");
if(ttyfile == NULL) { /* Check that we opened it successfully */
_pam_log(LOG_ERR,
"Error opening " SECURETTY_FILE);
return PAM_SERVICE_ERR;
}
/* There should be no more errors from here on */
retval=PAM_AUTH_ERR;
/* This loop assumes that PAM_SUCCESS == 0
and PAM_AUTH_ERR != 0 */
while((fgets(ttyfileline,sizeof(ttyfileline)-1, ttyfile) != NULL)
&& retval) {
if(ttyfileline[strlen(ttyfileline) - 1] == '\n')
ttyfileline[strlen(ttyfileline) - 1] = '\0';
retval = strcmp(ttyfileline,uttyname);
}
fclose(ttyfile);
if(retval) {
if (ctrl & PAM_DEBUG_ARG)
_pam_log(LOG_WARNING, "access denied: tty '%s' is not secure !",
uttyname);
retval = PAM_AUTH_ERR;
}
if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG))
_pam_log(LOG_DEBUG, "access allowed for '%s' on '%s'",
username, uttyname);
return retval;
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
return PAM_SUCCESS;
}
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_securetty_modstruct = {
"pam_securetty",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif
/* end of module definition */

View File

@ -0,0 +1,16 @@
#
# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
# $FreeBSD$
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
# what you are doing!).
#
# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27
#
include ../../Make.Rules
TITLE=pam_shells
include ../Simple.Rules

View File

@ -0,0 +1,11 @@
$FreeBSD$
pam_shells:
Authentication is granted if the users shell is listed in
/etc/shells. If no shell is in /etc/passwd (empty), the
/bin/sh is used (following ftpd's convention).
Also checks to make sure that /etc/shells is a plain
file and not world writable.
- Erik Troan <ewt@redhat.com>, Red Hat Software.
August 5, 1996.

View File

@ -0,0 +1,134 @@
/* pam_shells module */
#define SHELL_FILE "/etc/shells"
/*
* by Erik Troan <ewt@redhat.com>, Red Hat Software.
* August 5, 1996.
* This code shamelessly ripped from the pam_securetty module.
* $FreeBSD$
*/
#define _BSD_SOURCE
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>
/*
* here, we make a definition for the externally accessible function
* in this file (this definition is required for static a module
* but strongly encouraged generally) it is used to instruct the
* modules include file to define the function prototypes.
*/
#define PAM_SM_AUTH
#include <security/pam_modules.h>
/* some syslogging */
static void _pam_log(int err, const char *format, ...)
{
va_list args;
va_start(args, format);
openlog("PAM-shells", LOG_CONS|LOG_PID, LOG_AUTH);
vsyslog(err, format, args);
va_end(args);
closelog();
}
/* --- authentication management functions (only) --- */
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
int retval = PAM_AUTH_ERR;
const char *userName;
char *userShell;
char shellFileLine[256];
struct stat sb;
struct passwd * pw;
FILE * shellFile;
retval = pam_get_user(pamh,&userName,NULL);
if(retval != PAM_SUCCESS)
return PAM_SERVICE_ERR;
if(!userName || (strlen(userName) <= 0)) {
/* Don't let them use a NULL username... */
pam_get_user(pamh,&userName,NULL);
if (retval != PAM_SUCCESS)
return PAM_SERVICE_ERR;
}
pw = getpwnam(userName);
if (!pw)
return PAM_AUTH_ERR; /* user doesn't exist */
userShell = pw->pw_shell;
if(stat(SHELL_FILE,&sb)) {
_pam_log(LOG_ERR,
"%s cannot be stat'd (it probably does not exist)", SHELL_FILE);
return PAM_AUTH_ERR; /* must have /etc/shells */
}
if((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) {
_pam_log(LOG_ERR,
"%s is either world writable or not a normal file", SHELL_FILE);
return PAM_AUTH_ERR;
}
shellFile = fopen(SHELL_FILE,"r");
if(shellFile == NULL) { /* Check that we opened it successfully */
_pam_log(LOG_ERR,
"Error opening %s", SHELL_FILE);
return PAM_SERVICE_ERR;
}
/* There should be no more errors from here on */
retval=PAM_AUTH_ERR;
/* This loop assumes that PAM_SUCCESS == 0
and PAM_AUTH_ERR != 0 */
while((fgets(shellFileLine,255,shellFile) != NULL)
&& retval) {
if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
shellFileLine[strlen(shellFileLine) - 1] = '\0';
retval = strcmp(shellFileLine, userShell);
}
fclose(shellFile);
if(retval)
retval = PAM_AUTH_ERR;
return retval;
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
return PAM_SUCCESS;
}
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_shells_modstruct = {
"pam_shells",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif
/* end of module definition */

View File

@ -0,0 +1,16 @@
#
# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $
# $FreeBSD$
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
# what you are doing!).
#
# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27
#
include ../../Make.Rules
TITLE=pam_warn
include ../Simple.Rules

View File

@ -0,0 +1,26 @@
# $Id: README,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $
# $FreeBSD$
This module is an authentication module that does not authenticate.
Instead it always returns PAM_IGNORE, indicating that it does not want
to affect the authentication process.
Its purpose is to log a message to the syslog indicating the
pam_item's available at the time it was invoked. It is a diagnostic
tool.
Recognized arguments:
<none>
module services provided:
auth _authenticate and _setcred (blank)
acct _acct_mgmt [mapped to _authenticate]
session _open_session and
_close_session [mapped to _authenticate ]
password _chauthtok [mapped to _authenticate]
Andrew Morgan
1996/11/14

View File

@ -0,0 +1,133 @@
/* pam_warn module */
/*
* $Id: pam_warn.c,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $
* $FreeBSD$
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
*/
#define _BSD_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <syslog.h>
#include <stdarg.h>
/*
* here, we make a definition for the externally accessible function
* in this file (this definition is required for static a module
* but strongly encouraged generally) it is used to instruct the
* modules include file to define the function prototypes.
*/
#define PAM_SM_AUTH
#define PAM_SM_PASSWORD
#include <security/pam_modules.h>
/* some syslogging */
static void _pam_log(int err, const char *format, ...)
{
va_list args;
va_start(args, format);
openlog("PAM-warn", LOG_CONS|LOG_PID, LOG_AUTH);
vsyslog(err, format, args);
va_end(args);
closelog();
}
/* --- authentication management functions (only) --- */
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc
, const char **argv)
{
const char *service=NULL, *user=NULL, *terminal=NULL
, *rhost=NULL, *ruser=NULL;
(void) pam_get_item(pamh, PAM_SERVICE, (const void **)&service);
(void) pam_get_item(pamh, PAM_TTY, (const void **)&terminal);
_pam_log(LOG_NOTICE, "service: %s [on terminal: %s]"
, service ? service : "<unknown>"
, terminal ? terminal : "<unknown>"
);
(void) pam_get_user(pamh, &user, "Who are you? ");
(void) pam_get_item(pamh, PAM_RUSER, (const void **)&ruser);
(void) pam_get_item(pamh, PAM_RHOST, (const void **)&rhost);
_pam_log(LOG_NOTICE, "user: (uid=%d) -> %s [remote: %s@%s]"
, getuid()
, user ? user : "<unknown>"
, ruser ? ruser : "?nobody"
, rhost ? rhost : "?nowhere"
);
/* we are just a fly on the wall */
return PAM_IGNORE;
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
, const char **argv)
{
return PAM_IGNORE;
}
/* password updating functions */
PAM_EXTERN
int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc
, const char **argv)
{
/* map to the authentication function... */
return pam_sm_authenticate(pamh, flags, argc, argv);
}
PAM_EXTERN int
pam_sm_acct_mgmt (pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
/* map to the authentication function... */
return pam_sm_authenticate(pamh, flags, argc, argv);
}
PAM_EXTERN int
pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
/* map to the authentication function... */
return pam_sm_authenticate(pamh, flags, argc, argv);
}
PAM_EXTERN int
pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
/* map to the authentication function... */
return pam_sm_authenticate(pamh, flags, argc, argv);
}
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_warn_modstruct = {
"pam_warn",
pam_sm_authenticate,
pam_sm_setcred,
pam_sm_acct_mgmt,
pam_sm_open_session,
pam_sm_close_session,
pam_sm_chauthtok,
};
#endif
/* end of module definition */