1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
/*
* Logging functions for pam_krb5.
*
* Logs errors and debugging messages from pam_krb5 functions. The debug
* versions only log anything if debugging was enabled; the error versions
* always log.
*
* Copyright 2005, 2006, 2007, 2009 Russ Allbery <rra@stanford.edu>
* Copyright 2005 Andres Salomon <dilinger@debian.org>
* Copyright 1999, 2000 Frank Cusack <fcusack@fcusack.com>
*
* See LICENSE for licensing terms.
*/
#include <config.h>
#include <portable/pam.h>
#include <krb5.h>
#include <stdarg.h>
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
#include <internal.h>
#ifndef LOG_AUTHPRIV
# define LOG_AUTHPRIV LOG_AUTH
#endif
/*
* Utility function to format a message into newly allocated memory, reporting
* an error via syslog if vasprintf fails.
*/
static char *
format(const char *fmt, va_list args)
{
char *msg;
if (vasprintf(&msg, fmt, args) < 0) {
syslog(LOG_CRIT | LOG_AUTHPRIV, "vasprintf failed: %m");
return NULL;
}
return msg;
}
/*
* Log wrapper function that adds the user. Log a message with the given
* priority, prefixed by (user <user>) with the account name being
* authenticated if known.
*/
static void
log_vplain(struct pam_args *pargs, int priority, const char *fmt, va_list args)
{
const char *name;
char *msg;
if (priority == LOG_DEBUG && (pargs == NULL || !pargs->debug))
return;
if (pargs != NULL && pargs->ctx != NULL && pargs->ctx->name != NULL) {
name = pargs->ctx->name;
msg = format(fmt, args);
if (msg == NULL)
return;
pam_syslog(pargs->pamh, priority, "(user %s) %s", name, msg);
free(msg);
} else if (pargs != NULL) {
pam_vsyslog(pargs->pamh, priority, fmt, args);
} else {
msg = format(fmt, args);
if (msg == NULL)
return;
syslog(priority | LOG_AUTHPRIV, "%s", msg);
free(msg);
}
}
/*
* Wrapper around log_vplain with variadic arguments.
*/
static void
log_plain(struct pam_args *pargs, int priority, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
log_vplain(pargs, priority, fmt, args);
va_end(args);
}
/*
* Log wrapper function for reporting a PAM error. Log a message with the
* given priority, prefixed by (user <user>) with the account name being
* authenticated if known, followed by a colon and the formatted PAM error.
*/
static void
log_pam(struct pam_args *pargs, int priority, int status, const char *fmt,
va_list args)
{
char *msg;
if (priority == LOG_DEBUG && (pargs == NULL || !pargs->debug))
return;
msg = format(fmt, args);
if (msg == NULL)
return;
if (pargs == NULL)
log_plain(NULL, priority, "%s", msg);
else
log_plain(pargs, priority, "%s: %s", msg,
pam_strerror(pargs->pamh, status));
free(msg);
}
/*
* Log wrapper function for reporting a Kerberos error. Log a message with
* the given priority, prefixed by (user <user>) with the account name being
* authenticated if known, followed by a colon and the formatted Kerberos
* error.
*/
static void
log_krb5(struct pam_args *pargs, int priority, int status, const char *fmt,
va_list args)
{
char *msg;
const char *k5_msg = NULL;
if (priority == LOG_DEBUG && (pargs == NULL || !pargs->debug))
return;
msg = format(fmt, args);
if (msg == NULL)
return;
if (pargs != NULL && pargs->ctx != NULL && pargs->ctx->context != NULL)
k5_msg = pamk5_compat_get_error(pargs->ctx->context, status);
else
k5_msg = pamk5_compat_get_error(NULL, status);
log_plain(pargs, priority, "%s: %s", msg, k5_msg);
free(msg);
if (pargs != NULL && pargs->ctx != NULL && pargs->ctx->context != NULL)
pamk5_compat_free_error(pargs->ctx->context, k5_msg);
}
/*
* The public interfaces. For each common log level (crit, err, and debug),
* generate a pamk5_<level> function and one for _pam and _krb5. Do this with
* the preprocessor to save duplicate code.
*/
#define LOG_FUNCTION(level, priority) \
void \
pamk5_ ## level(struct pam_args *pargs, const char *fmt, ...) \
{ \
va_list args; \
\
va_start(args, fmt); \
log_vplain(pargs, priority, fmt, args); \
va_end(args); \
} \
void \
pamk5_ ## level ## _pam(struct pam_args *pargs, int status, \
const char *fmt, ...) \
{ \
va_list args; \
\
va_start(args, fmt); \
log_pam(pargs, priority, status, fmt, args); \
va_end(args); \
} \
void \
pamk5_ ## level ## _krb5(struct pam_args *pargs, int status, \
const char *fmt, ...) \
{ \
va_list args; \
\
va_start(args, fmt); \
log_krb5(pargs, priority, status, fmt, args); \
va_end(args); \
}
LOG_FUNCTION(crit, LOG_CRIT)
LOG_FUNCTION(err, LOG_ERR)
LOG_FUNCTION(debug, LOG_DEBUG)
/*
* Report an authentication failure. This is a separate function since we
* want to include various PAM metadata in the log message and put it in a
* standard format. The format here is modeled after the pam_unix
* authentication failure message from Linux PAM.
*/
void
pamk5_log_failure(struct pam_args *pargs, const char *fmt, ...)
{
char *msg;
va_list args;
const char *ruser = NULL;
const char *rhost = NULL;
const char *tty = NULL;
const char *name = NULL;
if (pargs->ctx != NULL && pargs->ctx->name != NULL)
name = pargs->ctx->name;
va_start(args, fmt);
msg = format(fmt, args);
if (msg == NULL)
return;
va_end(args);
pam_get_item(pargs->pamh, PAM_RUSER, (PAM_CONST void **) &ruser);
pam_get_item(pargs->pamh, PAM_RHOST, (PAM_CONST void **) &rhost);
pam_get_item(pargs->pamh, PAM_TTY, (PAM_CONST void **) &tty);
pam_syslog(pargs->pamh, LOG_NOTICE, "%s; logname=%s uid=%ld euid=%ld"
" tty=%s ruser=%s rhost=%s", msg,
(name != NULL) ? name : "",
(long) getuid(), (long) geteuid(),
(tty != NULL) ? tty : "",
(ruser != NULL) ? ruser : "",
(rhost != NULL) ? rhost : "");
}
|