commit
fc55f81471
@ -0,0 +1,595 @@
|
|||||||
|
diff -up Linux-PAM-1.3.1/libpam/pam_handlers.c.libpam-support-long-lines Linux-PAM-1.3.1/libpam/pam_handlers.c
|
||||||
|
--- Linux-PAM-1.3.1/libpam/pam_handlers.c.libpam-support-long-lines 2024-11-04 13:17:27.395991844 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/libpam/pam_handlers.c 2024-11-04 14:45:22.583441849 +0100
|
||||||
|
@@ -16,21 +16,30 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
-#define BUF_SIZE 1024
|
||||||
|
#define MODULE_CHUNK 4
|
||||||
|
#define UNKNOWN_MODULE "<*unknown module*>"
|
||||||
|
#ifndef _PAM_ISA
|
||||||
|
#define _PAM_ISA "."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
|
||||||
|
+struct line_buffer {
|
||||||
|
+ char *assembled;
|
||||||
|
+ char *chunk;
|
||||||
|
+ size_t chunk_size;
|
||||||
|
+ size_t len;
|
||||||
|
+ size_t size;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static void _pam_buffer_init(struct line_buffer *buffer);
|
||||||
|
+
|
||||||
|
+static int _pam_assemble_line(FILE *f, struct line_buffer *buf);
|
||||||
|
|
||||||
|
static void _pam_free_handlers_aux(struct handler **hp);
|
||||||
|
|
||||||
|
static int _pam_add_handler(pam_handle_t *pamh
|
||||||
|
, int must_fail, int other, int stack_level, int type
|
||||||
|
, int *actions, const char *mod_path
|
||||||
|
- , int argc, char **argv, int argvlen);
|
||||||
|
+ , int argc, char **argv, size_t argvlen);
|
||||||
|
|
||||||
|
/* Values for module type */
|
||||||
|
|
||||||
|
@@ -58,12 +67,15 @@ static int _pam_parse_conf_file(pam_hand
|
||||||
|
#endif /* PAM_READ_BOTH_CONFS */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
- char buf[BUF_SIZE];
|
||||||
|
+ struct line_buffer buffer;
|
||||||
|
int x; /* read a line from the FILE *f ? */
|
||||||
|
+
|
||||||
|
+ _pam_buffer_init(&buffer);
|
||||||
|
/*
|
||||||
|
* read a line from the configuration (FILE *) f
|
||||||
|
*/
|
||||||
|
- while ((x = _pam_assemble_line(f, buf, BUF_SIZE)) > 0) {
|
||||||
|
+ while ((x = _pam_assemble_line(f, &buffer)) > 0) {
|
||||||
|
+ char *buf = buffer.assembled;
|
||||||
|
char *tok, *nexttok=NULL;
|
||||||
|
const char *this_service;
|
||||||
|
const char *mod_path;
|
||||||
|
@@ -73,7 +85,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||||
|
int handler_type = PAM_HT_MODULE; /* regular handler from a module */
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
- int argvlen;
|
||||||
|
+ size_t argvlen;
|
||||||
|
|
||||||
|
D(("_pam_init_handler: LINE: %s", buf));
|
||||||
|
if (known_service != NULL) {
|
||||||
|
@@ -232,10 +244,11 @@ static int _pam_parse_conf_file(pam_hand
|
||||||
|
if (nexttok != NULL) {
|
||||||
|
D(("list: %s",nexttok));
|
||||||
|
argvlen = _pam_mkargv(nexttok, &argv, &argc);
|
||||||
|
- D(("argvlen = %d",argvlen));
|
||||||
|
+ D(("argvlen = %zu",argvlen));
|
||||||
|
} else { /* there are no arguments so fix by hand */
|
||||||
|
D(("_pam_init_handlers: empty argument list"));
|
||||||
|
- argvlen = argc = 0;
|
||||||
|
+ argvlen = 0;
|
||||||
|
+ argc = 0;
|
||||||
|
argv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -548,88 +561,243 @@ int _pam_init_handlers(pam_handle_t *pam
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int _pam_buffer_add(struct line_buffer *buffer, char *start, char *end)
|
||||||
|
+{
|
||||||
|
+ size_t len = end - start;
|
||||||
|
+
|
||||||
|
+ D(("assembled: [%zu/%zu] '%s', adding [%zu] '%s'",
|
||||||
|
+ buffer->len, buffer->size,
|
||||||
|
+ buffer->assembled == NULL ? "" : buffer->assembled, len, start));
|
||||||
|
+
|
||||||
|
+ if (start == end)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (buffer->assembled == NULL && buffer->chunk == start) {
|
||||||
|
+ /* no extra allocation needed, just move chunk to assembled */
|
||||||
|
+ buffer->assembled = buffer->chunk;
|
||||||
|
+ buffer->len = len;
|
||||||
|
+ buffer->size = buffer->chunk_size;
|
||||||
|
+
|
||||||
|
+ buffer->chunk = NULL;
|
||||||
|
+ buffer->chunk_size = 0;
|
||||||
|
+
|
||||||
|
+ D(("exiting with quick exchange"));
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (buffer->len + len + 1 > buffer->size) {
|
||||||
|
+ size_t size;
|
||||||
|
+ char *p;
|
||||||
|
+
|
||||||
|
+ size = buffer->len + len + 1;
|
||||||
|
+ if ((p = realloc(buffer->assembled, size)) == NULL)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ buffer->assembled = p;
|
||||||
|
+ buffer->size = size;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(buffer->assembled + buffer->len, start, len);
|
||||||
|
+ buffer->len += len;
|
||||||
|
+ buffer->assembled[buffer->len] = '\0';
|
||||||
|
+
|
||||||
|
+ D(("exiting"));
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int _pam_buffer_add_eol(struct line_buffer *buffer,
|
||||||
|
+ char *start, char *end)
|
||||||
|
+{
|
||||||
|
+ if (buffer->assembled != NULL || (*start != '\0' && *start != '\n'))
|
||||||
|
+ return _pam_buffer_add(buffer, start, end);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _pam_buffer_clear(struct line_buffer *buffer)
|
||||||
|
+{
|
||||||
|
+ _pam_drop(buffer->assembled);
|
||||||
|
+ _pam_drop(buffer->chunk);
|
||||||
|
+ buffer->chunk_size = 0;
|
||||||
|
+ buffer->len = 0;
|
||||||
|
+ buffer->size = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _pam_buffer_init(struct line_buffer *buffer)
|
||||||
|
+{
|
||||||
|
+ buffer->assembled = NULL;
|
||||||
|
+ buffer->chunk = NULL;
|
||||||
|
+ _pam_buffer_clear(buffer);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _pam_buffer_purge(struct line_buffer *buffer)
|
||||||
|
+{
|
||||||
|
+ _pam_drop(buffer->chunk);
|
||||||
|
+ buffer->chunk_size = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _pam_buffer_shift(struct line_buffer *buffer)
|
||||||
|
+{
|
||||||
|
+ if (buffer->assembled == NULL)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ _pam_buffer_purge(buffer);
|
||||||
|
+ buffer->chunk = buffer->assembled;
|
||||||
|
+ buffer->chunk_size = buffer->size;
|
||||||
|
+
|
||||||
|
+ buffer->assembled = NULL;
|
||||||
|
+ buffer->size = 0;
|
||||||
|
+ buffer->len = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int _pam_buffer_valid(struct line_buffer *buffer)
|
||||||
|
+{
|
||||||
|
+ return buffer->assembled != NULL && *buffer->assembled != '\0';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
- * This is where we read a line of the PAM config file. The line may be
|
||||||
|
- * preceeded by lines of comments and also extended with "\\\n"
|
||||||
|
+ * Trim string to relevant parts of a configuration line.
|
||||||
|
+ *
|
||||||
|
+ * Preceding whitespaces are skipped and comment (#) marks the end of
|
||||||
|
+ * configuration line.
|
||||||
|
+ *
|
||||||
|
+ * Returns start of configuration line.
|
||||||
|
*/
|
||||||
|
+static inline char *_pam_str_trim(char *str)
|
||||||
|
+{
|
||||||
|
+ /* skip leading spaces */
|
||||||
|
+ str += strspn(str, " \t");
|
||||||
|
+ /*
|
||||||
|
+ * we are only interested in characters before the first '#'
|
||||||
|
+ * character
|
||||||
|
+ */
|
||||||
|
+ str[strcspn(str, "#")] = '\0';
|
||||||
|
|
||||||
|
-static int _pam_assemble_line(FILE *f, char *buffer, int buf_len)
|
||||||
|
+ return str;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Remove escaped newline from end of string.
|
||||||
|
+ *
|
||||||
|
+ * Configuration lines may span across multiple lines in a file
|
||||||
|
+ * by ending a line with a backslash (\).
|
||||||
|
+ *
|
||||||
|
+ * If an escaped newline is encountered, the backslash will be
|
||||||
|
+ * replaced with a blank ' ' and the newline itself removed.
|
||||||
|
+ * Then the variable "end" will point to the new end of line.
|
||||||
|
+ *
|
||||||
|
+ * Returns 0 if escaped newline was found and replaced, 1 otherwise.
|
||||||
|
+ */
|
||||||
|
+static inline int _pam_str_unescnl(char *start, char **end)
|
||||||
|
{
|
||||||
|
- char *p = buffer;
|
||||||
|
- char *endp = buffer + buf_len;
|
||||||
|
- char *s, *os;
|
||||||
|
- int used = 0;
|
||||||
|
+ int ret = 1;
|
||||||
|
+ char *p = *end;
|
||||||
|
|
||||||
|
- /* loop broken with a 'break' when a non-'\\n' ended line is read */
|
||||||
|
+ /*
|
||||||
|
+ * Check for backslash by scanning back from the end of
|
||||||
|
+ * the entered line, the '\n' should be included since
|
||||||
|
+ * normally a line is terminated with this character.
|
||||||
|
+ */
|
||||||
|
+ while (p > start && ((*--p == ' ') || (*p == '\t') || (*p == '\n')))
|
||||||
|
+ ;
|
||||||
|
+ if (*p == '\\') {
|
||||||
|
+ *p++ = ' '; /* replace backslash with ' ' */
|
||||||
|
+ *p = '\0'; /* truncate the line here */
|
||||||
|
+ *end = p;
|
||||||
|
+ ret = 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- D(("called."));
|
||||||
|
- for (;;) {
|
||||||
|
- if (p >= endp) {
|
||||||
|
- /* Overflow */
|
||||||
|
- D(("_pam_assemble_line: overflow"));
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
- if (fgets(p, endp - p, f) == NULL) {
|
||||||
|
- if (used) {
|
||||||
|
- /* Incomplete read */
|
||||||
|
- return -1;
|
||||||
|
- } else {
|
||||||
|
- /* EOF */
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- /* skip leading spaces --- line may be blank */
|
||||||
|
+/*
|
||||||
|
+ * Prepare line from file for configuration line parsing.
|
||||||
|
+ *
|
||||||
|
+ * A configuration line may span across multiple lines in a file.
|
||||||
|
+ * Remove comments and skip preceding whitespaces.
|
||||||
|
+ *
|
||||||
|
+ * Returns 0 if line spans across multiple lines, 1 if
|
||||||
|
+ * end of line is encountered.
|
||||||
|
+ */
|
||||||
|
+static inline int _pam_str_prepare(char *line, ssize_t len,
|
||||||
|
+ char **start, char **end)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
- s = p + strspn(p, " \n\t");
|
||||||
|
- if (*s && (*s != '#')) {
|
||||||
|
- os = s;
|
||||||
|
+ *start = line;
|
||||||
|
+ *end = line + len;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * we are only interested in characters before the first '#'
|
||||||
|
- * character
|
||||||
|
- */
|
||||||
|
+ ret = _pam_str_unescnl(*start, end) || strchr(*start, '#') != NULL;
|
||||||
|
|
||||||
|
- while (*s && *s != '#')
|
||||||
|
- ++s;
|
||||||
|
- if (*s == '#') {
|
||||||
|
- *s = '\0';
|
||||||
|
- used += strlen(os);
|
||||||
|
- break; /* the line has been read */
|
||||||
|
- }
|
||||||
|
+ *start = _pam_str_trim(*start);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * This is where we read a line of the PAM config file. The line may be
|
||||||
|
+ * preceded by lines of comments and also extended with "\\\n"
|
||||||
|
+ *
|
||||||
|
+ * Returns 0 on EOF, 1 on successful line parsing, or -1 on error.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static int _pam_assemble_line(FILE *f, struct line_buffer *buffer)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ /* loop broken with a 'break' when a non-'\\n' ended line is read */
|
||||||
|
|
||||||
|
- s = os;
|
||||||
|
+ D(("called."));
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Check for backslash by scanning back from the end of
|
||||||
|
- * the entered line, the '\n' has been included since
|
||||||
|
- * normally a line is terminated with this
|
||||||
|
- * character. fgets() should only return one though!
|
||||||
|
- */
|
||||||
|
+ _pam_buffer_shift(buffer);
|
||||||
|
|
||||||
|
- s += strlen(s);
|
||||||
|
- while (s > os && ((*--s == ' ') || (*s == '\t')
|
||||||
|
- || (*s == '\n')));
|
||||||
|
+ for (;;) {
|
||||||
|
+ char *start, *end;
|
||||||
|
+ ssize_t n;
|
||||||
|
+ int eol;
|
||||||
|
|
||||||
|
- /* check if it ends with a backslash */
|
||||||
|
- if (*s == '\\') {
|
||||||
|
- *s++ = ' '; /* replace backslash with ' ' */
|
||||||
|
- *s = '\0'; /* truncate the line here */
|
||||||
|
- used += strlen(os);
|
||||||
|
- p = s; /* there is more ... */
|
||||||
|
+ if ((n = getline(&buffer->chunk, &buffer->chunk_size, f)) == -1) {
|
||||||
|
+ if (ret) {
|
||||||
|
+ /* Incomplete read */
|
||||||
|
+ ret = -1;
|
||||||
|
} else {
|
||||||
|
- /* End of the line! */
|
||||||
|
- used += strlen(os);
|
||||||
|
- break; /* this is the complete line */
|
||||||
|
+ /* EOF */
|
||||||
|
+ ret = 0;
|
||||||
|
}
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ eol = _pam_str_prepare(buffer->chunk, n, &start, &end);
|
||||||
|
|
||||||
|
+ if (eol) {
|
||||||
|
+ if (_pam_buffer_add_eol(buffer, start, end)) {
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (_pam_buffer_valid(buffer)) {
|
||||||
|
+ /* Successfully parsed a line */
|
||||||
|
+ ret = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* Start parsing next line */
|
||||||
|
+ _pam_buffer_shift(buffer);
|
||||||
|
+ ret = 0;
|
||||||
|
} else {
|
||||||
|
- /* Nothing in this line */
|
||||||
|
- /* Don't move p */
|
||||||
|
+ /* Configuration line spans across multiple lines in file */
|
||||||
|
+ if (_pam_buffer_add(buffer, start, end)) {
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* Keep parsing line */
|
||||||
|
+ ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- return used;
|
||||||
|
+ if (ret == 1)
|
||||||
|
+ _pam_buffer_purge(buffer);
|
||||||
|
+ else
|
||||||
|
+ _pam_buffer_clear(buffer);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
@@ -761,7 +929,7 @@ _pam_load_module(pam_handle_t *pamh, con
|
||||||
|
int _pam_add_handler(pam_handle_t *pamh
|
||||||
|
, int handler_type, int other, int stack_level, int type
|
||||||
|
, int *actions, const char *mod_path
|
||||||
|
- , int argc, char **argv, int argvlen)
|
||||||
|
+ , int argc, char **argv, size_t argvlen)
|
||||||
|
{
|
||||||
|
struct loaded_module *mod = NULL;
|
||||||
|
struct handler **handler_p;
|
||||||
|
diff -up Linux-PAM-1.3.1/libpam/pam_misc.c.libpam-support-long-lines Linux-PAM-1.3.1/libpam/pam_misc.c
|
||||||
|
--- Linux-PAM-1.3.1/libpam/pam_misc.c.libpam-support-long-lines 2017-02-10 11:10:15.000000000 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/libpam/pam_misc.c 2024-11-04 14:47:31.147672755 +0100
|
||||||
|
@@ -39,6 +39,8 @@
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
@@ -163,60 +165,55 @@ char *_pam_memdup(const char *x, int len
|
||||||
|
/* Generate argv, argc from s */
|
||||||
|
/* caller must free(argv) */
|
||||||
|
|
||||||
|
-int _pam_mkargv(char *s, char ***argv, int *argc)
|
||||||
|
+size_t _pam_mkargv(const char *s, char ***argv, int *argc)
|
||||||
|
{
|
||||||
|
- int l;
|
||||||
|
- int argvlen = 0;
|
||||||
|
- char *sbuf, *sbuf_start;
|
||||||
|
+ size_t l;
|
||||||
|
+ size_t argvlen = 0;
|
||||||
|
char **our_argv = NULL;
|
||||||
|
- char **argvbuf;
|
||||||
|
- char *argvbufp;
|
||||||
|
-#ifdef PAM_DEBUG
|
||||||
|
- int count=0;
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
- D(("_pam_mkargv called: %s",s));
|
||||||
|
+ D(("called: %s",s));
|
||||||
|
|
||||||
|
*argc = 0;
|
||||||
|
|
||||||
|
l = strlen(s);
|
||||||
|
- if (l) {
|
||||||
|
- if ((sbuf = sbuf_start = _pam_strdup(s)) == NULL) {
|
||||||
|
- pam_syslog(NULL, LOG_CRIT,
|
||||||
|
- "pam_mkargv: null returned by _pam_strdup");
|
||||||
|
- D(("arg NULL"));
|
||||||
|
+ if (l && l < SIZE_MAX / (sizeof(char) + sizeof(char *))) {
|
||||||
|
+ char **argvbuf;
|
||||||
|
+ /* Overkill on the malloc, but not large */
|
||||||
|
+ argvlen = (l + 1) * (sizeof(char) + sizeof(char *));
|
||||||
|
+ if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
|
||||||
|
+ pam_syslog(NULL, LOG_CRIT, "pam_mkargv: null returned by malloc");
|
||||||
|
+ argvlen = 0;
|
||||||
|
} else {
|
||||||
|
- /* Overkill on the malloc, but not large */
|
||||||
|
- argvlen = (l + 1) * ((sizeof(char)) + sizeof(char *));
|
||||||
|
- if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
|
||||||
|
- pam_syslog(NULL, LOG_CRIT,
|
||||||
|
- "pam_mkargv: null returned by malloc");
|
||||||
|
- } else {
|
||||||
|
- char *tmp=NULL;
|
||||||
|
-
|
||||||
|
- argvbufp = (char *) argvbuf + (l * sizeof(char *));
|
||||||
|
- D(("[%s]",sbuf));
|
||||||
|
- while ((sbuf = _pam_StrTok(sbuf, " \n\t", &tmp))) {
|
||||||
|
- D(("arg #%d",++count));
|
||||||
|
- D(("->[%s]",sbuf));
|
||||||
|
- strcpy(argvbufp, sbuf);
|
||||||
|
- D(("copied token"));
|
||||||
|
- *argvbuf = argvbufp;
|
||||||
|
- argvbufp += strlen(argvbufp) + 1;
|
||||||
|
- D(("stepped in argvbufp"));
|
||||||
|
- (*argc)++;
|
||||||
|
- argvbuf++;
|
||||||
|
- sbuf = NULL;
|
||||||
|
- D(("loop again?"));
|
||||||
|
+ char *argvbufp;
|
||||||
|
+ char *tmp=NULL;
|
||||||
|
+ char *tok;
|
||||||
|
+#ifdef PAM_DEBUG
|
||||||
|
+ unsigned count=0;
|
||||||
|
+#endif
|
||||||
|
+ argvbufp = (char *) argvbuf + (l * sizeof(char *));
|
||||||
|
+ strcpy(argvbufp, s);
|
||||||
|
+ D(("[%s]",argvbufp));
|
||||||
|
+ while ((tok = _pam_StrTok(argvbufp, " \n\t", &tmp))) {
|
||||||
|
+ D(("arg #%u",++count));
|
||||||
|
+ D(("->[%s]",tok));
|
||||||
|
+ *argvbuf++ = tok;
|
||||||
|
+ if (*argc == INT_MAX) {
|
||||||
|
+ pam_syslog(NULL, LOG_CRIT,
|
||||||
|
+ "pam_mkargv: too many arguments");
|
||||||
|
+ argvlen = 0;
|
||||||
|
+ _pam_drop(our_argv);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
+ (*argc)++;
|
||||||
|
+ argvbufp = NULL;
|
||||||
|
+ D(("loop again?"));
|
||||||
|
}
|
||||||
|
- _pam_drop(sbuf_start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*argv = our_argv;
|
||||||
|
|
||||||
|
- D(("_pam_mkargv returned"));
|
||||||
|
+ D(("exiting"));
|
||||||
|
|
||||||
|
return(argvlen);
|
||||||
|
}
|
||||||
|
diff -up Linux-PAM-1.3.1/libpam/pam_private.h.libpam-support-long-lines Linux-PAM-1.3.1/libpam/pam_private.h
|
||||||
|
--- Linux-PAM-1.3.1/libpam/pam_private.h.libpam-support-long-lines 2024-11-04 13:17:27.404991868 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/libpam/pam_private.h 2024-11-04 14:51:31.654635328 +0100
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
+#include <stddef.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <security/pam_appl.h>
|
||||||
|
@@ -266,7 +267,7 @@ char *_pam_strdup(const char *s);
|
||||||
|
|
||||||
|
char *_pam_memdup(const char *s, int len);
|
||||||
|
|
||||||
|
-int _pam_mkargv(char *s, char ***argv, int *argc);
|
||||||
|
+size_t _pam_mkargv(const char *s, char ***argv, int *argc);
|
||||||
|
|
||||||
|
void _pam_sanitize(pam_handle_t *pamh);
|
||||||
|
|
||||||
|
diff -up Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c
|
||||||
|
--- Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines 2017-02-10 11:10:15.000000000 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c 2024-11-04 13:17:27.434991946 +0100
|
||||||
|
@@ -408,7 +408,7 @@ call_exec (const char *pam_type, pam_han
|
||||||
|
_exit (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
- arggv = calloc (argc + 4, sizeof (char *));
|
||||||
|
+ arggv = calloc ((size_t) argc + 1, sizeof (char *));
|
||||||
|
if (arggv == NULL)
|
||||||
|
_exit (ENOMEM);
|
||||||
|
|
||||||
|
diff -up Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c
|
||||||
|
--- Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines 2017-02-10 11:10:15.000000000 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c 2024-11-04 13:17:27.434991946 +0100
|
||||||
|
@@ -101,7 +101,8 @@ static int process_args(pam_handle_t *pa
|
||||||
|
char **levp;
|
||||||
|
const char *user = NULL;
|
||||||
|
const void *tmp;
|
||||||
|
- int i,size, retval;
|
||||||
|
+ int i, retval;
|
||||||
|
+ size_t size;
|
||||||
|
|
||||||
|
*filtername = *++argv;
|
||||||
|
if (ctrl & FILTER_DEBUG) {
|
||||||
|
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c
|
||||||
|
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines 2024-11-04 13:17:27.423991918 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c 2024-11-04 13:17:27.434991946 +0100
|
||||||
|
@@ -83,14 +83,14 @@ static void try_to_display_fd(pam_handle
|
||||||
|
* Returns 0 in case of error, 1 in case of success.
|
||||||
|
*/
|
||||||
|
static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
|
||||||
|
- char ***out_arg_split, unsigned int *out_num_strs)
|
||||||
|
+ char ***out_arg_split, size_t *out_num_strs)
|
||||||
|
{
|
||||||
|
char *arg_extracted = NULL;
|
||||||
|
const char *arg_ptr = arg;
|
||||||
|
char **arg_split = NULL;
|
||||||
|
char delim_str[2];
|
||||||
|
- unsigned int i = 0;
|
||||||
|
- unsigned int num_strs = 0;
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ size_t num_strs = 0;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
delim_str[0] = delim;
|
||||||
|
@@ -184,13 +184,13 @@ static int filter_dirents(const struct d
|
||||||
|
}
|
||||||
|
|
||||||
|
static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||||
|
- char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing)
|
||||||
|
+ char **motd_dir_path_split, size_t num_motd_dirs, int report_missing)
|
||||||
|
{
|
||||||
|
struct dirent ***dirscans = NULL;
|
||||||
|
unsigned int *dirscans_sizes = NULL;
|
||||||
|
unsigned int dirscans_size_total = 0;
|
||||||
|
char **dirnames_all = NULL;
|
||||||
|
- unsigned int i;
|
||||||
|
+ size_t i;
|
||||||
|
int i_dirnames = 0;
|
||||||
|
|
||||||
|
if (pamh == NULL || motd_dir_path_split == NULL) {
|
||||||
|
@@ -302,11 +302,11 @@ int pam_sm_open_session(pam_handle_t *pa
|
||||||
|
int retval = PAM_IGNORE;
|
||||||
|
const char *motd_path = NULL;
|
||||||
|
char *motd_path_copy = NULL;
|
||||||
|
- unsigned int num_motd_paths = 0;
|
||||||
|
+ size_t num_motd_paths = 0;
|
||||||
|
char **motd_path_split = NULL;
|
||||||
|
const char *motd_dir_path = NULL;
|
||||||
|
char *motd_dir_path_copy = NULL;
|
||||||
|
- unsigned int num_motd_dir_paths = 0;
|
||||||
|
+ size_t num_motd_dir_paths = 0;
|
||||||
|
char **motd_dir_path_split = NULL;
|
||||||
|
int report_missing;
|
||||||
|
|
@ -0,0 +1,215 @@
|
|||||||
|
From 08992030c56c940c0707ccbc442b1c325aa01e6d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tomas Mraz <tmraz@fedoraproject.org>
|
||||||
|
Date: Tue, 6 Apr 2021 12:27:38 +0200
|
||||||
|
Subject: [PATCH] pam_access: clean up the remote host matching code
|
||||||
|
|
||||||
|
* modules/pam_access/pam_access.c (from_match): Split out remote_match()
|
||||||
|
function and avoid calling it when matching against LOCAL keyword.
|
||||||
|
There is also no point in doing domain match against TTY or SERVICE.
|
||||||
|
---
|
||||||
|
modules/pam_access/pam_access.c | 44 +++++++++++++++++++++------------
|
||||||
|
1 file changed, 28 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
|
||||||
|
index 98848c54..277192b9 100644
|
||||||
|
--- a/modules/pam_access/pam_access.c
|
||||||
|
+++ b/modules/pam_access/pam_access.c
|
||||||
|
@@ -160,6 +160,7 @@ static int list_match (pam_handle_t *, char *, char *, struct login_info *,
|
||||||
|
static int user_match (pam_handle_t *, char *, struct login_info *);
|
||||||
|
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 remote_match (pam_handle_t *, char *, struct login_info *);
|
||||||
|
static int string_match (pam_handle_t *, const char *, const char *, int);
|
||||||
|
static int network_netmask_match (pam_handle_t *, const char *, const char *, struct login_info *);
|
||||||
|
|
||||||
|
@@ -589,11 +590,9 @@ group_match (pam_handle_t *pamh, const char *tok, const char* usr,
|
||||||
|
/* from_match - match a host or tty against a list of tokens */
|
||||||
|
|
||||||
|
static int
|
||||||
|
-from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
|
||||||
|
+from_match (pam_handle_t *pamh, char *tok, struct login_info *item)
|
||||||
|
{
|
||||||
|
const char *string = item->from;
|
||||||
|
- int tok_len;
|
||||||
|
- int str_len;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (item->debug)
|
||||||
|
@@ -616,14 +615,29 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
|
||||||
|
} else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) {
|
||||||
|
/* ALL or exact match */
|
||||||
|
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)
|
||||||
|
- return (YES);
|
||||||
|
- } else if (item->from_remote_host == 0) { /* local: no PAM_RHOSTS */
|
||||||
|
- if (strcasecmp(tok, "LOCAL") == 0)
|
||||||
|
- return (YES);
|
||||||
|
- } else if (tok[(tok_len = strlen(tok)) - 1] == '.') {
|
||||||
|
+ } else if (strcasecmp(tok, "LOCAL") == 0) {
|
||||||
|
+ /* LOCAL matches only local accesses */
|
||||||
|
+ if (!item->from_remote_host)
|
||||||
|
+ return YES;
|
||||||
|
+ return NO;
|
||||||
|
+ } else if (item->from_remote_host) {
|
||||||
|
+ return remote_match(pamh, tok, item);
|
||||||
|
+ }
|
||||||
|
+ return NO;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
|
||||||
|
+{
|
||||||
|
+ const char *string = item->from;
|
||||||
|
+ size_t tok_len = strlen(tok);
|
||||||
|
+ size_t str_len;
|
||||||
|
+
|
||||||
|
+ if (tok[0] == '.') { /* domain: match last fields */
|
||||||
|
+ if ((str_len = strlen(string)) > tok_len
|
||||||
|
+ && strcasecmp(tok, string + str_len - tok_len) == 0)
|
||||||
|
+ return YES;
|
||||||
|
+ } else if (tok[tok_len - 1] == '.') {
|
||||||
|
struct addrinfo hint;
|
||||||
|
|
||||||
|
memset (&hint, '\0', sizeof (hint));
|
||||||
|
@@ -661,13 +675,11 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
|
||||||
|
runp = runp->ai_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- } else {
|
||||||
|
- /* Assume network/netmask with a IP of a host. */
|
||||||
|
- if (network_netmask_match(pamh, tok, string, item))
|
||||||
|
- return YES;
|
||||||
|
+ return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return NO;
|
||||||
|
+ /* Assume network/netmask with an IP of a host. */
|
||||||
|
+ return network_netmask_match(pamh, tok, string, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* string_match - match a string against one token */
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
|
|
||||||
|
From ecaaf4456e5aeacae1acdb1775bb5aadd3b19e13 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Wed, 16 Oct 2024 12:41:09 +0200
|
||||||
|
Subject: [PATCH 1/2] pam_access: always match local address
|
||||||
|
|
||||||
|
* modules/pam_access/pam_access.c: match the local address regardless of
|
||||||
|
the IP version in use.
|
||||||
|
|
||||||
|
In some circumstances the `localhost` may be translated to IPv4 or IPv6,
|
||||||
|
but the configuration file only indicated the address for one of the two
|
||||||
|
versions. Since the originating value is set in `PAM_RHOST` and PAM has
|
||||||
|
no control over it, let's match the local addresses regardless of the IP
|
||||||
|
version in use.
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-23018
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_access/pam_access.c | 30 ++++++++++++++++++++++++++++--
|
||||||
|
1 file changed, 28 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
|
||||||
|
index bfbc6d57..48e7c7e9 100644
|
||||||
|
--- a/modules/pam_access/pam_access.c
|
||||||
|
+++ b/modules/pam_access/pam_access.c
|
||||||
|
@@ -306,6 +306,23 @@ isipaddr (const char *string, int *addr_type,
|
||||||
|
return is_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* is_local_addr - checks if the IP address is local */
|
||||||
|
+static int
|
||||||
|
+is_local_addr (const char *string, int addr_type)
|
||||||
|
+{
|
||||||
|
+ if (addr_type == AF_INET) {
|
||||||
|
+ if (strcmp(string, "127.0.0.1") == 0) {
|
||||||
|
+ return YES;
|
||||||
|
+ }
|
||||||
|
+ } else if (addr_type == AF_INET6) {
|
||||||
|
+ if (strcmp(string, "::1") == 0) {
|
||||||
|
+ return YES;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NO;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/* are_addresses_equal - translate IP address strings to real IP
|
||||||
|
* addresses and compare them to find out if they are equal.
|
||||||
|
@@ -327,9 +344,18 @@ are_addresses_equal (const char *ipaddr0, const char *ipaddr1,
|
||||||
|
if (isipaddr (ipaddr1, &addr_type1, &addr1) == NO)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
- if (addr_type0 != addr_type1)
|
||||||
|
- /* different address types */
|
||||||
|
+ if (addr_type0 != addr_type1) {
|
||||||
|
+ /* different address types, but there is still a possibility that they are
|
||||||
|
+ * both local addresses
|
||||||
|
+ */
|
||||||
|
+ int local1 = is_local_addr(ipaddr0, addr_type0);
|
||||||
|
+ int local2 = is_local_addr(ipaddr1, addr_type1);
|
||||||
|
+
|
||||||
|
+ if (local1 == YES && local2 == YES)
|
||||||
|
+ return YES;
|
||||||
|
+
|
||||||
|
return NO;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (netmask != NULL) {
|
||||||
|
/* Got a netmask, so normalize addresses? */
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
|
|
||||||
|
From 641dfd1084508c63f3590e93a35b80ffc50774e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Fri, 18 Oct 2024 10:27:07 +0200
|
||||||
|
Subject: [PATCH 2/2] pam_access: clarify `LOCAL` keyword behaviour
|
||||||
|
|
||||||
|
* modules/pam_access/access.conf.5.xml: `LOCAL` keyword behaviour
|
||||||
|
explanation was focused on the development internals. Let's clarify it
|
||||||
|
by rephrasing it to something a sysadmin can understand.
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-39943
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_access/access.conf.5.xml | 17 ++++++-----------
|
||||||
|
1 file changed, 6 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml
|
||||||
|
index 35a1a8fe..0b93db00 100644
|
||||||
|
--- a/modules/pam_access/access.conf.5.xml
|
||||||
|
+++ b/modules/pam_access/access.conf.5.xml
|
||||||
|
@@ -79,17 +79,12 @@
|
||||||
|
with network mask (where network mask can be a decimal number or an
|
||||||
|
internet address also), <emphasis>ALL</emphasis> (which always matches)
|
||||||
|
or <emphasis>LOCAL</emphasis>. The <emphasis>LOCAL</emphasis>
|
||||||
|
- keyword matches if and only if
|
||||||
|
- <citerefentry><refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||||
|
- when called with an <parameter>item_type</parameter> of
|
||||||
|
- <emphasis>PAM_RHOST</emphasis>, returns <code>NULL</code> or an
|
||||||
|
- empty string (and therefore the
|
||||||
|
- <replaceable>origins</replaceable> field is compared against the
|
||||||
|
- return value of
|
||||||
|
- <citerefentry><refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||||
|
- called with an <parameter>item_type</parameter> of
|
||||||
|
- <emphasis>PAM_TTY</emphasis> or, absent that,
|
||||||
|
- <emphasis>PAM_SERVICE</emphasis>).
|
||||||
|
+ keyword matches when the user connects without a network
|
||||||
|
+ connection (e.g., <emphasis>su</emphasis>,
|
||||||
|
+ <emphasis>login</emphasis>). A connection through the loopback
|
||||||
|
+ device (e.g., <command>ssh user@localhost</command>) is
|
||||||
|
+ considered a network connection, and thus, the
|
||||||
|
+ <emphasis>LOCAL</emphasis> keyword does not match.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
@ -0,0 +1,211 @@
|
|||||||
|
diff -up Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml
|
||||||
|
--- Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml.pam-access-resolve-ip 2020-11-25 17:57:02.000000000 +0100
|
||||||
|
+++ Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml 2024-11-21 10:04:58.553127026 +0100
|
||||||
|
@@ -226,6 +226,14 @@
|
||||||
|
item and the line will be most probably ignored. For this reason, it is not
|
||||||
|
recommended to put spaces around the ':' characters.
|
||||||
|
</para>
|
||||||
|
+ <para>
|
||||||
|
+ An IPv6 link local host address must contain the interface
|
||||||
|
+ identifier. IPv6 link local network/netmask is not supported.
|
||||||
|
+ </para>
|
||||||
|
+ <para>
|
||||||
|
+ Hostnames should be written as Fully-Qualified Host Name (FQHN) to avoid
|
||||||
|
+ confusion with device names or PAM service names.
|
||||||
|
+ </para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="access.conf-see_also">
|
||||||
|
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml
|
||||||
|
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml.pam-access-resolve-ip 2020-11-25 17:57:02.000000000 +0100
|
||||||
|
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml 2024-11-21 10:04:58.553127026 +0100
|
||||||
|
@@ -25,11 +25,14 @@
|
||||||
|
<arg choice="opt">
|
||||||
|
debug
|
||||||
|
</arg>
|
||||||
|
+ <arg choice="opt" rep="norepeat">
|
||||||
|
+ noaudit
|
||||||
|
+ </arg>
|
||||||
|
<arg choice="opt">
|
||||||
|
nodefgroup
|
||||||
|
</arg>
|
||||||
|
- <arg choice="opt">
|
||||||
|
- noaudit
|
||||||
|
+ <arg choice="opt" rep="norepeat">
|
||||||
|
+ nodns
|
||||||
|
</arg>
|
||||||
|
<arg choice="opt">
|
||||||
|
accessfile=<replaceable>file</replaceable>
|
||||||
|
@@ -114,7 +117,46 @@
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
- <option>fieldsep=<replaceable>separators</replaceable></option>
|
||||||
|
+ nodefgroup
|
||||||
|
+ </term>
|
||||||
|
+ <listitem>
|
||||||
|
+ <para>
|
||||||
|
+ User tokens which are not enclosed in parentheses will not be
|
||||||
|
+ matched against the group database. The backwards compatible default is
|
||||||
|
+ to try the group database match even for tokens not enclosed
|
||||||
|
+ in parentheses.
|
||||||
|
+ </para>
|
||||||
|
+ </listitem>
|
||||||
|
+ </varlistentry>
|
||||||
|
+
|
||||||
|
+ <varlistentry>
|
||||||
|
+ <term>
|
||||||
|
+ nodns
|
||||||
|
+ </term>
|
||||||
|
+ <listitem>
|
||||||
|
+ <para>
|
||||||
|
+ Do not try to resolve tokens as hostnames, only IPv4 and IPv6
|
||||||
|
+ addresses will be resolved. Which means to allow login from a
|
||||||
|
+ remote host, the IP addresses need to be specified in <filename>access.conf</filename>.
|
||||||
|
+ </para>
|
||||||
|
+ </listitem>
|
||||||
|
+ </varlistentry>
|
||||||
|
+
|
||||||
|
+ <varlistentry>
|
||||||
|
+ <term>
|
||||||
|
+ quiet_log
|
||||||
|
+ </term>
|
||||||
|
+ <listitem>
|
||||||
|
+ <para>
|
||||||
|
+ Do not log denials with
|
||||||
|
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||||
|
+ </para>
|
||||||
|
+ </listitem>
|
||||||
|
+ </varlistentry>
|
||||||
|
+
|
||||||
|
+ <varlistentry>
|
||||||
|
+ <term>
|
||||||
|
+ fieldsep=separators
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
@@ -152,20 +194,6 @@
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
-
|
||||||
|
- <varlistentry>
|
||||||
|
- <term>
|
||||||
|
- <option>nodefgroup</option>
|
||||||
|
- </term>
|
||||||
|
- <listitem>
|
||||||
|
- <para>
|
||||||
|
- User tokens which are not enclosed in parentheses will not be
|
||||||
|
- matched against the group database. The backwards compatible default is
|
||||||
|
- to try the group database match even for tokens not enclosed
|
||||||
|
- in parentheses.
|
||||||
|
- </para>
|
||||||
|
- </listitem>
|
||||||
|
- </varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/pam_access.c
|
||||||
|
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.c.pam-access-resolve-ip 2024-11-21 10:04:58.547127010 +0100
|
||||||
|
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.c 2024-11-21 10:04:58.553127026 +0100
|
||||||
|
@@ -92,6 +92,7 @@ struct login_info {
|
||||||
|
int debug; /* Print debugging messages. */
|
||||||
|
int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
|
||||||
|
int noaudit; /* Do not audit denials */
|
||||||
|
+ int nodns; /* Do not try to resolve tokens as hostnames */
|
||||||
|
const char *fs; /* field separator */
|
||||||
|
const char *sep; /* list-element separator */
|
||||||
|
int from_remote_host; /* If PAM_RHOST was used for from */
|
||||||
|
@@ -143,6 +144,8 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||||
|
loginfo->only_new_group_syntax = YES;
|
||||||
|
} else if (strcmp (argv[i], "noaudit") == 0) {
|
||||||
|
loginfo->noaudit = YES;
|
||||||
|
+ } else if (strcmp (argv[i], "nodns") == 0) {
|
||||||
|
+ loginfo->nodns = YES;
|
||||||
|
} else {
|
||||||
|
pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
|
||||||
|
}
|
||||||
|
@@ -700,6 +703,39 @@ string_match (pam_handle_t *pamh, const
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+is_device (pam_handle_t *pamh, const char *tok)
|
||||||
|
+{
|
||||||
|
+ struct stat st;
|
||||||
|
+ const char *dev = "/dev/";
|
||||||
|
+ char *devname;
|
||||||
|
+
|
||||||
|
+ devname = malloc (strlen(dev) + strlen (tok) + 1);
|
||||||
|
+ if (devname == NULL) {
|
||||||
|
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory for device name: %m");
|
||||||
|
+ /*
|
||||||
|
+ * We should return an error and abort, but pam_access has no good
|
||||||
|
+ * error handling.
|
||||||
|
+ */
|
||||||
|
+ return NO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ char *cp = stpcpy (devname, dev);
|
||||||
|
+ strcpy (cp, tok);
|
||||||
|
+
|
||||||
|
+ if (lstat(devname, &st) != 0)
|
||||||
|
+ {
|
||||||
|
+ free (devname);
|
||||||
|
+ return NO;
|
||||||
|
+ }
|
||||||
|
+ free (devname);
|
||||||
|
+
|
||||||
|
+ if (S_ISCHR(st.st_mode))
|
||||||
|
+ return YES;
|
||||||
|
+
|
||||||
|
+ return NO;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* network_netmask_match - match a string against one token
|
||||||
|
* where string is a hostname or ip (v4,v6) address and tok
|
||||||
|
* represents either a hostname, a single ip (v4,v6) address
|
||||||
|
@@ -761,10 +797,42 @@ network_netmask_match (pam_handle_t *pam
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ else if (isipaddr(tok, NULL, NULL) == YES)
|
||||||
|
+ {
|
||||||
|
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
||||||
|
+ {
|
||||||
|
+ if (item->debug)
|
||||||
|
+ pam_syslog(pamh, LOG_DEBUG, "cannot resolve IP address \"%s\"", tok);
|
||||||
|
+
|
||||||
|
+ return NO;
|
||||||
|
+ }
|
||||||
|
+ netmask_ptr = NULL;
|
||||||
|
+ }
|
||||||
|
+ else if (item->nodns)
|
||||||
|
+ {
|
||||||
|
+ /* Only hostnames are left, which we would need to resolve via DNS */
|
||||||
|
+ return NO;
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
+ /* Bail out on X11 Display entries and ttys. */
|
||||||
|
+ if (tok[0] == ':')
|
||||||
|
+ {
|
||||||
|
+ if (item->debug)
|
||||||
|
+ pam_syslog (pamh, LOG_DEBUG,
|
||||||
|
+ "network_netmask_match: tok=%s is X11 display", tok);
|
||||||
|
+ return NO;
|
||||||
|
+ }
|
||||||
|
+ if (is_device (pamh, tok))
|
||||||
|
+ {
|
||||||
|
+ if (item->debug)
|
||||||
|
+ pam_syslog (pamh, LOG_DEBUG,
|
||||||
|
+ "network_netmask_match: tok=%s is a TTY", tok);
|
||||||
|
+ return NO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
- * It is either an IP address or a hostname.
|
||||||
|
+ * It is most likely a hostname.
|
||||||
|
* Let getaddrinfo sort everything out
|
||||||
|
*/
|
||||||
|
if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
@ -0,0 +1,47 @@
|
|||||||
|
diff -up Linux-PAM-1.3.1/modules/pam_unix/passverify.c.pam-unix-shadow-password Linux-PAM-1.3.1/modules/pam_unix/passverify.c
|
||||||
|
--- Linux-PAM-1.3.1/modules/pam_unix/passverify.c.pam-unix-shadow-password 2024-11-05 13:02:14.637785962 +0100
|
||||||
|
+++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c 2024-11-05 13:02:14.643785975 +0100
|
||||||
|
@@ -73,9 +73,13 @@ verify_pwd_hash(const char *p, char *has
|
||||||
|
|
||||||
|
strip_hpux_aging(hash);
|
||||||
|
hash_len = strlen(hash);
|
||||||
|
- if (!hash_len) {
|
||||||
|
+
|
||||||
|
+ if (p && p[0] == '\0' && !nullok) {
|
||||||
|
+ /* The passed password is empty */
|
||||||
|
+ retval = PAM_AUTH_ERR;
|
||||||
|
+ } else if (!hash_len) {
|
||||||
|
/* the stored password is NULL */
|
||||||
|
- if (nullok) { /* this means we've succeeded */
|
||||||
|
+ if (p && p[0] == '\0' && nullok) { /* this means we've succeeded */
|
||||||
|
D(("user has empty password - access granted"));
|
||||||
|
retval = PAM_SUCCESS;
|
||||||
|
} else {
|
||||||
|
@@ -192,17 +196,21 @@ PAMH_ARG_DECL(int get_account_info,
|
||||||
|
return PAM_UNIX_RUN_HELPER;
|
||||||
|
#endif
|
||||||
|
} else if (is_pwd_shadowed(*pwd)) {
|
||||||
|
+#ifdef HELPER_COMPILE
|
||||||
|
/*
|
||||||
|
- * ...and shadow password file entry for this user,
|
||||||
|
+ * shadow password file entry for this user,
|
||||||
|
* if shadowing is enabled
|
||||||
|
*/
|
||||||
|
-#ifndef HELPER_COMPILE
|
||||||
|
- if (geteuid() || SELINUX_ENABLED)
|
||||||
|
- return PAM_UNIX_RUN_HELPER;
|
||||||
|
-#endif
|
||||||
|
- *spwdent = pam_modutil_getspnam(pamh, name);
|
||||||
|
+ *spwdent = getspnam(name);
|
||||||
|
if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL)
|
||||||
|
return PAM_AUTHINFO_UNAVAIL;
|
||||||
|
+#else
|
||||||
|
+ /*
|
||||||
|
+ * The helper has to be invoked to deal with
|
||||||
|
+ * the shadow password file entry.
|
||||||
|
+ */
|
||||||
|
+ return PAM_UNIX_RUN_HELPER;
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return PAM_USER_UNKNOWN;
|
Loading…
Reference in new issue