mirror of
https://github.com/sudo-project/sudo.git
synced 2025-09-04 00:05:11 +00:00
Add a new sudoers settings log_passwords and passprompt_regex.
When logging terminal input, if log_passwords is disabled and any of the regular expressions in the passprompt_regex list are found in the terminal output, terminal input will be replaced with '*' characters until a newline or carriage return is found in the input or an output character is received.
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.TH "SUDOERS" "@mansectform@" "January 20, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||
.TH "SUDOERS" "@mansectform@" "January 27, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||
.nh
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -2660,6 +2660,43 @@ This flag is
|
||||
\fIoff\fR
|
||||
by default.
|
||||
.TP 18n
|
||||
log_passwords
|
||||
Most programs that require a user's password will disable echo before
|
||||
reading the password to avoid displaying the plaintext password on
|
||||
the screen.
|
||||
However, if terminal input is being logged (see
|
||||
\fIlog_input\fR),
|
||||
the password will still be present in the I/O log.
|
||||
If the
|
||||
\fIlog_passwords\fR
|
||||
option is disabled,
|
||||
\fBsudoers\fR
|
||||
will attempt to prevent passwords from being logged.
|
||||
It does this by using the regular expressions in
|
||||
\fIpassprompt_regex\fR
|
||||
to match a password prompt in the terminal output buffer.
|
||||
When a match is found, input characters in the I/O log will be replaced with
|
||||
\(oq*\(cq
|
||||
until either a line feed or carriage return is found in the terminal input
|
||||
or a new terminal output buffer is received.
|
||||
If, however, a program displays characters as the user types
|
||||
(such as
|
||||
\fBsudo\fR
|
||||
when
|
||||
\fIpwfeedback\fR
|
||||
is set), only the
|
||||
first character of the password will be replaced in the I/O log.
|
||||
This option has no effect unless
|
||||
\fIlog_input\fR
|
||||
and
|
||||
\fIlog_input\fR
|
||||
are also set.
|
||||
This flag is
|
||||
\fIon\fR
|
||||
by default.
|
||||
.sp
|
||||
This setting is only supported by version 1.9.10 or higher.
|
||||
.TP 18n
|
||||
fqdn
|
||||
Set this flag if you want to put fully qualified host names in the
|
||||
\fIsudoers\fR
|
||||
@@ -5261,6 +5298,17 @@ flag (I/O logging enabled) or the
|
||||
flag (I/O logging disabled) is set.
|
||||
.sp
|
||||
This setting is only supported by version 1.9.0 or higher.
|
||||
.TP 18n
|
||||
passprompt_regex
|
||||
A list of POSIX extended regular expressions used to
|
||||
match password prompts in the terminal output.
|
||||
This option is only used when
|
||||
\fIlog_passwords\fR
|
||||
has been disabled.
|
||||
The default value is
|
||||
\(lq[Pp]assword[: ]*\(rq
|
||||
.sp
|
||||
This setting is only supported by version 1.9.10 or higher.
|
||||
.SH "GROUP PROVIDER PLUGINS"
|
||||
The
|
||||
\fBsudoers\fR
|
||||
|
@@ -24,7 +24,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.Dd January 20, 2022
|
||||
.Dd January 27, 2022
|
||||
.Dt SUDOERS @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -2507,6 +2507,42 @@ characters.
|
||||
This flag is
|
||||
.Em off
|
||||
by default.
|
||||
.It log_passwords
|
||||
Most programs that require a user's password will disable echo before
|
||||
reading the password to avoid displaying the plaintext password on
|
||||
the screen.
|
||||
However, if terminal input is being logged (see
|
||||
.Em log_input ) ,
|
||||
the password will still be present in the I/O log.
|
||||
If the
|
||||
.Em log_passwords
|
||||
option is disabled,
|
||||
.Nm
|
||||
will attempt to prevent passwords from being logged.
|
||||
It does this by using the regular expressions in
|
||||
.Em passprompt_regex
|
||||
to match a password prompt in the terminal output buffer.
|
||||
When a match is found, input characters in the I/O log will be replaced with
|
||||
.Ql *
|
||||
until either a line feed or carriage return is found in the terminal input
|
||||
or a new terminal output buffer is received.
|
||||
If, however, a program displays characters as the user types
|
||||
(such as
|
||||
.Nm sudo
|
||||
when
|
||||
.Em pwfeedback
|
||||
is set), only the
|
||||
first character of the password will be replaced in the I/O log.
|
||||
This option has no effect unless
|
||||
.Em log_input
|
||||
and
|
||||
.Em log_input
|
||||
are also set.
|
||||
This flag is
|
||||
.Em on
|
||||
by default.
|
||||
.Pp
|
||||
This setting is only supported by version 1.9.10 or higher.
|
||||
.It fqdn
|
||||
Set this flag if you want to put fully qualified host names in the
|
||||
.Em sudoers
|
||||
@@ -4908,6 +4944,16 @@ flag (I/O logging enabled) or the
|
||||
flag (I/O logging disabled) is set.
|
||||
.Pp
|
||||
This setting is only supported by version 1.9.0 or higher.
|
||||
.It passprompt_regex
|
||||
A list of POSIX extended regular expressions used to
|
||||
match password prompts in the terminal output.
|
||||
This option is only used when
|
||||
.Em log_passwords
|
||||
has been disabled.
|
||||
The default value is
|
||||
.Dq [Pp]assword[: ]*
|
||||
.Pp
|
||||
This setting is only supported by version 1.9.10 or higher.
|
||||
.El
|
||||
.Sh GROUP PROVIDER PLUGINS
|
||||
The
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
#
|
||||
# Copyright (c) 1996, 1998-2005, 2007-2021
|
||||
# Copyright (c) 1996, 1998-2005, 2007-2022
|
||||
# Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -1504,22 +1504,22 @@ defaults.lo: $(srcdir)/defaults.c $(devdir)/def_data.c $(devdir)/def_data.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
|
||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||
$(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
|
||||
$(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
|
||||
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
|
||||
$(top_builddir)/pathnames.h
|
||||
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
|
||||
$(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
|
||||
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
|
||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/defaults.c
|
||||
defaults.i: $(srcdir)/defaults.c $(devdir)/def_data.c $(devdir)/def_data.h \
|
||||
$(devdir)/gram.h $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
|
||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||
$(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
|
||||
$(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
|
||||
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
|
||||
$(top_builddir)/pathnames.h
|
||||
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
|
||||
$(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
|
||||
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
|
||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
defaults.plog: defaults.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/defaults.c --i-file $< --output-file $@
|
||||
|
@@ -645,6 +645,14 @@ struct sudo_defs_types sudo_defs_table[] = {
|
||||
"rlimit_stack", T_RLIMIT|T_BOOL,
|
||||
N_("The maximum size to which the process's stack may grow (in bytes): %s"),
|
||||
NULL,
|
||||
}, {
|
||||
"log_passwords", T_FLAG,
|
||||
N_("Store plaintext passwords in I/O log input"),
|
||||
NULL,
|
||||
}, {
|
||||
"passprompt_regex", T_LIST|T_BOOL,
|
||||
N_("List of regular expressions to use when matching a password prompt"),
|
||||
NULL,
|
||||
}, {
|
||||
NULL, 0, NULL
|
||||
}
|
||||
|
@@ -300,6 +300,10 @@
|
||||
#define def_rlimit_rss (sudo_defs_table[I_RLIMIT_RSS].sd_un.str)
|
||||
#define I_RLIMIT_STACK 149
|
||||
#define def_rlimit_stack (sudo_defs_table[I_RLIMIT_STACK].sd_un.str)
|
||||
#define I_LOG_PASSWORDS 150
|
||||
#define def_log_passwords (sudo_defs_table[I_LOG_PASSWORDS].sd_un.flag)
|
||||
#define I_PASSPROMPT_REGEX 151
|
||||
#define def_passprompt_regex (sudo_defs_table[I_PASSPROMPT_REGEX].sd_un.list)
|
||||
|
||||
enum def_tuple {
|
||||
never,
|
||||
|
@@ -466,3 +466,9 @@ rlimit_rss
|
||||
rlimit_stack
|
||||
T_RLIMIT|T_BOOL
|
||||
"The maximum size to which the process's stack may grow (in bytes): %s"
|
||||
log_passwords
|
||||
T_FLAG
|
||||
"Store plaintext passwords in I/O log input"
|
||||
passprompt_regex
|
||||
T_LIST|T_BOOL
|
||||
"List of regular expressions to use when matching a password prompt"
|
||||
|
@@ -36,10 +36,12 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "sudoers.h"
|
||||
#include "sudo_eventlog.h"
|
||||
#include "sudo_iolog.h"
|
||||
#include <gram.h>
|
||||
|
||||
static struct early_default early_defaults[] = {
|
||||
@@ -454,6 +456,24 @@ free_defs_val(int type, union sudo_defs_val *sd_un)
|
||||
memset(sd_un, 0, sizeof(*sd_un));
|
||||
}
|
||||
|
||||
static bool
|
||||
init_passprompt_regex(void)
|
||||
{
|
||||
struct list_member *lm;
|
||||
debug_decl(init_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
|
||||
|
||||
/* Add initial defaults setting. */
|
||||
lm = calloc(1, sizeof(struct list_member));
|
||||
if (lm == NULL || (lm->value = strdup(PASSPROMPT_REGEX)) == NULL) {
|
||||
free(lm);
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
debug_return_bool(false);
|
||||
}
|
||||
SLIST_INSERT_HEAD(&def_passprompt_regex, lm, entries);
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default options to compiled-in values.
|
||||
* Any of these may be overridden at runtime by a "Defaults" file.
|
||||
@@ -596,6 +616,7 @@ init_defaults(void)
|
||||
#ifdef HAVE_ZLIB_H
|
||||
def_compress_io = true;
|
||||
#endif
|
||||
def_log_passwords = true;
|
||||
def_log_server_timeout = 30;
|
||||
def_log_server_verify = true;
|
||||
def_log_server_keepalive = true;
|
||||
@@ -658,6 +679,10 @@ init_defaults(void)
|
||||
/* Init eventlog config. */
|
||||
init_eventlog_config();
|
||||
|
||||
/* Initial iolog password prompt regex. */
|
||||
if (!init_passprompt_regex())
|
||||
debug_return_bool(false);
|
||||
|
||||
firsttime = false;
|
||||
|
||||
debug_return_bool(true);
|
||||
@@ -1252,3 +1277,29 @@ oom:
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
bool
|
||||
cb_passprompt_regex(const union sudo_defs_val *sd_un, int op)
|
||||
{
|
||||
struct list_member *lm;
|
||||
int errcode;
|
||||
char errbuf[1024];
|
||||
regex_t re;
|
||||
debug_decl(cb_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
|
||||
|
||||
/* If adding one or more regexps, validate them with regcomp(). */
|
||||
if (op == '+' || op == true) {
|
||||
SLIST_FOREACH(lm, &sd_un->list, entries) {
|
||||
errcode = regcomp(&re, lm->value, REG_EXTENDED|REG_NOSUB);
|
||||
if (errcode != 0) {
|
||||
regerror(errcode, &re, errbuf, sizeof(errbuf));
|
||||
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
||||
lm->value, errbuf);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
regfree(&re);
|
||||
}
|
||||
}
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
@@ -137,6 +137,7 @@ bool set_default(const char *var, const char *val, int op, const char *file, int
|
||||
bool update_defaults(struct sudoers_parse_tree *parse_tree, struct defaults_list *defs, int what, bool quiet);
|
||||
bool check_defaults(struct sudoers_parse_tree *parse_tree, bool quiet);
|
||||
bool append_default(const char *var, const char *val, int op, char *source, struct defaults_list *defs);
|
||||
bool cb_passprompt_regex(const union sudo_defs_val *sd_un, int op);
|
||||
|
||||
extern struct sudo_defs_types sudo_defs_table[];
|
||||
|
||||
|
@@ -69,8 +69,10 @@ static struct sudoers_io_operations {
|
||||
|
||||
static struct log_details iolog_details;
|
||||
static bool warned = false;
|
||||
static bool log_passwords = true;
|
||||
static int iolog_dir_fd = -1;
|
||||
static struct timespec last_time;
|
||||
static void *passprompt_regex_handle;
|
||||
static void sudoers_io_setops(void);
|
||||
|
||||
/* sudoers_io is declared at the end of this file. */
|
||||
@@ -209,6 +211,7 @@ free_iolog_details(void)
|
||||
|
||||
/*
|
||||
* Convert a comma-separated list to a string list.
|
||||
* XXX - handle escaped commas
|
||||
*/
|
||||
static struct sudoers_str_list *
|
||||
deserialize_stringlist(const char *s)
|
||||
@@ -244,6 +247,39 @@ bad:
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set passprompt regex filter based on a comma-separated string.
|
||||
* Returns a passprompt regex handle pointer.
|
||||
*/
|
||||
static void *
|
||||
set_passprompt_regex(const char *cstr)
|
||||
{
|
||||
void *handle;
|
||||
char *cp, *last, *str;
|
||||
debug_decl(set_passprompt_regex, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
handle = iolog_pwfilt_alloc();
|
||||
str = strdup(cstr);
|
||||
if (handle == NULL || str == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* XXX - handle escaped commas */
|
||||
for ((cp = strtok_r(str, ",", &last)); cp != NULL;
|
||||
(cp = strtok_r(NULL, ",", &last))) {
|
||||
if (!iolog_pwfilt_add(handle, cp))
|
||||
goto bad;
|
||||
}
|
||||
|
||||
free(str);
|
||||
debug_return_ptr(handle);
|
||||
bad:
|
||||
free(str);
|
||||
iolog_pwfilt_free(handle);
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pull out I/O log related data from user_info and command_info arrays.
|
||||
* Returns true if I/O logging is enabled, false if not and -1 on error.
|
||||
@@ -441,6 +477,16 @@ iolog_deserialize_info(struct log_details *details, char * const user_info[],
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (strncmp(*cur, "log_passwords=", sizeof("log_passwords=") - 1) == 0) {
|
||||
int val = sudo_strtobool(*cur + sizeof("log_passwords=") - 1);
|
||||
if (val != -1) {
|
||||
log_passwords = val;
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_WARN,
|
||||
"%s: unable to parse %s", __func__, *cur);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (strncmp(*cur, "log_servers=", sizeof("log_servers=") - 1) == 0) {
|
||||
details->log_servers =
|
||||
deserialize_stringlist(*cur + sizeof("log_servers=") - 1);
|
||||
@@ -506,6 +552,14 @@ iolog_deserialize_info(struct log_details *details, char * const user_info[],
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (strncmp(*cur, "passprompt_regex=", sizeof("passprompt_regex=") - 1) == 0) {
|
||||
passprompt_regex_handle =
|
||||
set_passprompt_regex(*cur + sizeof("passprompt_regex=") - 1);
|
||||
if (passprompt_regex_handle == NULL)
|
||||
debug_return_int(-1);
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (strncmp(*cur, "runas_gid=", sizeof("runas_gid=") - 1) == 0) {
|
||||
runas_gid_str = *cur + sizeof("runas_gid=") - 1;
|
||||
@@ -852,6 +906,8 @@ sudoers_io_close(int exit_status, int error)
|
||||
free_iolog_details();
|
||||
sudo_freepwcache();
|
||||
sudo_freegrcache();
|
||||
iolog_pwfilt_free(passprompt_regex_handle);
|
||||
passprompt_regex_handle = NULL;
|
||||
|
||||
/* sudoers_debug_deregister() calls sudo_debug_exit() for us. */
|
||||
sudoers_debug_deregister();
|
||||
@@ -879,6 +935,7 @@ sudoers_io_log_local(int event, const char *buf, unsigned int len,
|
||||
{
|
||||
struct iolog_file *iol;
|
||||
char tbuf[1024];
|
||||
char *newbuf = NULL;
|
||||
int ret = -1;
|
||||
debug_decl(sudoers_io_log_local, SUDOERS_DEBUG_PLUGIN);
|
||||
|
||||
@@ -895,8 +952,13 @@ sudoers_io_log_local(int event, const char *buf, unsigned int len,
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
||||
if (!log_passwords && passprompt_regex_handle != NULL) {
|
||||
if (!iolog_pwfilt_run(passprompt_regex_handle, event, buf, len, &newbuf))
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
||||
/* Write I/O log file entry. */
|
||||
if (iolog_write(iol, buf, len, errstr) == -1)
|
||||
if (iolog_write(iol, newbuf ? newbuf : buf, len, errstr) == -1)
|
||||
goto done;
|
||||
|
||||
/* Write timing file entry. */
|
||||
@@ -914,6 +976,7 @@ sudoers_io_log_local(int event, const char *buf, unsigned int len,
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
free(newbuf);
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2010-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
* Copyright (c) 2010-2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -575,6 +575,7 @@ bad:
|
||||
/*
|
||||
* Convert struct list_members to a comma-separated string with
|
||||
* the given variable name.
|
||||
* XXX - escape commas in member values
|
||||
*/
|
||||
static char *
|
||||
serialize_list(const char *varname, struct list_members *members)
|
||||
@@ -638,7 +639,7 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[],
|
||||
}
|
||||
|
||||
/* Increase the length of command_info as needed, it is *not* checked. */
|
||||
command_info = calloc(68, sizeof(char *));
|
||||
command_info = calloc(70, sizeof(char *));
|
||||
if (command_info == NULL)
|
||||
goto oom;
|
||||
|
||||
@@ -676,6 +677,16 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[],
|
||||
if ((command_info[info_len++] = strdup("iolog_flush=true")) == NULL)
|
||||
goto oom;
|
||||
}
|
||||
if ((command_info[info_len++] = sudo_new_key_val("log_passwords",
|
||||
def_log_passwords ? "true" : "false")) == NULL)
|
||||
goto oom;
|
||||
if (!SLIST_EMPTY(&def_passprompt_regex)) {
|
||||
char *passprompt_regex =
|
||||
serialize_list("passprompt_regex", &def_passprompt_regex);
|
||||
if (passprompt_regex == NULL)
|
||||
goto oom;
|
||||
command_info[info_len++] = passprompt_regex;
|
||||
}
|
||||
if (def_maxseq != NULL) {
|
||||
if ((command_info[info_len++] = sudo_new_key_val("maxseq", def_maxseq)) == NULL)
|
||||
goto oom;
|
||||
|
@@ -1658,6 +1658,7 @@ set_callbacks(void)
|
||||
sudo_defs_table[I_MAILFROM].callback = cb_mailfrom;
|
||||
sudo_defs_table[I_MAILTO].callback = cb_mailto;
|
||||
sudo_defs_table[I_MAILSUB].callback = cb_mailsub;
|
||||
sudo_defs_table[I_PASSPROMPT_REGEX].callback = cb_passprompt_regex;
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user