Skip to content

Commit

Permalink
Make it possible to use the AnonRejectPasswords directive to require …
Browse files Browse the repository at this point in the history
…email-like

anonymous passwords.
  • Loading branch information
Castaglia committed Jun 9, 2015
1 parent 59d6a4b commit 74ca739
Show file tree
Hide file tree
Showing 4 changed files with 365 additions and 38 deletions.
35 changes: 34 additions & 1 deletion doc/modules/mod_auth.html
Expand Up @@ -85,7 +85,7 @@ <h2><a name="AllowEmptyPasswords">AllowEmptyPasswords</a></h2>
<p>
<hr>
<h2><a name="AnonRejectPasswords">AnonRejectPasswords</a></h2>
<strong>Syntax:</strong> AnonRejectPasswords <em>pattern</em><br>
<strong>Syntax:</strong> AnonRejectPasswords <em>pattern [flags]</em><br>
<strong>Default:</strong> None<br>
<strong>Context:</strong> <code>&lt;Anonymous&gt;</code><br>
<strong>Module:</strong> mod_auth<br>
Expand All @@ -104,6 +104,39 @@ <h2><a name="AnonRejectPasswords">AnonRejectPasswords</a></h2>
AnonRejectPasswords @evil\.org$
</pre>

<p>
The optional <em>flags</em> parameter can be used to specify flags for the
given regular expression; currently the supported flags are:
<ul>
<li><code>[NC|nocase]</code>
</ul>
Thus for a case-insensitive pattern, you would use:
<pre>
# Reject all <Anonymous> logins that use "evil.org" as part of the password
AnonRejectPasswords @evil\.org$ [NC]
</pre>
or:
<pre>
# Reject all <Anonymous> logins that use "evil.org" as part of the password
AnonRejectPasswords @evil\.org$ [nocase]
</pre>

<p>
If you want to reject any anonymous passwords which do <b>not</b> match the
pattern, then prefix your pattern with the <code>!</code> (exclamation point)
character:
<pre>
# Reject all <Anonymous> logins that do NOT use "good.org" as part of the password
AnonRejectPasswords !@good\.org$ [nocase]
</pre>
<b>Note</b> that this also allows you to use <code>AnonRejectPasswords</code>
to <b>require</b> that your anonymous logins use email-like passwords:
<pre>
# Require anonymous passwords that look like email addresses. See:
# <a href="http://www.regular-expressions.info/email.html">http://www.regular-expressions.info/email.html</a>
AnonRejectPasswords !^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$ [NC]
</pre>

