upas/smtp: handle temporary authentication failures

under heavy load, factotum can return a "too much activity" error,
which upas/smtpd and upas/smtp should consider a temporary error
instead of a permanent one.
This commit is contained in:
cinap_lenrek 2019-06-20 12:13:51 +02:00
parent 4ff5a4febb
commit 56e71d5260
4 changed files with 32 additions and 10 deletions

View file

@ -108,3 +108,12 @@ returnable(char *path)
{ {
return strcmp(path, "/dev/null") != 0; return strcmp(path, "/dev/null") != 0;
} }
int
temperror(void)
{
char err[ERRMAX];
rerrstr(err, sizeof(err));
return strstr(err, "too much activity") != nil || strstr(err, "temporary problem") != nil;
}

View file

@ -37,6 +37,7 @@ int shellchars(char*);
String *escapespecial(String*); String *escapespecial(String*);
String *unescapespecial(String*); String *unescapespecial(String*);
int returnable(char*); int returnable(char*);
int temperror(void);
/* folder.c */ /* folder.c */
Biobuf *openfolder(char*, long); Biobuf *openfolder(char*, long);

View file

@ -30,8 +30,8 @@ void quit(char*);
char* rcptto(char*); char* rcptto(char*);
char *rewritezone(char *); char *rewritezone(char *);
#define Retry "Retry, Temporary Failure" char Retry[] = "Retry, Temporary Failure";
#define Giveup "Permanent Failure" char Giveup[] = "Permanent Failure";
String *reply; /* last reply */ String *reply; /* last reply */
String *toline; String *toline;
@ -468,8 +468,12 @@ smtpcram(DS *ds)
n = auth_respond(ch, l, usr, sizeof usr, rbuf, sizeof rbuf, auth_getkey, n = auth_respond(ch, l, usr, sizeof usr, rbuf, sizeof rbuf, auth_getkey,
"proto=cram role=client server=%q user=%q", "proto=cram role=client server=%q user=%q",
ds->host, user); ds->host, user);
if(n == -1) if(n == -1){
return "cannot find SMTP password"; if(temperror())
return Retry;
syslog(0, "smtp.fail", "failed to get challenge response: %r");
return Giveup;
}
if(usr[0] == 0) if(usr[0] == 0)
return "cannot find user name"; return "cannot find user name";
for(i = 0; i < n; i++) for(i = 0; i < n; i++)
@ -498,6 +502,8 @@ doauth(char *methods)
"proto=pass service=smtp server=%q user=%q", "proto=pass service=smtp server=%q user=%q",
ds.host, user); ds.host, user);
if (p == nil) { if (p == nil) {
if(temperror())
return Retry;
syslog(0, "smtp.fail", "failed to get userpasswd: %r"); syslog(0, "smtp.fail", "failed to get userpasswd: %r");
return Giveup; return Giveup;
} }

View file

@ -1685,9 +1685,7 @@ auth(String *mech, String *resp)
memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64)); memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64));
user = s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1; user = s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1;
pass = user + strlen(user) + 1; pass = user + strlen(user) + 1;
// ai = auth_userpasswd(user, pass); authenticated = passauth(user, pass) != -1;
// authenticated = ai != nil;
authenticated = passauth(user, pass) != -1;
memset(pass, 'X', strlen(pass)); memset(pass, 'X', strlen(pass));
goto windup; goto windup;
} }
@ -1727,8 +1725,13 @@ windup:
reply("235 2.0.0 Authentication successful\r\n"); reply("235 2.0.0 Authentication successful\r\n");
} else { } else {
rejectcount++; rejectcount++;
reply("535 5.7.1 Authentication failed\r\n"); if(temperror()){
syslog(0, "smtpd", "temporary authentication failure: %r");
reply("454 4.7.0 Temporary authentication failure\r\n");
} else {
syslog(0, "smtpd", "authentication failed: %r"); syslog(0, "smtpd", "authentication failed: %r");
reply("535 5.7.1 Authentication failed\r\n");
}
} }
goto bomb_out; goto bomb_out;
} }
@ -1738,6 +1741,9 @@ windup:
chs = auth_challenge("proto=cram role=server"); chs = auth_challenge("proto=cram role=server");
if (chs == nil) { if (chs == nil) {
rejectcount++; rejectcount++;
if(temperror())
reply("454 4.7.0 Temporary authentication failure\r\n");
else
reply("501 5.7.5 Couldn't get CRAM-MD5 challenge\r\n"); reply("501 5.7.5 Couldn't get CRAM-MD5 challenge\r\n");
goto bomb_out; goto bomb_out;
} }