- add auditing to pam_access, pam_limits, and pam_time
- moved sanity testing code to check script
This commit is contained in:
parent
392622e8de
commit
2badd4f116
838
pam-0.99.8.1-audit-failed.patch
Normal file
838
pam-0.99.8.1-audit-failed.patch
Normal file
@ -0,0 +1,838 @@
|
||||
diff -up Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed Linux-PAM-0.99.8.1/libpam/libpam.map
|
||||
--- Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed 2006-06-14 17:28:44.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/libpam/libpam.map 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -45,3 +45,7 @@ LIBPAM_MODUTIL_1.0 {
|
||||
pam_modutil_read;
|
||||
pam_modutil_write;
|
||||
};
|
||||
+LIBPAM_MODUTIL_1.1 {
|
||||
+ global:
|
||||
+ pam_modutil_audit_write;
|
||||
+} LIBPAM_MODUTIL_1.0;
|
||||
diff -up Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed Linux-PAM-0.99.8.1/libpam/pam_audit.c
|
||||
--- Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed 2008-01-22 22:24:05.000000000 +0100
|
||||
+++ Linux-PAM-0.99.8.1/libpam/pam_audit.c 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -42,39 +42,53 @@ _pam_audit_writelog(pam_handle_t *pamh,
|
||||
best to fix it. */
|
||||
errno = -rc;
|
||||
|
||||
+ if (rc < 0 && errno != old_errno)
|
||||
+ {
|
||||
+ old_errno = errno;
|
||||
+ pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
|
||||
+ }
|
||||
+
|
||||
pamh->audit_state |= PAMAUDIT_LOGGED;
|
||||
|
||||
- if (rc < 0) {
|
||||
- if (rc == -EPERM && getuid() != 0)
|
||||
- return 0;
|
||||
- if (errno != old_errno) {
|
||||
- old_errno = errno;
|
||||
- pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
|
||||
- }
|
||||
- }
|
||||
- return rc;
|
||||
+ if (rc == -EPERM && getuid () != 0)
|
||||
+ return 0;
|
||||
+ else
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
-int
|
||||
-_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
|
||||
+static int
|
||||
+_pam_audit_open(pam_handle_t *pamh)
|
||||
{
|
||||
- const char *message;
|
||||
- int type;
|
||||
int audit_fd;
|
||||
-
|
||||
audit_fd = audit_open();
|
||||
if (audit_fd < 0) {
|
||||
/* You get these error codes only when the kernel doesn't have
|
||||
* audit compiled in. */
|
||||
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
||||
errno == EAFNOSUPPORT)
|
||||
- return retval;
|
||||
+ return -2;
|
||||
|
||||
/* this should only fail in case of extreme resource shortage,
|
||||
* need to prevent login in that case for CAPP compliance.
|
||||
*/
|
||||
pam_syslog(pamh, LOG_CRIT, "audit_open() failed: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return audit_fd;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
|
||||
+{
|
||||
+ const char *message;
|
||||
+ int type;
|
||||
+ int audit_fd;
|
||||
+
|
||||
+ if ((audit_fd=_pam_audit_open(pamh)) == -1) {
|
||||
return PAM_SYSTEM_ERR;
|
||||
+ } else if (audit_fd == -2) {
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
@@ -141,4 +155,30 @@ _pam_audit_end(pam_handle_t *pamh, int s
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int
|
||||
+pam_modutil_audit_write(pam_handle_t *pamh, int type,
|
||||
+ const char *message, int retval)
|
||||
+{
|
||||
+ int audit_fd;
|
||||
+ int rc;
|
||||
+
|
||||
+ if ((audit_fd=_pam_audit_open(pamh)) == -1) {
|
||||
+ return PAM_SYSTEM_ERR;
|
||||
+ } else if (audit_fd == -2) {
|
||||
+ return retval;
|
||||
+ }
|
||||
+
|
||||
+ rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
|
||||
+
|
||||
+ audit_close(audit_fd);
|
||||
+
|
||||
+ return rc < 0 ? PAM_SYSTEM_ERR : PAM_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+int pam_modutil_audit_write(pam_handle_t *pamh UNUSED, int type UNUSED,
|
||||
+ const char *message UNUSED, int retval UNUSED)
|
||||
+{
|
||||
+ return PAM_SUCCESS;
|
||||
+}
|
||||
#endif /* HAVE_LIBAUDIT */
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed 2007-06-22 10:03:29.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -29,6 +29,9 @@
|
||||
nodefgroup
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
accessfile=<replaceable>file</replaceable>
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
@@ -54,6 +57,10 @@
|
||||
<filename>/etc/security/access.conf</filename> if you don't specify
|
||||
another file.
|
||||
</para>
|
||||
+ <para>
|
||||
+ If Linux PAM is compiled with audit support the module will report
|
||||
+ when it denies access based on origin (host or tty).
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_access-options">
|
||||
@@ -87,6 +94,17 @@
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
+ <option>noaudit</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not report logins from disallowed hosts and ttys to the audit subsystem.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
<option>fieldsep=<replaceable>separators</replaceable></option>
|
||||
</term>
|
||||
<listitem>
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed 2007-06-25 11:59:11.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -46,6 +46,10 @@
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+#include <libaudit.h>
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* here, we make definitions for the externally accessible functions
|
||||
* in this file (these definitions are required for static modules
|
||||
@@ -81,17 +85,11 @@
|
||||
|
||||
/* Delimiters for fields and for lists of users, ttys or hosts. */
|
||||
|
||||
-static const char *fs = ":"; /* field separator */
|
||||
-static const char *sep = ", \t"; /* list-element separator */
|
||||
-
|
||||
- /* Constants to be used in assignments only, not in comparisons... */
|
||||
|
||||
+#define ALL 2
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
-/* Only allow group entries of the form "(xyz)" */
|
||||
-static int only_new_group_syntax = NO;
|
||||
-
|
||||
/*
|
||||
* A structure to bundle up all login-related information to keep the
|
||||
* functional interfaces as generic as possible.
|
||||
@@ -100,12 +98,13 @@ struct login_info {
|
||||
const struct passwd *user;
|
||||
const char *from;
|
||||
const char *config_file;
|
||||
+ int debug; /* Print debugging messages. */
|
||||
+ int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
|
||||
+ int noaudit; /* Do not audit denials */
|
||||
+ const char *fs; /* field separator */
|
||||
+ const char *sep; /* list-element separator */
|
||||
};
|
||||
|
||||
-/* Print debugging messages.
|
||||
- Default is NO which means don't print debugging messages. */
|
||||
-static char pam_access_debug = NO;
|
||||
-
|
||||
/* Parse module config arguments */
|
||||
|
||||
static int
|
||||
@@ -113,17 +112,22 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
int argc, const char **argv)
|
||||
{
|
||||
int i;
|
||||
-
|
||||
+
|
||||
+ loginfo->noaudit = NO;
|
||||
+ loginfo->debug = NO;
|
||||
+ loginfo->only_new_group_syntax = NO;
|
||||
+ loginfo->fs = ":";
|
||||
+ loginfo->sep = ", \t";
|
||||
for (i=0; i<argc; ++i) {
|
||||
if (!strncmp("fieldsep=", argv[i], 9)) {
|
||||
|
||||
/* the admin wants to override the default field separators */
|
||||
- fs = argv[i]+9;
|
||||
+ loginfo->fs = argv[i]+9;
|
||||
|
||||
} else if (!strncmp("listsep=", argv[i], 8)) {
|
||||
|
||||
/* the admin wants to override the default list separators */
|
||||
- sep = argv[i]+8;
|
||||
+ loginfo->sep = argv[i]+8;
|
||||
|
||||
} else if (!strncmp("accessfile=", argv[i], 11)) {
|
||||
FILE *fp = fopen(11 + argv[i], "r");
|
||||
@@ -138,9 +142,11 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
}
|
||||
|
||||
} else if (strcmp (argv[i], "debug") == 0) {
|
||||
- pam_access_debug = YES;
|
||||
+ loginfo->debug = YES;
|
||||
} else if (strcmp (argv[i], "nodefgroup") == 0) {
|
||||
- only_new_group_syntax = YES;
|
||||
+ loginfo->only_new_group_syntax = YES;
|
||||
+ } else if (strcmp (argv[i], "noaudit") == 0) {
|
||||
+ loginfo->noaudit = YES;
|
||||
} else {
|
||||
pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
|
||||
}
|
||||
@@ -153,13 +159,13 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
|
||||
typedef int match_func (pam_handle_t *, char *, struct login_info *);
|
||||
|
||||
-static int list_match (pam_handle_t *, char *, struct login_info *,
|
||||
+static int list_match (pam_handle_t *, char *, char *, struct login_info *,
|
||||
match_func *);
|
||||
static int user_match (pam_handle_t *, char *, struct login_info *);
|
||||
-static int group_match (pam_handle_t *, const char *, const char *);
|
||||
+static int group_match (pam_handle_t *, const char *, const char *, int);
|
||||
static int from_match (pam_handle_t *, char *, struct login_info *);
|
||||
-static int string_match (pam_handle_t *, const char *, const char *);
|
||||
-static int network_netmask_match (pam_handle_t *, const char *, const char *);
|
||||
+static int string_match (pam_handle_t *, const char *, const char *, int);
|
||||
+static int network_netmask_match (pam_handle_t *, const char *, const char *, int);
|
||||
|
||||
|
||||
/* isipaddr - find out if string provided is an IP address or not */
|
||||
@@ -325,11 +331,12 @@ login_access (pam_handle_t *pamh, struct
|
||||
char *users; /* becomes list of login names */
|
||||
char *froms; /* becomes list of terminals or hosts */
|
||||
int match = NO;
|
||||
+ int nonall_match = NO;
|
||||
int end;
|
||||
int lineno = 0; /* for diagnostics */
|
||||
char *sptr;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"login_access: user=%s, from=%s, file=%s",
|
||||
item->user->pw_name,
|
||||
@@ -361,8 +368,8 @@ login_access (pam_handle_t *pamh, struct
|
||||
continue;
|
||||
|
||||
/* Allow field seperator in last field of froms */
|
||||
- if (!(perm = strtok_r(line, fs, &sptr))
|
||||
- || !(users = strtok_r(NULL, fs, &sptr))
|
||||
+ if (!(perm = strtok_r(line, item->fs, &sptr))
|
||||
+ || !(users = strtok_r(NULL, item->fs, &sptr))
|
||||
|| !(froms = strtok_r(NULL, "\n", &sptr))) {
|
||||
pam_syslog(pamh, LOG_ERR, "%s: line %d: bad field count",
|
||||
item->config_file, lineno);
|
||||
@@ -373,17 +380,22 @@ login_access (pam_handle_t *pamh, struct
|
||||
item->config_file, lineno);
|
||||
continue;
|
||||
}
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"line %d: %s : %s : %s", lineno, perm, users, froms);
|
||||
- match = list_match(pamh, froms, item, from_match);
|
||||
- if (pam_access_debug)
|
||||
- pam_syslog (pamh, LOG_DEBUG,
|
||||
- "from_match=%d, \"%s\"", match, item->from);
|
||||
- match = match && list_match (pamh, users, item, user_match);
|
||||
- if (pam_access_debug)
|
||||
+ match = list_match(pamh, users, NULL, item, user_match);
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG, "user_match=%d, \"%s\"",
|
||||
match, item->user->pw_name);
|
||||
+ if (match) {
|
||||
+ match = list_match(pamh, froms, NULL, item, from_match);
|
||||
+ if (!match && perm[0] == '+') {
|
||||
+ nonall_match = YES;
|
||||
+ }
|
||||
+ if (item->debug)
|
||||
+ pam_syslog (pamh, LOG_DEBUG,
|
||||
+ "from_match=%d, \"%s\"", match, item->from);
|
||||
+ }
|
||||
}
|
||||
(void) fclose(fp);
|
||||
} else if (errno == ENOENT) {
|
||||
@@ -394,20 +406,27 @@ login_access (pam_handle_t *pamh, struct
|
||||
pam_syslog(pamh, LOG_ERR, "cannot open %s: %m", item->config_file);
|
||||
return NO;
|
||||
}
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+ if (!item->noaudit && line[0] == '-' && (match == YES || (match == ALL &&
|
||||
+ nonall_match == YES))) {
|
||||
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_LOCATION,
|
||||
+ "pam_access", 0);
|
||||
+ }
|
||||
+#endif
|
||||
return (match == NO || (line[0] == '+'));
|
||||
}
|
||||
|
||||
|
||||
/* list_match - match an item against a list of tokens with exceptions */
|
||||
|
||||
-static int list_match(pam_handle_t *pamh,
|
||||
- char *list, struct login_info *item, match_func *match_fn)
|
||||
+static int
|
||||
+list_match(pam_handle_t *pamh, char *list, char *sptr,
|
||||
+ struct login_info *item, match_func *match_fn)
|
||||
{
|
||||
char *tok;
|
||||
int match = NO;
|
||||
- char *sptr;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug && list != NULL)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"list_match: list=%s, item=%s", list, item->user->pw_name);
|
||||
|
||||
@@ -418,8 +437,8 @@ static int list_match(pam_handle_t *pamh
|
||||
* the match is affected by any exceptions.
|
||||
*/
|
||||
|
||||
- for (tok = strtok_r(list, sep, &sptr); tok != 0;
|
||||
- tok = strtok_r(NULL, sep, &sptr)) {
|
||||
+ for (tok = strtok_r(list, item->sep, &sptr); tok != 0;
|
||||
+ tok = strtok_r(NULL, item->sep, &sptr)) {
|
||||
if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
|
||||
break;
|
||||
if ((match = (*match_fn) (pamh, tok, item))) /* YES */
|
||||
@@ -428,10 +447,12 @@ static int list_match(pam_handle_t *pamh
|
||||
/* Process exceptions to matches. */
|
||||
|
||||
if (match != NO) {
|
||||
- while ((tok = strtok_r(NULL, sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
|
||||
+ while ((tok = strtok_r(NULL, item->sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
|
||||
/* VOID */ ;
|
||||
- if (tok == 0 || list_match(pamh, sptr, item, match_fn) == NO)
|
||||
- return (match);
|
||||
+ if (tok == 0)
|
||||
+ return match;
|
||||
+ if (list_match(pamh, NULL, sptr, item, match_fn) == NO)
|
||||
+ return YES; /* drop special meaning of ALL */
|
||||
}
|
||||
return (NO);
|
||||
}
|
||||
@@ -453,7 +474,7 @@ static char *myhostname(void)
|
||||
|
||||
static int
|
||||
netgroup_match (pam_handle_t *pamh, const char *netgroup,
|
||||
- const char *machine, const char *user)
|
||||
+ const char *machine, const char *user, int debug)
|
||||
{
|
||||
char *mydomain = NULL;
|
||||
int retval;
|
||||
@@ -462,7 +483,7 @@ netgroup_match (pam_handle_t *pamh, cons
|
||||
|
||||
|
||||
retval = innetgr (netgroup, machine, user, mydomain);
|
||||
- if (pam_access_debug == YES)
|
||||
+ if (debug == YES)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"netgroup_match: %d (netgroup=%s, machine=%s, user=%s, domain=%s)",
|
||||
retval, netgroup ? netgroup : "NULL",
|
||||
@@ -480,8 +501,9 @@ user_match (pam_handle_t *pamh, char *to
|
||||
char *string = item->user->pw_name;
|
||||
struct login_info fake_item;
|
||||
char *at;
|
||||
+ int rv;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"user_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -500,12 +522,12 @@ user_match (pam_handle_t *pamh, char *to
|
||||
return (user_match (pamh, tok, item) &&
|
||||
from_match (pamh, at + 1, &fake_item));
|
||||
} else if (tok[0] == '@') /* netgroup */
|
||||
- return (netgroup_match (pamh, tok + 1, (char *) 0, string));
|
||||
+ return (netgroup_match (pamh, tok + 1, (char *) 0, string, item->debug));
|
||||
else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')')
|
||||
- return (group_match (pamh, tok, string));
|
||||
- else if (string_match (pamh, tok, string)) /* ALL or exact match */
|
||||
- return YES;
|
||||
- else if (only_new_group_syntax == NO &&
|
||||
+ return (group_match (pamh, tok, string, item->debug));
|
||||
+ else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
|
||||
+ return rv;
|
||||
+ else if (item->only_new_group_syntax == NO &&
|
||||
pam_modutil_user_in_group_nam_nam (pamh,
|
||||
item->user->pw_name, tok))
|
||||
/* try group membership */
|
||||
@@ -518,11 +540,12 @@ user_match (pam_handle_t *pamh, char *to
|
||||
/* group_match - match a username against token named group */
|
||||
|
||||
static int
|
||||
-group_match (pam_handle_t *pamh, const char *tok, const char* usr)
|
||||
+group_match (pam_handle_t *pamh, const char *tok, const char* usr,
|
||||
+ int debug)
|
||||
{
|
||||
char grptok[BUFSIZ];
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"group_match: grp=%s, user=%s", grptok, usr);
|
||||
|
||||
@@ -548,8 +571,9 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
const char *string = item->from;
|
||||
int tok_len;
|
||||
int str_len;
|
||||
+ int rv;
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (item->debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"from_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -565,10 +589,10 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
if (string == NULL) {
|
||||
return NO;
|
||||
} else if (tok[0] == '@') { /* netgroup */
|
||||
- return (netgroup_match (pamh, tok + 1, string, (char *) 0));
|
||||
- } else if (string_match(pamh, tok, string)) {
|
||||
+ return (netgroup_match (pamh, tok + 1, string, (char *) 0, item->debug));
|
||||
+ } else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) {
|
||||
/* ALL or exact match */
|
||||
- return (YES);
|
||||
+ return rv;
|
||||
} 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)
|
||||
@@ -614,7 +638,7 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
}
|
||||
} else if (isipaddr(string, NULL, NULL) == YES) {
|
||||
/* Assume network/netmask with a IP of a host. */
|
||||
- if (network_netmask_match(pamh, tok, string))
|
||||
+ if (network_netmask_match(pamh, tok, string, item->debug))
|
||||
return YES;
|
||||
} else {
|
||||
/* Assume network/netmask with a name of a host. */
|
||||
@@ -641,7 +665,7 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
: (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
|
||||
buf, sizeof (buf));
|
||||
|
||||
- if (network_netmask_match(pamh, tok, buf))
|
||||
+ if (network_netmask_match(pamh, tok, buf, item->debug))
|
||||
{
|
||||
freeaddrinfo (res);
|
||||
return YES;
|
||||
@@ -658,10 +682,11 @@ from_match (pam_handle_t *pamh UNUSED, c
|
||||
/* string_match - match a string against one token */
|
||||
|
||||
static int
|
||||
-string_match (pam_handle_t *pamh, const char *tok, const char *string)
|
||||
+string_match (pam_handle_t *pamh, const char *tok, const char *string,
|
||||
+ int debug)
|
||||
{
|
||||
|
||||
- if (pam_access_debug)
|
||||
+ if (debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"string_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -672,7 +697,7 @@ string_match (pam_handle_t *pamh, const
|
||||
*/
|
||||
|
||||
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
|
||||
- return (YES);
|
||||
+ return (ALL);
|
||||
} else if (string != NULL) {
|
||||
if (strcasecmp(tok, string) == 0) { /* try exact match */
|
||||
return (YES);
|
||||
@@ -690,9 +715,9 @@ string_match (pam_handle_t *pamh, const
|
||||
*/
|
||||
static int
|
||||
network_netmask_match (pam_handle_t *pamh,
|
||||
- const char *tok, const char *string)
|
||||
+ const char *tok, const char *string, int debug)
|
||||
{
|
||||
- if (pam_access_debug)
|
||||
+ if (debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"network_netmask_match: tok=%s, item=%s", tok, string);
|
||||
|
||||
@@ -771,6 +796,22 @@ pam_sm_authenticate (pam_handle_t *pamh,
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
+ if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
|
||||
+ return (PAM_USER_UNKNOWN);
|
||||
+
|
||||
+ /*
|
||||
+ * Bundle up the arguments to avoid unnecessary clumsiness later on.
|
||||
+ */
|
||||
+ loginfo.user = user_pw;
|
||||
+ loginfo.config_file = PAM_ACCESS_CONFIG;
|
||||
+
|
||||
+ /* parse the argument list */
|
||||
+
|
||||
+ if (!parse_args(pamh, &loginfo, argc, argv)) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
|
||||
+ return PAM_ABORT;
|
||||
+ }
|
||||
+
|
||||
/* remote host name */
|
||||
|
||||
if (pam_get_item(pamh, PAM_RHOST, &void_from)
|
||||
@@ -799,7 +840,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
|
||||
return PAM_ABORT;
|
||||
}
|
||||
from = void_from;
|
||||
- if (pam_access_debug)
|
||||
+ if (loginfo.debug)
|
||||
pam_syslog (pamh, LOG_DEBUG,
|
||||
"cannot determine tty or remote hostname, using service %s",
|
||||
from);
|
||||
@@ -817,22 +858,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
|
||||
}
|
||||
}
|
||||
|
||||
- if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
|
||||
- return (PAM_USER_UNKNOWN);
|
||||
-
|
||||
- /*
|
||||
- * Bundle up the arguments to avoid unnecessary clumsiness later on.
|
||||
- */
|
||||
- loginfo.user = user_pw;
|
||||
loginfo.from = from;
|
||||
- loginfo.config_file = PAM_ACCESS_CONFIG;
|
||||
-
|
||||
- /* parse the argument list */
|
||||
-
|
||||
- if (!parse_args(pamh, &loginfo, argc, argv)) {
|
||||
- pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
|
||||
- return PAM_ABORT;
|
||||
- }
|
||||
|
||||
if (login_access(pamh, &loginfo)) {
|
||||
return (PAM_SUCCESS);
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed 2006-06-16 08:35:16.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -22,9 +22,16 @@
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+#include <libaudit.h>
|
||||
+#endif
|
||||
+
|
||||
#define PAM_TIME_BUFLEN 1000
|
||||
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
|
||||
|
||||
+#define PAM_DEBUG_ARG 0x0001
|
||||
+#define PAM_NO_AUDIT 0x0002
|
||||
+
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
#endif
|
||||
@@ -46,6 +53,29 @@ typedef enum { AND, OR } operator;
|
||||
#include <security/_pam_macros.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_ext.h>
|
||||
+#include <security/pam_modutil.h>
|
||||
+
|
||||
+static int
|
||||
+_pam_parse (const pam_handle_t *pamh, int argc, const char **argv)
|
||||
+{
|
||||
+ int ctrl = 0;
|
||||
+
|
||||
+ /* step through arguments */
|
||||
+ for (; argc-- > 0; ++argv) {
|
||||
+
|
||||
+ /* generic options */
|
||||
+
|
||||
+ if (!strcmp(*argv, "debug")) {
|
||||
+ ctrl |= PAM_DEBUG_ARG;
|
||||
+ } else if (!strcmp(*argv, "noaudit")) {
|
||||
+ ctrl |= PAM_NO_AUDIT;
|
||||
+ } else {
|
||||
+ pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ctrl;
|
||||
+}
|
||||
|
||||
/* --- static functions for checking whether the user should be let in --- */
|
||||
|
||||
@@ -59,7 +89,7 @@ shift_bytes(char *mem, int from, int by)
|
||||
}
|
||||
|
||||
static int
|
||||
-read_field(pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
|
||||
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
|
||||
{
|
||||
/* is buf set ? */
|
||||
|
||||
@@ -137,6 +167,7 @@ read_field(pam_handle_t *pamh, int fd, c
|
||||
switch ((*buf)[i]) {
|
||||
int j,c;
|
||||
case '#':
|
||||
+ c = 0;
|
||||
for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
|
||||
if (j >= *to) {
|
||||
(*buf)[*to = ++i] = '\0';
|
||||
@@ -324,6 +355,13 @@ is_same(pam_handle_t *pamh UNUSED, const
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* Ok, we know that b is a substring from A and does not contain
|
||||
+ wildcards, but now the length of both strings must be the same,
|
||||
+ too. */
|
||||
+ if (strlen (a) != strlen(b))
|
||||
+ return FALSE;
|
||||
+
|
||||
return ( !len );
|
||||
}
|
||||
|
||||
@@ -559,11 +597,15 @@ check_account(pam_handle_t *pamh, const
|
||||
|
||||
PAM_EXTERN int
|
||||
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
|
||||
- int argc UNUSED, const char **argv UNUSED)
|
||||
+ int argc, const char **argv)
|
||||
{
|
||||
const void *service=NULL, *void_tty=NULL;
|
||||
const char *tty;
|
||||
const char *user=NULL;
|
||||
+ int ctrl;
|
||||
+ int rv;
|
||||
+
|
||||
+ ctrl = _pam_parse(pamh, argc, argv);
|
||||
|
||||
/* set service name */
|
||||
|
||||
@@ -612,7 +654,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
|
||||
D(("user=%s", user));
|
||||
D(("tty=%s", tty));
|
||||
|
||||
- return check_account(pamh, service, tty, user);
|
||||
+ rv = check_account(pamh, service, tty, user);
|
||||
+ if (rv != PAM_SUCCESS) {
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+ if (!(ctrl & PAM_NO_AUDIT)) {
|
||||
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_TIME,
|
||||
+ "pam_time", rv); /* ignore return value as we fail anyway */
|
||||
+ }
|
||||
+#endif
|
||||
+ if (ctrl & PAM_DEBUG_ARG) {
|
||||
+ pam_syslog(pamh, LOG_DEBUG, "user %s rejected", user);
|
||||
+ }
|
||||
+ }
|
||||
+ return rv;
|
||||
}
|
||||
|
||||
/* end of module definition */
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed 2006-06-22 21:44:30.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -22,6 +22,12 @@
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis id="pam_time-cmdsynopsis">
|
||||
<command>pam_time.so</command>
|
||||
+ <arg choice="opt">
|
||||
+ debug
|
||||
+ </arg>
|
||||
+ <arg choice="opt">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -41,11 +47,40 @@
|
||||
By default rules for time/port access are taken from config file
|
||||
<filename>/etc/security/time.conf</filename>.
|
||||
</para>
|
||||
+ <para>
|
||||
+ If Linux PAM is compiled with audit support the module will report
|
||||
+ when it denies access.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_time-options">
|
||||
<title>OPTIONS</title>
|
||||
- <para>This module does not recognice any options.</para>
|
||||
+ <variablelist>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>debug</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Some debug informations are printed with
|
||||
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>noaudit</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not report logins at disallowed time to the audit subsystem.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ </variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_time-services">
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed 2007-07-10 12:10:56.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c 2008-01-22 22:41:40.000000000 +0100
|
||||
@@ -41,6 +41,10 @@
|
||||
#include <pwd.h>
|
||||
#include <locale.h>
|
||||
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+#include <libaudit.h>
|
||||
+#endif
|
||||
+
|
||||
/* Module defines */
|
||||
#define LINE_LENGTH 1024
|
||||
|
||||
@@ -101,6 +105,7 @@ struct pam_limit_s {
|
||||
#define PAM_DEBUG_ARG 0x0001
|
||||
#define PAM_DO_SETREUID 0x0002
|
||||
#define PAM_UTMP_EARLY 0x0004
|
||||
+#define PAM_NO_AUDIT 0x0008
|
||||
|
||||
/* Limits from globbed files. */
|
||||
#define LIMITS_CONF_GLOB LIMITS_FILE_DIR
|
||||
@@ -126,6 +131,8 @@ _pam_parse (const pam_handle_t *pamh, in
|
||||
ctrl |= PAM_DO_SETREUID;
|
||||
} else if (!strcmp(*argv,"utmp_early")) {
|
||||
ctrl |= PAM_UTMP_EARLY;
|
||||
+ } else if (!strcmp(*argv,"noaudit")) {
|
||||
+ ctrl |= PAM_NO_AUDIT;
|
||||
} else {
|
||||
pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
|
||||
}
|
||||
@@ -599,6 +606,13 @@ static int setup_limits(pam_handle_t *pa
|
||||
D(("skip login limit check for uid=0"));
|
||||
} else if (pl->login_limit > 0) {
|
||||
if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
|
||||
+#ifdef HAVE_LIBAUDIT
|
||||
+ if (!(ctrl & PAM_NO_AUDIT)) {
|
||||
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_SESSIONS,
|
||||
+ "pam_limits", PAM_PERM_DENIED);
|
||||
+ /* ignore return value as we fail anyway */
|
||||
+ }
|
||||
+#endif
|
||||
retval |= LOGIN_ERR;
|
||||
}
|
||||
} else if (pl->login_limit == 0) {
|
||||
diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml
|
||||
--- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed 2007-04-30 12:47:26.000000000 +0200
|
||||
+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml 2008-01-22 22:24:05.000000000 +0100
|
||||
@@ -34,6 +34,9 @@
|
||||
<arg choice="opt">
|
||||
utmp_early
|
||||
</arg>
|
||||
+ <arg choice="opt">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -57,6 +60,11 @@
|
||||
<para>
|
||||
The module must not be called by a multithreaded application.
|
||||
</para>
|
||||
+ <para>
|
||||
+ If Linux PAM is compiled with audit support the module will report
|
||||
+ when it denies access based on limit of maximum number of concurrent
|
||||
+ login sessions.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_limits-options">
|
||||
@@ -111,6 +119,16 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>noaudit</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not report exceeded maximum logins count to the audit subsystem.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
68
pam.spec
68
pam.spec
@ -11,7 +11,7 @@
|
||||
Summary: A security tool which provides authentication for applications
|
||||
Name: pam
|
||||
Version: 0.99.8.1
|
||||
Release: 15%{?dist}
|
||||
Release: 16%{?dist}
|
||||
# The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant
|
||||
# as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+,
|
||||
# pam_rhosts_auth module is BSD with advertising
|
||||
@ -46,6 +46,7 @@ Patch47: pam-0.99.8.1-xauth-no-free.patch
|
||||
Patch48: pam-0.99.8.1-substack.patch
|
||||
Patch49: pam-0.99.8.1-tty-audit.patch
|
||||
Patch50: pam-0.99.8.1-tty-audit2.patch
|
||||
Patch51: pam-0.99.8.1-audit-failed.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
Requires: cracklib, cracklib-dicts >= 2.8
|
||||
@ -117,6 +118,7 @@ popd
|
||||
%patch48 -p0 -b .substack
|
||||
%patch49 -p1 -b .tty-audit
|
||||
%patch50 -p1 -b .tty-audit2
|
||||
%patch51 -p1 -b .audit-failed
|
||||
|
||||
autoreconf
|
||||
|
||||
@ -158,6 +160,7 @@ LDFLAGS=-L${topdir}/%{_lib} ; export LDFLAGS
|
||||
--enable-isadir=../../%{_lib}/security \
|
||||
--with-db-uniquename=_pam
|
||||
make
|
||||
# we do not use _smp_mflags because the build of sources in yacc/flex fails
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
@ -188,35 +191,6 @@ install -m 600 /dev/null $RPM_BUILD_ROOT/var/log/tallylog
|
||||
# Install man pages.
|
||||
install -m 644 %{SOURCE9} %{SOURCE10} $RPM_BUILD_ROOT%{_mandir}/man5/
|
||||
|
||||
# Make sure every module subdirectory gave us a module. Yes, this is hackish.
|
||||
for dir in modules/pam_* ; do
|
||||
if [ -d ${dir} ] ; then
|
||||
if ! ls -1 $RPM_BUILD_ROOT/%{_lib}/security/`basename ${dir}`*.so ; then
|
||||
echo ERROR `basename ${dir}` did not build a module.
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for module problems. Specifically, check that every module we just
|
||||
# installed can actually be loaded by a minimal PAM-aware application.
|
||||
/sbin/ldconfig -n $RPM_BUILD_ROOT/%{_lib}
|
||||
for module in $RPM_BUILD_ROOT/%{_lib}/security/pam*.so ; do
|
||||
if ! env LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_lib} \
|
||||
%{SOURCE8} -ldl -lpam -L$RPM_BUILD_ROOT/%{_lib} ${module} ; then
|
||||
echo ERROR module: ${module} cannot be loaded.
|
||||
exit 1
|
||||
fi
|
||||
# And for good measure, make sure that none of the modules pull in threading
|
||||
# libraries, which if loaded in a non-threaded application, can cause Very
|
||||
# Bad Things to happen.
|
||||
if env LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_lib} \
|
||||
LD_PRELOAD=$RPM_BUILD_ROOT/%{_lib}/libpam.so ldd -r ${module} | fgrep -q libpthread ; then
|
||||
echo ERROR module: ${module} pulls threading libraries.
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for phase in auth acct passwd session ; do
|
||||
ln -sf pam_unix.so $RPM_BUILD_ROOT/%{_lib}/security/pam_unix_${phase}.so
|
||||
done
|
||||
@ -241,6 +215,36 @@ install -m755 -d $RPM_BUILD_ROOT/lib/security
|
||||
|
||||
%find_lang Linux-PAM
|
||||
|
||||
%check
|
||||
# Make sure every module subdirectory gave us a module. Yes, this is hackish.
|
||||
for dir in modules/pam_* ; do
|
||||
if [ -d ${dir} ] ; then
|
||||
if ! ls -1 $RPM_BUILD_ROOT/%{_lib}/security/`basename ${dir}`*.so ; then
|
||||
echo ERROR `basename ${dir}` did not build a module.
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for module problems. Specifically, check that every module we just
|
||||
# installed can actually be loaded by a minimal PAM-aware application.
|
||||
/sbin/ldconfig -n $RPM_BUILD_ROOT/%{_lib}
|
||||
for module in $RPM_BUILD_ROOT/%{_lib}/security/pam*.so ; do
|
||||
if ! env LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_lib} \
|
||||
%{SOURCE8} -ldl -lpam -L$RPM_BUILD_ROOT/%{_lib} ${module} ; then
|
||||
echo ERROR module: ${module} cannot be loaded.
|
||||
exit 1
|
||||
fi
|
||||
# And for good measure, make sure that none of the modules pull in threading
|
||||
# libraries, which if loaded in a non-threaded application, can cause Very
|
||||
# Bad Things to happen.
|
||||
if env LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_lib} \
|
||||
LD_PRELOAD=$RPM_BUILD_ROOT%{_libdir}/libpam.so ldd -r ${module} | fgrep -q libpthread ; then
|
||||
echo ERROR module: ${module} pulls threading libraries.
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
@ -364,6 +368,10 @@ fi
|
||||
%doc doc/adg/*.txt doc/adg/html
|
||||
|
||||
%changelog
|
||||
* Tue Jan 22 2008 Tomas Mraz <tmraz@redhat.com> 0.99.8.1-16
|
||||
- add auditing to pam_access, pam_limits, and pam_time
|
||||
- moved sanity testing code to check script
|
||||
|
||||
* Mon Jan 14 2008 Tomas Mraz <tmraz@redhat.com> 0.99.8.1-15
|
||||
- merge review fixes (#226228)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user