aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_unix
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@stoeckmann.org>2023-12-10 14:20:32 +0000
committerTobias Stoeckmann <tobias@stoeckmann.org>2023-12-11 21:02:31 +0100
commitb8429cc8036cd23d075174d13eedc6d857e2b454 (patch)
tree961a80706e4bfa229cfe0c9ec127b28da7fe4fe4 /modules/pam_unix
parentbf9ebc84c091f9f2d018aac2f9c2c4c4933e319e (diff)
downloadpam-b8429cc8036cd23d075174d13eedc6d857e2b454.tar.gz
pam-b8429cc8036cd23d075174d13eedc6d857e2b454.tar.bz2
pam-b8429cc8036cd23d075174d13eedc6d857e2b454.zip
pam_unix: check str to integer conversions
Print an error in syslog if an integer could not be converted. Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Diffstat (limited to 'modules/pam_unix')
-rw-r--r--modules/pam_unix/passverify.c10
-rw-r--r--modules/pam_unix/support.c60
2 files changed, 53 insertions, 17 deletions
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 930c7d3c..98f997d5 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -5,6 +5,7 @@
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
#include "support.h"
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
@@ -703,7 +704,8 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass,
while (fgets(buf, 16380, opwfile)) {
if (!strncmp(buf, forwho, len) && strchr(":,\n", buf[len]) != NULL) {
- char *sptr = NULL;
+ char *ep, *sptr = NULL;
+ long value;
found = 1;
if (howmany == 0)
continue;
@@ -724,7 +726,11 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass,
continue;
}
s_pas = strtok_r(NULL, ":", &sptr);
- npas = strtol(s_npas, NULL, 10) + 1;
+ value = strtol(s_npas, &ep, 10);
+ if (value < 0 || value >= INT_MAX || s_npas == ep || *ep != '\0')
+ npas = 0;
+ else
+ npas = (int)value + 1;
while (npas > howmany && s_pas != NULL) {
s_pas = strpbrk(s_pas, ",");
if (s_pas != NULL)
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index ec9a5725..9cc39ad7 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -46,6 +46,18 @@ int _make_remark(pam_handle_t * pamh, unsigned long long ctrl,
return retval;
}
+static int _unix_strtoi(const char *str, int minval, int *result)
+{
+ char *ep;
+ long value = strtol(str, &ep, 10);
+ if (value < minval || value > INT_MAX || str == ep || *ep != '\0') {
+ *result = minval;
+ return -1;
+ }
+ *result = (int)value;
+ return 0;
+}
+
/*
* set the control flags for the UNIX module.
*/
@@ -126,9 +138,11 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember,
"option remember not allowed for this module type");
continue;
}
- *remember = strtol(str, NULL, 10);
- if ((*remember == INT_MIN) || (*remember == INT_MAX))
- *remember = -1;
+ if (_unix_strtoi(str, -1, remember)) {
+ pam_syslog(pamh, LOG_ERR,
+ "option remember invalid [%s]", str);
+ continue;
+ }
if (*remember > 400)
*remember = 400;
} else if (j == UNIX_MIN_PASS_LEN) {
@@ -137,14 +151,22 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember,
"option minlen not allowed for this module type");
continue;
}
- *pass_min_len = atoi(str);
+ if (_unix_strtoi(str, 0, pass_min_len)) {
+ pam_syslog(pamh, LOG_ERR,
+ "option minlen invalid [%s]", str);
+ continue;
+ }
} else if (j == UNIX_ALGO_ROUNDS) {
if (rounds == NULL) {
pam_syslog(pamh, LOG_ERR,
"option rounds not allowed for this module type");
continue;
}
- *rounds = strtol(str, NULL, 10);
+ if (_unix_strtoi(str, 0, rounds)) {
+ pam_syslog(pamh, LOG_ERR,
+ "option rounds invalid [%s]", str);
+ continue;
+ }
}
ctrl &= unix_args[j].mask; /* for turning things off */
@@ -166,16 +188,24 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember,
/* Read number of rounds for sha256, sha512 and yescrypt */
if (off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) {
- val = NULL;
- if (on(UNIX_YESCRYPT_PASS, ctrl)) {
- val = pam_modutil_search_key(pamh, LOGIN_DEFS, "YESCRYPT_COST_FACTOR");
- } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
- val = pam_modutil_search_key(pamh, LOGIN_DEFS, "SHA_CRYPT_MAX_ROUNDS");
- }
- if (val) {
- *rounds = strtol(val, NULL, 10);
- set(UNIX_ALGO_ROUNDS, ctrl);
- free (val);
+ const char *key = NULL;
+ if (on(UNIX_YESCRYPT_PASS, ctrl))
+ key = "YESCRYPT_COST_FACTOR";
+ else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl))
+ key = "SHA_CRYPT_MAX_ROUNDS";
+ else
+ key = NULL;
+
+ if (key != NULL) {
+ val = pam_modutil_search_key(pamh, LOGIN_DEFS, key);
+ if (val) {
+ if (_unix_strtoi(val, 0, rounds))
+ pam_syslog(pamh, LOG_ERR,
+ "option %s invalid [%s]", key, val);
+ else
+ set(UNIX_ALGO_ROUNDS, ctrl);
+ free (val);
+ }
}
}