diff options
Diffstat (limited to 'modules/pam_timestamp/pam_timestamp.c')
-rw-r--r-- | modules/pam_timestamp/pam_timestamp.c | 102 |
1 files changed, 89 insertions, 13 deletions
diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c index 30be883c..c5fa6dfc 100644 --- a/modules/pam_timestamp/pam_timestamp.c +++ b/modules/pam_timestamp/pam_timestamp.c @@ -53,10 +53,19 @@ #include <time.h> #include <sys/time.h> #include <unistd.h> -#include <utmp.h> #include <syslog.h> #include <paths.h> +#ifdef WITH_OPENSSL +#include "hmac_openssl_wrapper.h" +#else #include "hmacsha1.h" +#endif /* WITH_OPENSSL */ + +#ifdef USE_LOGIND +#include <systemd/sd-login.h> +#else +#include <utmp.h> +#endif #include <security/pam_modules.h> #include <security/_pam_macros.h> @@ -79,11 +88,14 @@ #define BUFLEN PATH_MAX #endif +#define ROOT_USER 0 +#define ROOT_GROUP 0 + /* Return PAM_SUCCESS if the given directory looks "safe". */ static int check_dir_perms(pam_handle_t *pamh, const char *tdir) { - char scratch[BUFLEN]; + char scratch[BUFLEN] = {}; struct stat st; int i; /* Check that the directory is "safe". */ @@ -91,7 +103,6 @@ check_dir_perms(pam_handle_t *pamh, const char *tdir) return PAM_AUTH_ERR; } /* Iterate over the path, checking intermediate directories. */ - memset(scratch, 0, sizeof(scratch)); for (i = 0; (tdir[i] != '\0') && (i < (int)sizeof(scratch)); i++) { scratch[i] = tdir[i]; if ((scratch[i] == '/') || (tdir[i + 1] == '\0')) { @@ -193,10 +204,26 @@ timestamp_good(time_t then, time_t now, time_t interval) } static int -check_login_time(const char *ruser, time_t timestamp) +check_login_time( +#ifdef USE_LOGIND + uid_t uid, +#else + const char *ruser, +#endif + time_t timestamp) { - struct utmp utbuf, *ut; time_t oldest_login = 0; +#ifdef USE_LOGIND +#define USEC_PER_SEC ((uint64_t) 1000000ULL) + uint64_t usec = 0; + + if (sd_uid_get_login_time(uid, &usec) < 0) { + return PAM_SERVICE_ERR; + } + + oldest_login = usec/USEC_PER_SEC; +#else + struct utmp utbuf, *ut; setutent(); while( @@ -217,6 +244,7 @@ check_login_time(const char *ruser, time_t timestamp) } } endutent(); +#endif if(oldest_login == 0 || timestamp < oldest_login) { return PAM_AUTH_ERR; } @@ -449,6 +477,13 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) return PAM_AUTH_ERR; } +#ifdef WITH_OPENSSL + if (hmac_size(pamh, debug, &maclen)) { + return PAM_AUTH_ERR; + } +#else + maclen = hmac_sha1_size(); +#endif /* WITH_OPENSSL */ /* Check that the file is the expected size. */ if (st.st_size == 0) { /* Invalid, but may have been created by sudo. */ @@ -456,7 +491,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) return PAM_AUTH_ERR; } if (st.st_size != - (off_t)(strlen(path) + 1 + sizeof(then) + hmac_sha1_size())) { + (off_t)(strlen(path) + 1 + sizeof(then) + maclen)) { pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' " "appears to be corrupted", path); close(fd); @@ -487,8 +522,17 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) message_end = message + strlen(path) + 1 + sizeof(then); /* Regenerate the MAC. */ - hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY, 0, 0, - message, message_end - message); +#ifdef WITH_OPENSSL + if (hmac_generate(pamh, debug, &mac, &maclen, TIMESTAMPKEY, + ROOT_USER, ROOT_GROUP, message, message_end - message)) { + close(fd); + free(message); + return PAM_AUTH_ERR; + } +#else + hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY, + ROOT_USER, ROOT_GROUP, message, message_end - message); +#endif /* WITH_OPENSSL */ if ((mac == NULL) || (memcmp(path, message, strlen(path)) != 0) || (memcmp(mac, message_end, maclen) != 0)) { @@ -509,7 +553,15 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) close(fd); return PAM_AUTH_ERR; } +#ifdef USE_LOGIND + struct passwd *pwd = pam_modutil_getpwnam(pamh, ruser); + if (pwd != NULL) { + return PAM_SERVICE_ERR; + } + if (check_login_time(pwd->pw_uid, then) != PAM_SUCCESS) +#else if (check_login_time(ruser, then) != PAM_SUCCESS) +#endif { pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' is " "older than oldest login, disallowing " @@ -605,8 +657,16 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char * } } +#ifdef WITH_OPENSSL + if (hmac_size(pamh, debug, &maclen)) { + return PAM_SESSION_ERR; + } +#else + maclen = hmac_sha1_size(); +#endif /* WITH_OPENSSL */ + /* Generate the message. */ - text = malloc(strlen(path) + 1 + sizeof(now) + hmac_sha1_size()); + text = malloc(strlen(path) + 1 + sizeof(now) + maclen); if (text == NULL) { pam_syslog(pamh, LOG_CRIT, "unable to allocate memory: %m"); return PAM_SESSION_ERR; @@ -621,15 +681,21 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char * p += sizeof(now); /* Generate the MAC and append it to the plaintext. */ - hmac_sha1_generate_file(pamh, &mac, &maclen, - TIMESTAMPKEY, - 0, 0, - text, p - text); +#ifdef WITH_OPENSSL + if (hmac_generate(pamh, debug, &mac, &maclen, TIMESTAMPKEY, + ROOT_USER, ROOT_GROUP, text, p - text)) { + free(text); + return PAM_SESSION_ERR; + } +#else + hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY, + ROOT_USER, ROOT_GROUP, text, p - text); if (mac == NULL) { pam_syslog(pamh, LOG_ERR, "failure generating MAC: %m"); free(text); return PAM_SESSION_ERR; } +#endif /* WITH_OPENSSL */ memmove(p, mac, maclen); p += maclen; free(mac); @@ -691,6 +757,9 @@ main(int argc, char **argv) fd_set write_fds; char path[BUFLEN]; struct stat st; +#ifdef USE_LOGIND + uid_t uid; +#endif /* Check that there's nothing funny going on with stdio. */ if ((fstat(STDIN_FILENO, &st) == -1) || @@ -746,6 +815,9 @@ main(int argc, char **argv) if (pwd == NULL) { retval = 4; } +#ifdef USE_LOGIND + uid = pwd->pw_uid; +#endif /* Get the name of the target user. */ user = strdup(pwd->pw_name); @@ -796,7 +868,11 @@ main(int argc, char **argv) /* Check the timestamp. */ if (lstat(path, &st) != -1) { /* Check oldest login against timestamp */ +#ifdef USE_LOGIND + if (check_login_time(uid, st.st_mtime) != PAM_SUCCESS) { +#else if (check_login_time(user, st.st_mtime) != PAM_SUCCESS) { +#endif retval = 7; } else if (timestamp_good(st.st_mtime, time(NULL), DEFAULT_TIMESTAMP_TIMEOUT) != PAM_SUCCESS) { |