diff options
Diffstat (limited to 'libpam/include')
-rw-r--r-- | libpam/include/pam_cc_compat.h | 20 | ||||
-rw-r--r-- | libpam/include/pam_inline.h | 64 | ||||
-rw-r--r-- | libpam/include/security/_pam_macros.h | 28 | ||||
-rw-r--r-- | libpam/include/security/_pam_types.h | 6 | ||||
-rw-r--r-- | libpam/include/security/pam_modutil.h | 11 |
5 files changed, 112 insertions, 17 deletions
diff --git a/libpam/include/pam_cc_compat.h b/libpam/include/pam_cc_compat.h index 69190368..0a6e32d5 100644 --- a/libpam/include/pam_cc_compat.h +++ b/libpam/include/pam_cc_compat.h @@ -32,6 +32,11 @@ _Pragma("GCC diagnostic ignored \"-Wcast-align\"") # define DIAG_POP_IGNORE_CAST_ALIGN \ _Pragma("GCC diagnostic pop") +# define DIAG_PUSH_IGNORE_FORMAT_NONLITERAL \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") +# define DIAG_POP_IGNORE_FORMAT_NONLITERAL \ + _Pragma("GCC diagnostic pop") #elif PAM_CLANG_PREREQ(2, 6) # define DIAG_PUSH_IGNORE_CAST_QUAL \ _Pragma("clang diagnostic push"); \ @@ -43,11 +48,18 @@ _Pragma("clang diagnostic ignored \"-Wcast-align\"") # define DIAG_POP_IGNORE_CAST_ALIGN \ _Pragma("clang diagnostic pop") +# define DIAG_PUSH_IGNORE_FORMAT_NONLITERAL \ + _Pragma("clang diagnostic push"); \ + _Pragma("clang diagnostic ignored \"-Wformat-nonliteral\"") +# define DIAG_POP_IGNORE_FORMAT_NONLITERAL \ + _Pragma("clang diagnostic pop") #else -# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */ -# define DIAG_POP_IGNORE_CAST_QUAL /* empty */ -# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */ -# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */ +# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */ +# define DIAG_POP_IGNORE_CAST_QUAL /* empty */ +# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */ +# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */ +# define DIAG_PUSH_IGNORE_FORMAT_NONLITERAL /* empty */ +# define DIAG_POP_IGNORE_FORMAT_NONLITERAL /* empty */ #endif /* diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h index ec2f3bf0..7721c0b7 100644 --- a/libpam/include/pam_inline.h +++ b/libpam/include/pam_inline.h @@ -9,6 +9,7 @@ #define PAM_INLINE_H #include "pam_cc_compat.h" +#include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> @@ -33,6 +34,12 @@ * 0, otherwise. */ #define PAM_MUST_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(!PAM_IS_NOT_ARRAY(a_)) +/* + * Evaluates to + * - a syntax error if the argument is an array, + * 0, otherwise. + */ +#define PAM_MUST_NOT_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(PAM_IS_NOT_ARRAY(a_)) /* Evaluates to the number of elements in the specified array. */ #define PAM_ARRAY_SIZE(a_) (sizeof(a_) / sizeof((a_)[0]) + PAM_MUST_BE_ARRAY(a_)) @@ -66,6 +73,59 @@ pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix #define pam_str_skip_icase_prefix(str_, prefix_) \ pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) + +/* + * Macros to securely erase memory + */ + +#ifdef HAVE_MEMSET_EXPLICIT +static inline void pam_overwrite_n(void *ptr, size_t len) +{ + if (ptr) + memset_explicit(ptr, len); +} +#elif defined HAVE_EXPLICIT_BZERO +static inline void pam_overwrite_n(void *ptr, size_t len) +{ + if (ptr) + explicit_bzero(ptr, len); +} +#else +static inline void pam_overwrite_n(void *ptr, size_t len) +{ + if (ptr) { + ptr = memset(ptr, '\0', len); + __asm__ __volatile__ ("" : : "r"(ptr) : "memory"); + } +} +#endif + +#define pam_overwrite_string(x) \ +do { \ + char *xx__ = (x) + PAM_MUST_NOT_BE_ARRAY(x); \ + if (xx__) \ + pam_overwrite_n(xx__, strlen(xx__)); \ +} while(0) + +#define pam_overwrite_array(x) pam_overwrite_n(x, sizeof(x) + PAM_MUST_BE_ARRAY(x)) + +#define pam_overwrite_object(x) pam_overwrite_n(x, sizeof(*(x)) + PAM_MUST_NOT_BE_ARRAY(x)) + +static inline void +pam_drop_response(struct pam_response *reply, int replies) +{ + int reply_i; + + for (reply_i = 0; reply_i < replies; ++reply_i) { + if (reply[reply_i].resp) { + pam_overwrite_string(reply[reply_i].resp); + free(reply[reply_i].resp); + } + } + free(reply); +} + + static inline int pam_read_passwords(int fd, int npass, char **passwords) { @@ -101,7 +161,7 @@ pam_read_passwords(int fd, int npass, char **passwords) if (npass > 0) { memcpy(passwords[i], pptr, rbytes); } - memset(pptr, '\0', rbytes); + pam_overwrite_n(pptr, rbytes); } } offset += rbytes; @@ -109,7 +169,7 @@ pam_read_passwords(int fd, int npass, char **passwords) /* clear up */ if (offset > 0 && npass > 0) { - memset(passwords[i], '\0', offset); + pam_overwrite_n(passwords[i], offset); } return i; diff --git a/libpam/include/security/_pam_macros.h b/libpam/include/security/_pam_macros.h index e891e226..b5129d2a 100644 --- a/libpam/include/security/_pam_macros.h +++ b/libpam/include/security/_pam_macros.h @@ -7,6 +7,8 @@ * Organized by Cristian Gafton <gafton@redhat.com> */ +#include "_pam_types.h" + /* a 'safe' version of strdup */ #include <stdlib.h> @@ -14,20 +16,22 @@ #define x_strdup(s) ( (s) ? strdup(s):NULL ) -/* Good policy to strike out passwords with some characters not just - free the memory */ +/* + * WARNING: Do NOT use these overwrite macros, as they do not reliable + * override the memory. + */ -#define _pam_overwrite(x) \ -do { \ - register char *__xx__; \ - if ((__xx__=(x))) \ - while (*__xx__) \ - *__xx__++ = '\0'; \ +#define _pam_overwrite(x) \ +do { \ + PAM_DEPRECATED register char *__xx__; \ + if ((__xx__=(x))) \ + while (*__xx__) \ + *__xx__++ = '\0'; \ } while (0) #define _pam_overwrite_n(x,n) \ do { \ - register char *__xx__; \ + PAM_DEPRECATED register char *__xx__; \ register unsigned int __i__ = 0; \ if ((__xx__=(x))) \ for (;__i__<n; __i__++) \ @@ -46,9 +50,13 @@ do { \ } \ } while (0) +/* + * WARNING: Do NOT use this macro, as it does not reliable override the memory. + */ + #define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \ do { \ - int reply_i; \ + PAM_DEPRECATED int reply_i; \ \ for (reply_i=0; reply_i<replies; ++reply_i) { \ if (reply[reply_i].resp) { \ diff --git a/libpam/include/security/_pam_types.h b/libpam/include/security/_pam_types.h index 2abb7ee5..4d6909e8 100644 --- a/libpam/include/security/_pam_types.h +++ b/libpam/include/security/_pam_types.h @@ -160,6 +160,12 @@ typedef struct pam_handle pam_handle_t; # define PAM_FORMAT(params) #endif +#if PAM_GNUC_PREREQ(3,1) +# define PAM_DEPRECATED __attribute__((__deprecated__)) +#else +# define PAM_DEPRECATED +#endif + #if PAM_GNUC_PREREQ(3,3) && !defined(LIBPAM_COMPILE) # define PAM_NONNULL(params) __attribute__((__nonnull__ params)) #else diff --git a/libpam/include/security/pam_modutil.h b/libpam/include/security/pam_modutil.h index 33f87b90..c2578323 100644 --- a/libpam/include/security/pam_modutil.h +++ b/libpam/include/security/pam_modutil.h @@ -147,7 +147,16 @@ pam_modutil_sanitize_helper_fds(pam_handle_t *pamh, enum pam_modutil_redirect_fd redirect_stdout, enum pam_modutil_redirect_fd redirect_stderr); -/* lookup a value for key in login.defs file or similar key value format */ +/************************************************** + * @brief Lookup a value for the key in the file (i.e. login.defs or a similar + * key-value format file). + * + * @param[in] pamh The pam handle structure + * @param[in] file_name Configuration file name + * @param[in] key Lookup key + * + * @return value, or NULL if key was not found. + **************************************************/ extern char * PAM_NONNULL((1,2,3)) pam_modutil_search_key(pam_handle_t *pamh, const char *file_name, |