<p>
<hr>
<h2><a name="CreateHome">CreateHome</a></h2>
Expand Down
54 changes: 37 additions & 17 deletions modules/mod_auth.c
Expand Up @@ -1013,28 +1013,38 @@ static int setup_env(pool *p, cmd_rec *cmd, char *user, char *pass) {

if (c) {
anongroup = get_param_ptr(c->subset, "GroupName", FALSE);
if (!anongroup)
if (anongroup == NULL) {
anongroup = get_param_ptr(main_server->conf, "GroupName",FALSE);
}

#ifdef PR_USE_REGEX
/* Check for configured AnonRejectPasswords regex here, and fail the login
* if the given password matches the regex.
*/
#ifdef PR_USE_REGEX
if ((tmpc = find_config(c->subset, CONF_PARAM, "AnonRejectPasswords",
FALSE)) != NULL) {
int re_res;
pr_regex_t *pw_regex = (pr_regex_t *) tmpc->argv[0];
tmpc = find_config(c->subset, CONF_PARAM, "AnonRejectPasswords", FALSE);
if (tmpc != NULL) {
int re_notmatch;
pr_regex_t *pw_regex;

if (pw_regex && pass &&
((re_res = pr_regexp_exec(pw_regex, pass, 0, NULL, 0, 0, 0)) == 0)) {
char errstr[200] = {'\0'};
pw_regex = (pr_regex_t *) tmpc->argv[0];
re_notmatch = *((int *) tmpc->argv[1]);

pr_regexp_error(re_res, pw_regex, errstr, sizeof(errstr));
pr_log_auth(PR_LOG_NOTICE, "ANON %s: AnonRejectPasswords denies login",
origuser);
if (pw_regex != NULL &&
pass != NULL) {
int re_res;

re_res = pr_regexp_exec(pw_regex, pass, 0, NULL, 0, 0, 0);
if (re_res == 0 ||
(re_res != 0 && re_notmatch == TRUE)) {
char errstr[200] = {'\0'};

pr_regexp_error(re_res, pw_regex, errstr, sizeof(errstr));
pr_log_auth(PR_LOG_NOTICE,
"ANON %s: AnonRejectPasswords denies login", origuser);

pr_event_generate("mod_auth.anon-reject-passwords", session.c);
goto auth_failure;
pr_event_generate("mod_auth.anon-reject-passwords", session.c);
goto auth_failure;
}
}
}
#endif
Expand Down Expand Up @@ -2725,8 +2735,10 @@ MODRET set_anonrequirepassword(cmd_rec *cmd) {
/* usage: AnonRejectPasswords pattern [flags] */
MODRET set_anonrejectpasswords(cmd_rec *cmd) {
#ifdef PR_USE_REGEX
config_rec *c;
pr_regex_t *pre = NULL;
int regex_flags = REG_EXTENDED|REG_NOSUB, res = 0;
int notmatch = FALSE, regex_flags = REG_EXTENDED|REG_NOSUB, res = 0;
char *pattern = NULL;

if (cmd->argc-1 < 1 ||
cmd->argc-1 > 2) {
Expand Down Expand Up @@ -2759,7 +2771,13 @@ MODRET set_anonrejectpasswords(cmd_rec *cmd) {

pre = pr_regexp_alloc(&auth_module);

res = pr_regexp_compile(pre, cmd->argv[1], regex_flags);
pattern = cmd->argv[1];
if (*pattern == '!') {
notmatch = TRUE;
pattern++;
}

res = pr_regexp_compile(pre, pattern, regex_flags);
if (res != 0) {
char errstr[200] = {'\0'};

Expand All @@ -2770,7 +2788,9 @@ MODRET set_anonrejectpasswords(cmd_rec *cmd) {
cmd->argv[1], "': ", errstr, NULL));
}

(void) add_config_param(cmd->argv[0], 1, pre);
c = add_config_param(cmd->argv[0], 2, pre, NULL);
c->argv[1] = palloc(c->pool, sizeof(int));
*((int *) c->argv[1]) = notmatch;
return PR_HANDLED(cmd);

#else
Expand Down
23 changes: 16 additions & 7 deletions src/regexp.c
Expand Up @@ -2,7 +2,7 @@
* ProFTPD - FTP server daemon
* Copyright (c) 1997, 1998 Public Flood Software
* Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
* Copyright (c) 2001-2013 The ProFTPD Project team
* Copyright (c) 2001-2015 The ProFTPD Project team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -24,9 +24,7 @@
* the source code for OpenSSL in the source distribution.
*/

/* Regex management code
* $Id: regexp.c,v 1.20 2013-03-14 21:49:19 castaglia Exp $
*/
/* Regex management code. */

#include "conf.h"

Expand All @@ -45,7 +43,7 @@ struct regexp_rec {
/* For callers wishing to use POSIX REs */
regex_t *re;

/* For calles wishing to use PCRE REs */
/* For callers wishing to use PCRE REs */
pcre *pcre;
pcre_extra *pcre_extra;

Expand Down Expand Up @@ -190,7 +188,7 @@ void pr_regexp_free(module *m, pr_regex_t *pre) {
#ifdef PR_USE_PCRE
static int regexp_compile_pcre(pr_regex_t *pre, const char *pattern,
int flags) {
int err_offset;
int err_offset, study_flags = 0;

if (pre == NULL ||
pattern == NULL) {
Expand All @@ -213,9 +211,12 @@ static int regexp_compile_pcre(pr_regex_t *pre, const char *pattern,
}

/* Study the pattern as well, just in case. */
#ifdef PCRE_STUDY_JIT_COMPILE
study_flags = PCRE_STUDY_JIT_COMPILE;
#endif /* PCRE_STUDY_JIT_COMPILE */
pr_trace_msg(trace_channel, 9, "studying pattern '%s' for PCRE extra data",
pattern);
pre->pcre_extra = pcre_study(pre->pcre, 0, &(pre->pcre_errstr));
pre->pcre_extra = pcre_study(pre->pcre, study_flags, &(pre->pcre_errstr));
return 0;
}
#endif /* PR_USE_PCRE */
Expand Down Expand Up @@ -448,6 +449,14 @@ int pr_regexp_exec(pr_regex_t *pre, const char *str, size_t nmatches,
#endif /* PR_USE_PCRE */

res = regexp_exec_posix(pre, str, nmatches, matches, flags);

/* Make sure that we return a negative value to indicate a failed match;
* PCRE already does this.
*/
if (res == REG_NOMATCH) {
res = -1;
}

return res;
}

Expand Down

0 comments on commit 74ca739

Please sign in to comment.