summaryrefslogtreecommitdiff
path: root/Linux-PAM/modules/pam_group/pam_group.c
diff options
context:
space:
mode:
Diffstat (limited to 'Linux-PAM/modules/pam_group/pam_group.c')
-rw-r--r--Linux-PAM/modules/pam_group/pam_group.c258
1 files changed, 114 insertions, 144 deletions
diff --git a/Linux-PAM/modules/pam_group/pam_group.c b/Linux-PAM/modules/pam_group/pam_group.c
index c7b75fe2..1dc329ef 100644
--- a/Linux-PAM/modules/pam_group/pam_group.c
+++ b/Linux-PAM/modules/pam_group/pam_group.c
@@ -1,17 +1,10 @@
/* pam_group module */
/*
- * $Id: pam_group.c,v 1.7 2004/09/24 13:13:20 kukuk Exp $
- *
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/7/6
*/
-const static char rcsid[] =
-"$Id: pam_group.c,v 1.7 2004/09/24 13:13:20 kukuk Exp $;\n"
-"Version 0.5 for Linux-PAM\n"
-"Copyright (c) Andrew G. Morgan 1996 <morgan@linux.kernel.org>\n";
-
-#define _BSD_SOURCE
+#include "config.h"
#include <sys/file.h>
#include <stdio.h>
@@ -27,23 +20,18 @@ const static char rcsid[] =
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <netdb.h>
-#ifdef DEFAULT_CONF_FILE
-# define PAM_GROUP_CONF DEFAULT_CONF_FILE /* from external define */
-#else
-# define PAM_GROUP_CONF "/etc/security/group.conf"
-#endif
#define PAM_GROUP_BUFLEN 1000
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
-#ifdef TRUE
-# undef TRUE
-#endif
-#ifdef FALSE
-# undef FALSE
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
#endif
-typedef enum { FALSE, TRUE } boolean;
typedef enum { AND, OR } operator;
/*
@@ -57,21 +45,11 @@ typedef enum { AND, OR } operator;
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
-#include <security/_pam_modutil.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
/* --- static functions for checking whether the user should be let in --- */
-static void _log_err(const char *format, ... )
-{
- va_list args;
-
- va_start(args, format);
- openlog("pam_group", LOG_CONS|LOG_PID, LOG_AUTH);
- vsyslog(LOG_CRIT, format, args);
- va_end(args);
- closelog();
-}
-
static void shift_bytes(char *mem, int from, int by)
{
while (by-- > 0) {
@@ -86,14 +64,15 @@ static void shift_bytes(char *mem, int from, int by)
* Therefore, always check buf after calling this to see if an error
* occurred.
*/
-static int read_field(int fd, char **buf, int *from, int *to)
+static int
+read_field (const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
{
/* is buf set ? */
if (! *buf) {
*buf = (char *) malloc(PAM_GROUP_BUFLEN);
if (! *buf) {
- _log_err("out of memory");
+ pam_syslog(pamh, LOG_ERR, "out of memory");
return -1;
}
*from = *to = 0;
@@ -103,7 +82,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
/* do we have a file open ? return error */
if (fd < 0 && *to <= 0) {
- _log_err( PAM_GROUP_CONF " not opened");
+ pam_syslog(pamh, LOG_ERR, "%s not opened", PAM_GROUP_CONF);
memset(*buf, 0, PAM_GROUP_BUFLEN);
_pam_drop(*buf);
return -1;
@@ -132,7 +111,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
i = read(fd, *to + *buf, PAM_GROUP_BUFLEN - *to);
if (i < 0) {
- _log_err("error reading " PAM_GROUP_CONF);
+ pam_syslog(pamh, LOG_ERR, "error reading %s: %m", PAM_GROUP_CONF);
close(fd);
return -1;
} else if (!i) {
@@ -140,7 +119,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
fd = -1; /* end of file reached */
} else
*to += i;
-
+
/*
* contract the buffer. Delete any comments, and replace all
* multiple spaces with single commas
@@ -161,8 +140,9 @@ static int read_field(int fd, char **buf, int *from, int *to)
}
}
switch ((*buf)[i]) {
- int j,c;
+ int j, c;
case '#':
+ c = 0;
for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
if (j >= *to) {
(*buf)[*to = ++i] = '\0';
@@ -171,8 +151,9 @@ static int read_field(int fd, char **buf, int *from, int *to)
*to -= j-i;
++i;
} else {
- _log_err("internal error in " __FILE__
- " at line %d", __LINE__ );
+ pam_syslog(pamh, LOG_CRIT,
+ "internal error in file %s at line %d",
+ __FILE__, __LINE__);
close(fd);
return -1;
}
@@ -236,11 +217,10 @@ static int read_field(int fd, char **buf, int *from, int *to)
static int logic_member(const char *string, int *at)
{
- int len,c,to;
+ int c,to;
int done=0;
int token=0;
- len=0;
to=*at;
do {
c = string[to++];
@@ -263,7 +243,7 @@ static int logic_member(const char *string, int *at)
default:
if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
- || c == '-' || c == '.' || c == '/') {
+ || c == '-' || c == '.' || c == '/' || c == ':') {
token = 1;
} else if (token) {
--to;
@@ -279,11 +259,13 @@ static int logic_member(const char *string, int *at)
typedef enum { VAL, OP } expect;
-static boolean logic_field(const void *me, const char *x, int rule,
- boolean (*agrees)(const void *, const char *
- , int, int))
+static int
+logic_field (const pam_handle_t *pamh, const void *me,
+ const char *x, int rule,
+ int (*agrees)(const pam_handle_t *pamh, const void *,
+ const char *, int, int))
{
- boolean left=FALSE, right, not=FALSE;
+ int left=FALSE, right, not=FALSE;
operator oper=OR;
int at=0, l;
expect next=VAL;
@@ -294,15 +276,18 @@ static boolean logic_field(const void *me, const char *x, int rule,
if (next == VAL) {
if (c == '!')
not = !not;
- else if (isalpha(c) || c == '*') {
- right = not ^ agrees(me, x+at, l, rule);
+ else if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
+ || c == '-' || c == '.' || c == '/' || c == ':') {
+ right = not ^ agrees(pamh, me, x+at, l, rule);
if (oper == AND)
left &= right;
else
left |= right;
next = OP;
} else {
- _log_err("garbled syntax; expected name (rule #%d)", rule);
+ pam_syslog(pamh, LOG_ERR,
+ "garbled syntax; expected name (rule #%d)",
+ rule);
return FALSE;
}
} else { /* OP */
@@ -314,8 +299,9 @@ static boolean logic_field(const void *me, const char *x, int rule,
oper = OR;
break;
default:
- _log_err("garbled syntax; expected & or | (rule #%d)"
- , rule);
+ pam_syslog(pamh, LOG_ERR,
+ "garbled syntax; expected & or | (rule #%d)",
+ rule);
D(("%c at %d",c,at));
return FALSE;
}
@@ -327,7 +313,9 @@ static boolean logic_field(const void *me, const char *x, int rule,
return left;
}
-static boolean is_same(const void *A, const char *b, int len, int rule)
+static int
+is_same (const pam_handle_t *pamh UNUSED,
+ const void *A, const char *b, int len, int rule UNUSED)
{
int i;
const char *a;
@@ -349,10 +337,10 @@ typedef struct {
int minute; /* integer, hour*100+minute for now */
} TIME;
-struct day {
+static struct day {
const char *d;
int bit;
-} static const days[11] = {
+} const days[11] = {
{ "su", 01 },
{ "mo", 02 },
{ "tu", 04 },
@@ -382,9 +370,11 @@ static TIME time_now(void)
}
/* take the current date and see if the range "date" passes it */
-static boolean check_time(const void *AT, const char *times, int len, int rule)
+static int
+check_time (const pam_handle_t *pamh, const void *AT,
+ const char *times, int len, int rule)
{
- boolean not,pass;
+ int not,pass;
int marked_day, time_start, time_end;
const TIME *at;
int i,j=0;
@@ -394,7 +384,8 @@ static boolean check_time(const void *AT, const char *times, int len, int rule)
if (times == NULL) {
/* this should not happen */
- _log_err("internal error: " __FILE__ " line %d", __LINE__);
+ pam_syslog(pamh, LOG_CRIT, "internal error in file %s at line %d",
+ __FILE__, __LINE__);
return FALSE;
}
@@ -418,13 +409,13 @@ static boolean check_time(const void *AT, const char *times, int len, int rule)
}
j += 2;
if (this_day == -1) {
- _log_err("bad day specified (rule #%d)", rule);
+ pam_syslog(pamh, LOG_ERR, "bad day specified (rule #%d)", rule);
return FALSE;
}
marked_day ^= this_day;
}
if (marked_day == 0) {
- _log_err("no day specified");
+ pam_syslog(pamh, LOG_ERR, "no day specified");
return FALSE;
}
D(("day range = 0%o", marked_day));
@@ -448,7 +439,7 @@ static boolean check_time(const void *AT, const char *times, int len, int rule)
D(("i=%d, time_end=%d, times[j]='%c'", i, time_end, times[j]));
if (i != 5 || time_end == -1) {
- _log_err("no/bad times specified (rule #%d)", rule);
+ pam_syslog(pamh, LOG_ERR, "no/bad times specified (rule #%d)", rule);
return TRUE;
}
D(("times(%d to %d)", time_start,time_end));
@@ -483,11 +474,10 @@ static boolean check_time(const void *AT, const char *times, int len, int rule)
static int find_member(const char *string, int *at)
{
- int len,c,to;
+ int c,to;
int done=0;
int token=0;
- len=0;
to=*at;
do {
c = string[to++];
@@ -547,7 +537,7 @@ static int mkgrplist(pam_handle_t *pamh, char *buf, gid_t **list, int len)
if (tmp != NULL) {
(*list) = tmp;
} else {
- _log_err("out of memory for group list");
+ pam_syslog(pamh, LOG_ERR, "out of memory for group list");
free(*list);
(*list) = NULL;
return -1;
@@ -561,44 +551,17 @@ static int mkgrplist(pam_handle_t *pamh, char *buf, gid_t **list, int len)
D(("found group: %s",buf+at));
/* this is where we convert a group name to a gid_t */
-#ifdef WANT_PWDB
- {
- int retval;
- const struct pwdb *pw=NULL;
-
- retval = pwdb_locate("group", PWDB_DEFAULT, buf+at
- , PWDB_ID_UNKNOWN, &pw);
- if (retval != PWDB_SUCCESS) {
- _log_err("bad group: %s; %s", buf+at, pwdb_strerror(retval));
- } else {
- const struct pwdb_entry *pwe=NULL;
-
- D(("group %s exists", buf+at));
- retval = pwdb_get_entry(pw, "gid", &pwe);
- if (retval == PWDB_SUCCESS) {
- D(("gid = %d [%p]",* (const gid_t *) pwe->value,list));
- (*list)[len++] = * (const gid_t *) pwe->value;
- pwdb_entry_delete(&pwe); /* tidy up */
- } else {
- _log_err("%s group entry is bad; %s"
- , pwdb_strerror(retval));
- }
- pw = NULL; /* break link - cached for later use */
- }
- }
-#else
{
const struct group *grp;
- grp = _pammodutil_getgrnam(pamh, buf+at);
+ grp = pam_modutil_getgrnam(pamh, buf+at);
if (grp == NULL) {
- _log_err("bad group: %s", buf+at);
+ pam_syslog(pamh, LOG_ERR, "bad group: %s", buf+at);
} else {
D(("group %s exists", buf+at));
(*list)[len++] = grp->gr_gid;
}
}
-#endif
/* next entry along */
@@ -630,7 +593,11 @@ static int check_account(pam_handle_t *pamh, const char *service,
if (no_grps > 0) {
grps = calloc( blk_size(no_grps) , sizeof(gid_t) );
D(("copying current list into grps [%d big]",blk_size(no_grps)));
- (void) getgroups(no_grps, grps);
+ if (getgroups(no_grps, grps) < 0) {
+ D(("getgroups call failed"));
+ no_grps = 0;
+ grps = NULL;
+ }
#ifdef DEBUG
{
int z;
@@ -653,7 +620,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the service name field */
- fd = read_field(fd,&buffer,&from,&to);
+ fd = read_field(pamh,fd,&buffer,&from,&to);
if (!buffer || !buffer[0]) {
/* empty line .. ? */
continue;
@@ -661,44 +628,51 @@ static int check_account(pam_handle_t *pamh, const char *service,
++count;
D(("working on rule #%d",count));
- good = logic_field(service, buffer, count, is_same);
+ good = logic_field(pamh,service, buffer, count, is_same);
D(("with service: %s", good ? "passes":"fails" ));
/* here we get the terminal name field */
- fd = read_field(fd,&buffer,&from,&to);
+ fd = read_field(pamh,fd,&buffer,&from,&to);
if (!buffer || !buffer[0]) {
- _log_err(PAM_GROUP_CONF "; no tty entry #%d", count);
+ pam_syslog(pamh, LOG_ERR,
+ "%s: no tty entry #%d", PAM_GROUP_CONF, count);
continue;
}
- good &= logic_field(tty, buffer, count, is_same);
+ good &= logic_field(pamh,tty, buffer, count, is_same);
D(("with tty: %s", good ? "passes":"fails" ));
/* here we get the username field */
- fd = read_field(fd,&buffer,&from,&to);
+ fd = read_field(pamh,fd,&buffer,&from,&to);
if (!buffer || !buffer[0]) {
- _log_err(PAM_GROUP_CONF "; no user entry #%d", count);
+ pam_syslog(pamh, LOG_ERR,
+ "%s: no user entry #%d", PAM_GROUP_CONF, count);
continue;
}
- good &= logic_field(user, buffer, count, is_same);
+ /* If buffer starts with @, we are using netgroups */
+ if (buffer[0] == '@')
+ good &= innetgr (&buffer[1], NULL, user, NULL);
+ else
+ good &= logic_field(pamh,user, buffer, count, is_same);
D(("with user: %s", good ? "passes":"fails" ));
/* here we get the time field */
- fd = read_field(fd,&buffer,&from,&to);
+ fd = read_field(pamh,fd,&buffer,&from,&to);
if (!buffer || !buffer[0]) {
- _log_err(PAM_GROUP_CONF "; no time entry #%d", count);
+ pam_syslog(pamh, LOG_ERR,
+ "%s: no time entry #%d", PAM_GROUP_CONF, count);
continue;
}
- good &= logic_field(&here_and_now, buffer, count, check_time);
+ good &= logic_field(pamh,&here_and_now, buffer, count, check_time);
D(("with time: %s", good ? "passes":"fails" ));
- fd = read_field(fd,&buffer,&from,&to);
+ fd = read_field(pamh,fd,&buffer,&from,&to);
if (!buffer || !buffer[0]) {
- _log_err(PAM_GROUP_CONF "; no listed groups for rule #%d"
- , count);
+ pam_syslog(pamh, LOG_ERR,
+ "%s: no listed groups for rule #%d", PAM_GROUP_CONF, count);
continue;
}
@@ -719,9 +693,10 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* check the line is terminated correctly */
- fd = read_field(fd,&buffer,&from,&to);
+ fd = read_field(pamh,fd,&buffer,&from,&to);
if (buffer && buffer[0]) {
- _log_err(PAM_GROUP_CONF "; poorly terminated rule #%d", count);
+ pam_syslog(pamh, LOG_ERR,
+ "%s: poorly terminated rule #%d", PAM_GROUP_CONF, count);
}
if (good > 0) {
@@ -737,17 +712,19 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* now set the groups for the user */
if (no_grps > 0) {
+#ifdef DEBUG
int err;
+#endif
D(("trying to set %d groups", no_grps));
#ifdef DEBUG
for (err=0; err<no_grps; ++err) {
D(("gid[%d]=%d", err, grps[err]));
}
#endif
- if ((err = setgroups(no_grps, grps))) {
- D(("but couldn't set groups %d", err));
- _log_err("unable to set the group membership for user (err=%d)"
- , err);
+ if (setgroups(no_grps, grps) != 0) {
+ D(("but couldn't set groups %m"));
+ pam_syslog(pamh, LOG_ERR,
+ "unable to set the group membership for user: %m");
retval = PAM_CRED_ERR;
}
}
@@ -763,17 +740,20 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* --- public authentication management functions --- */
-PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags
- , int argc, const char **argv)
+PAM_EXTERN int
+pam_sm_authenticate (pam_handle_t *pamh UNUSED, int flags UNUSED,
+ int argc UNUSED, const char **argv UNUSED)
{
return PAM_IGNORE;
}
-PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
- , int argc, const char **argv)
+PAM_EXTERN int
+pam_sm_setcred (pam_handle_t *pamh, int flags,
+ int argc UNUSED, const char **argv UNUSED)
{
- const char *service=NULL, *tty=NULL;
+ const void *service=NULL, *void_tty=NULL;
const char *user=NULL;
+ const char *tty;
int retval;
unsigned setting;
@@ -787,9 +767,9 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
/* set service name */
- if (pam_get_item(pamh, PAM_SERVICE, (const void **)&service)
+ if (pam_get_item(pamh, PAM_SERVICE, &service)
!= PAM_SUCCESS || service == NULL) {
- _log_err("cannot find the current service name");
+ pam_syslog(pamh, LOG_ERR, "cannot find the current service name");
return PAM_ABORT;
}
@@ -797,28 +777,33 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
|| *user == '\0') {
- _log_err("cannot determine the user's name");
+ pam_syslog(pamh, LOG_ERR, "cannot determine the user's name");
return PAM_USER_UNKNOWN;
}
/* set tty name */
- if (pam_get_item(pamh, PAM_TTY, (const void **)&tty) != PAM_SUCCESS
- || tty == NULL) {
+ if (pam_get_item(pamh, PAM_TTY, &void_tty) != PAM_SUCCESS
+ || void_tty == NULL) {
D(("PAM_TTY not set, probing stdin"));
tty = ttyname(STDIN_FILENO);
if (tty == NULL) {
- _log_err("couldn't get the tty name");
- return PAM_ABORT;
+ tty = "";
}
if (pam_set_item(pamh, PAM_TTY, tty) != PAM_SUCCESS) {
- _log_err("couldn't set tty name");
+ pam_syslog(pamh, LOG_ERR, "couldn't set tty name");
return PAM_ABORT;
}
}
-
- if (strncmp("/dev/",tty,5) == 0) { /* strip leading /dev/ */
- tty += 5;
+ else
+ tty = (const char *) void_tty;
+
+ if (tty[0] == '/') { /* full path */
+ const char *t;
+ tty++;
+ if ((t = strchr(tty, '/')) != NULL) {
+ tty = t + 1;
+ }
}
/* good, now we have the service name, the user and the terminal name */
@@ -827,22 +812,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
D(("user=%s", user));
D(("tty=%s", tty));
-#ifdef WANT_PWDB
-
- /* We initialize the pwdb library and check the account */
- retval = pwdb_start(); /* initialize */
- if (retval == PWDB_SUCCESS) {
- retval = check_account(pamh, service,tty,user); /* get groups */
- (void) pwdb_end(); /* tidy up */
- } else {
- D(("failed to initialize pwdb; %s", pwdb_strerror(retval)));
- _log_err("unable to initialize libpwdb");
- retval = PAM_ABORT;
- }
-
-#else /* WANT_PWDB */
retval = check_account(pamh,service,tty,user); /* get groups */
-#endif /* WANT_PWDB */
return retval;
}