From: Todd C. Miller Date: Mon, 11 Dec 2017 19:43:58 +0000 (-0700) Subject: Add authfail_message sudoers option to allow the user to override X-Git-Tag: SUDO_1_8_22^2~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1350a30737db53d985dfe27c30a45e52472903b6;p=sudo Add authfail_message sudoers option to allow the user to override the default message of %d incorrect password attempt(s). --- diff --git a/doc/sudoers.cat b/doc/sudoers.cat index 9abf92ec3..670a69c15 100644 --- a/doc/sudoers.cat +++ b/doc/sudoers.cat @@ -1600,6 +1600,12 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS SSttrriinnggss: + authfail_message Message that is displayed after a user fails to + authenticate. The message may include the `%d' escape + which will expand to the number of failed password + attempts. If set, it overrides the default message, %d + incorrect password attempts. + badpass_message Message that is displayed if a user enters an incorrect password. The default is Sorry, try again. unless insults are enabled. diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index 959ef24b9..9f4757dd0 100644 --- a/doc/sudoers.man.in +++ b/doc/sudoers.man.in @@ -3288,6 +3288,14 @@ its own umask which will override the value set in .PP \fBStrings\fR: .TP 18n +authfail_message +Message that is displayed after a user fails to authenticate. +The message may include the +\(oq%d\(cq +escape which will expand to the number of failed password attempts. +If set, it overrides the default message, +\fR%d incorrect password attempts\fR. +.TP 18n badpass_message Message that is displayed if a user enters an incorrect password. The default is diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index d3c1448cb..2773d6c2a 100644 --- a/doc/sudoers.mdoc.in +++ b/doc/sudoers.mdoc.in @@ -19,7 +19,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.Dd September 26, 2017 +.Dd December 11, 2017 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -3094,6 +3094,13 @@ its own umask which will override the value set in .Pp .Sy Strings : .Bl -tag -width 16n +.It authfail_message +Message that is displayed after a user fails to authenticate. +The message may include the +.Ql %d +escape which will expand to the number of failed password attempts. +If set, it overrides the default message, +.Li %d incorrect password attempt(s) . .It badpass_message Message that is displayed if a user enters an incorrect password. The default is diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c index dae695471..aa944921f 100644 --- a/plugins/sudoers/def_data.c +++ b/plugins/sudoers/def_data.c @@ -480,6 +480,10 @@ struct sudo_defs_types sudo_defs_table[] = { "timestamp_type", T_TUPLE, N_("Type of authentication timestamp record: %s"), def_data_timestamp_type, + }, { + "authfail_message", T_STR, + N_("Authentication failure message: %s"), + NULL, }, { NULL, 0, NULL } diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h index 78f126d24..63ee074bd 100644 --- a/plugins/sudoers/def_data.h +++ b/plugins/sudoers/def_data.h @@ -220,6 +220,8 @@ #define def_syslog_pid (sudo_defs_table[I_SYSLOG_PID].sd_un.flag) #define I_TIMESTAMP_TYPE 110 #define def_timestamp_type (sudo_defs_table[I_TIMESTAMP_TYPE].sd_un.tuple) +#define I_AUTHFAIL_MESSAGE 111 +#define def_authfail_message (sudo_defs_table[I_AUTHFAIL_MESSAGE].sd_un.str) enum def_tuple { never, diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in index f61dc8eb6..103fcf06e 100644 --- a/plugins/sudoers/def_data.in +++ b/plugins/sudoers/def_data.in @@ -348,3 +348,6 @@ timestamp_type T_TUPLE "Type of authentication timestamp record: %s" global ppid tty +authfail_message + T_STR + "Authentication failure message: %s" diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 31298658a..79aa7e4b3 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -421,6 +421,57 @@ log_allowed(int status) debug_return_bool(ret); } +/* + * Format an authentication failure message, using either + * authfail_message from sudoers or a locale-specific message. + */ +static int +fmt_authfail_message(char **str, va_list ap) +{ + unsigned int tries = va_arg(ap, unsigned int); + char *src, *dst0, *dst, *dst_end; + size_t size; + int len; + debug_decl(fmt_authfail_message, SUDOERS_DEBUG_LOGGING) + + if (def_authfail_message == NULL) { + debug_return_int(asprintf(str, ngettext("%u incorrect password attempt", + "%u incorrect password attempts", tries), tries)); + } + + src = def_authfail_message; + size = strlen(src) + 33; + if ((dst0 = dst = malloc(size)) == NULL) + debug_return_int(-1); + dst_end = dst + size; + + /* Always leave space for the terminating NUL. */ + while (*src != '\0' && dst + 1 < dst_end) { + if (src[0] == '%') { + switch (src[1]) { + case '%': + src++; + break; + case 'd': + len = snprintf(dst, dst_end - dst, "%u", tries); + if (len == -1 || len >= (int)(dst_end - dst)) + goto done; + dst += len; + src += 2; + continue; + default: + break; + } + } + *dst++ = *src++; + } +done: + *dst = '\0'; + + *str = dst0; + debug_return_int(dst - dst0); +} + /* * Perform logging for log_warning()/log_warningx(). */ @@ -442,9 +493,7 @@ vlog_warning(int flags, const char *fmt, va_list ap) /* Expand printf-style format + args (with a special case). */ if (fmt == INCORRECT_PASSWORD_ATTEMPT) { - unsigned int tries = va_arg(ap, unsigned int); - len = asprintf(&message, ngettext("%u incorrect password attempt", - "%u incorrect password attempts", tries), tries); + len = fmt_authfail_message(&message, ap); } else { len = vasprintf(&message, _(fmt), ap); } @@ -508,9 +557,15 @@ vlog_warning(int flags, const char *fmt, va_list ap) if (!ISSET(flags, SLOG_NO_STDERR)) { sudoers_setlocale(SUDOERS_LOCALE_USER, NULL); if (fmt == INCORRECT_PASSWORD_ATTEMPT) { - unsigned int tries = va_arg(ap2, unsigned int); - sudo_warnx_nodebug(ngettext("%u incorrect password attempt", - "%u incorrect password attempts", tries), tries); + len = fmt_authfail_message(&message, ap2); + if (len == -1) { + sudo_warnx(U_("%s: %s"), __func__, + U_("unable to allocate memory")); + ret = false; + goto done; + } + sudo_warnx_nodebug("%s", message); + free(message); } else { errno = serrno; if (ISSET(flags, SLOG_USE_ERRNO))