aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@stoeckmann.org>2023-11-11 23:34:28 +0100
committerDmitry V. Levin <github.dl@altlinux.org>2023-11-13 10:38:36 +0000
commitf800c5a8533003be7df56e6253821cf145f1a725 (patch)
tree1590545d2d4976cf958c843d0bcfa7236fe0bad8
parent32e4039784ba32a54406688b5bb71d3069381648 (diff)
downloadpam-f800c5a8533003be7df56e6253821cf145f1a725.tar.gz
pam-f800c5a8533003be7df56e6253821cf145f1a725.tar.bz2
pam-f800c5a8533003be7df56e6253821cf145f1a725.zip
pam_shells: limit shells to absolute paths
Only allow shells with absolute paths. Also handle line truncations which could occur with fgets by prefering getline/getdelim. Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
-rw-r--r--modules/pam_shells/pam_shells.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/modules/pam_shells/pam_shells.c b/modules/pam_shells/pam_shells.c
index 276a56dd..54875704 100644
--- a/modules/pam_shells/pam_shells.c
+++ b/modules/pam_shells/pam_shells.c
@@ -8,6 +8,7 @@
#include "config.h"
+#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <string.h>
@@ -115,8 +116,8 @@ static int perform_check(pam_handle_t *pamh)
econf_free (keys);
econf_free (key_file);
#else
- char shellFileLine[256];
- FILE * shellFile;
+ FILE *shellFile;
+ char *p = NULL;
if (!check_file(SHELL_FILE, pamh))
return PAM_AUTH_ERR;
@@ -129,14 +130,47 @@ static int perform_check(pam_handle_t *pamh)
retval = 1;
- while(retval && (fgets(shellFileLine, 255, shellFile) != NULL)) {
- if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
- shellFileLine[strlen(shellFileLine) - 1] = '\0';
- retval = strcmp(shellFileLine, userShell);
+#if defined(HAVE_GETLINE) || defined (HAVE_GETDELIM)
+ size_t n = 0;
+
+ while (retval &&
+#if defined(HAVE_GETLINE)
+ getline(&p, &n, shellFile)
+#elif defined (HAVE_GETDELIM)
+ getdelim(&p, &n, '\n', shellFile)
+#endif
+ != -1) {
+
+ if (p[0] != '/') {
+ continue;
+ }
+ retval = strcmp(p, userShell);
+ }
+
+ free(p);
+#else
+ char buf[PATH_MAX + 2];
+ int ignore = 0;
+
+ while (retval && fgets(buf, sizeof(buf), shellFile) != NULL) {
+ p = strchr(buf, '\n');
+ if (p == NULL) {
+ ignore = 1;
+ continue;
+ } else if (ignore) {
+ ignore = 0;
+ continue;
+ }
+
+ if (buf[0] != '/') {
+ continue;
+ }
+ retval = strcmp(buf, userShell);
}
+#endif
fclose(shellFile);
- #endif
+#endif
if (retval) {
return PAM_AUTH_ERR;