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;
}
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 *unescapespecial(String*);
int returnable(char*);
int temperror(void);
/* folder.c */
Biobuf *openfolder(char*, long);

View file

@ -30,8 +30,8 @@ void quit(char*);
char* rcptto(char*);
char *rewritezone(char *);
#define Retry "Retry, Temporary Failure"
#define Giveup "Permanent Failure"
char Retry[] = "Retry, Temporary Failure";
char Giveup[] = "Permanent Failure";
String *reply; /* last reply */
String *toline;
@ -468,8 +468,12 @@ smtpcram(DS *ds)
n = auth_respond(ch, l, usr, sizeof usr, rbuf, sizeof rbuf, auth_getkey,
"proto=cram role=client server=%q user=%q",
ds->host, user);
if(n == -1)
return "cannot find SMTP password";
if(n == -1){
if(temperror())
return Retry;
syslog(0, "smtp.fail", "failed to get challenge response: %r");
return Giveup;
}
if(usr[0] == 0)
return "cannot find user name";
for(i = 0; i < n; i++)
@ -498,6 +502,8 @@ doauth(char *methods)
"proto=pass service=smtp server=%q user=%q",
ds.host, user);
if (p == nil) {
if(temperror())
return Retry;
syslog(0, "smtp.fail", "failed to get userpasswd: %r");
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));
user = s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1;
pass = user + strlen(user) + 1;
// ai = auth_userpasswd(user, pass);
// authenticated = ai != nil;
authenticated = passauth(user, pass) != -1;
authenticated = passauth(user, pass) != -1;
memset(pass, 'X', strlen(pass));
goto windup;
}
@ -1727,8 +1725,13 @@ windup:
reply("235 2.0.0 Authentication successful\r\n");
} else {
rejectcount++;
reply("535 5.7.1 Authentication failed\r\n");
syslog(0, "smtpd", "authentication failed: %r");
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");
reply("535 5.7.1 Authentication failed\r\n");
}
}
goto bomb_out;
}
@ -1738,7 +1741,10 @@ windup:
chs = auth_challenge("proto=cram role=server");
if (chs == nil) {
rejectcount++;
reply("501 5.7.5 Couldn't get CRAM-MD5 challenge\r\n");
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");
goto bomb_out;
}
reply("334 %.*[\r\n", chs->nchal, chs->chal);