Skip to content

Commit 33e5b79

Browse files
committed
Add support for AUTH PLAIN
1 parent 7f88bbe commit 33e5b79

3 files changed

Lines changed: 114 additions & 61 deletions

File tree

crypto.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ smtp_auth_md5(int fd, char *login, char *password)
383383
" AUTH cram-md5 not available: %s", neterr);
384384
/* if cram-md5 is not available */
385385
free(temp);
386-
return (-1);
386+
return (1);
387387
}
388388

389389
/* skip 3 char status + 1 char space */
@@ -405,7 +405,7 @@ smtp_auth_md5(int fd, char *login, char *password)
405405
len = base64_encode(buffer, strlen(buffer), &temp);
406406
if (len < 0) {
407407
syslog(LOG_ERR, "can not encode auth reply: %m");
408-
return (-1);
408+
return (1);
409409
}
410410

411411
/* send answer */
@@ -414,7 +414,7 @@ smtp_auth_md5(int fd, char *login, char *password)
414414
if (read_remote(fd, 0, NULL) != 2) {
415415
syslog(LOG_WARNING, "remote delivery deferred:"
416416
" AUTH cram-md5 failed: %s", neterr);
417-
return (-2);
417+
return (-1);
418418
}
419419

420420
return (0);

dma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ struct mx_hostentry {
166166
struct smtp_auth_mechanisms {
167167
int cram_md5;
168168
int login;
169+
int plain;
169170
};
170171

171172
struct smtp_features {

net.c

Lines changed: 110 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -258,77 +258,125 @@ read_remote(int fd, int extbufsize, char *extbuf)
258258
return (-1);
259259
}
260260

261+
static int
262+
smtp_auth_login(int fd, char *login, char* password)
263+
{
264+
char *temp;
265+
int len, res = 0;
266+
267+
/* Send AUTH command according to RFC 2554 */
268+
send_remote_command(fd, "AUTH LOGIN");
269+
if (read_remote(fd, 0, NULL) != 3) {
270+
syslog(LOG_NOTICE, "remote delivery deferred:"
271+
" AUTH login not available: %s",
272+
neterr);
273+
return (1);
274+
}
275+
276+
len = base64_encode(login, strlen(login), &temp);
277+
if (len < 0) {
278+
encerr:
279+
syslog(LOG_ERR, "can not encode auth reply: %m");
280+
return (1);
281+
}
282+
283+
send_remote_command(fd, "%s", temp);
284+
free(temp);
285+
res = read_remote(fd, 0, NULL);
286+
if (res != 3) {
287+
syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s",
288+
res == 5 ? "failed" : "deferred", neterr);
289+
return (res == 5 ? -1 : 1);
290+
}
291+
292+
len = base64_encode(password, strlen(password), &temp);
293+
if (len < 0)
294+
goto encerr;
295+
296+
send_remote_command(fd, "%s", temp);
297+
free(temp);
298+
res = read_remote(fd, 0, NULL);
299+
if (res != 2) {
300+
syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s",
301+
res == 5 ? "failed" : "deferred", neterr);
302+
return (res == 5 ? -1 : 1);
303+
}
304+
305+
return (0);
306+
}
307+
308+
static int
309+
smtp_auth_plain(int fd, char *login, char* password)
310+
{
311+
char *temp, *authdata;
312+
int len, res = 0;
313+
314+
len = asprintf(&authdata, "%c%s%c%s", '\0', login, '\0', password);
315+
if (len < 0) {
316+
syslog(LOG_ERR, "can not format auth reply: %m");
317+
return (1);
318+
}
319+
320+
len = base64_encode(authdata, len, &temp);
321+
free(authdata);
322+
if (len < 0) {
323+
syslog(LOG_ERR, "can not encode auth reply: %m");
324+
return (1);
325+
}
326+
327+
/* Send AUTH command according to RFC 2554 */
328+
send_remote_command(fd, "AUTH PLAIN %s", temp);
329+
free(temp);
330+
res = read_remote(fd, 0, NULL);
331+
if (res != 2) {
332+
syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s",
333+
res == 5 ? "failed" : "deferred", neterr);
334+
return (res == 5 ? -1 : 1);
335+
}
336+
337+
return (0);
338+
}
339+
261340
/*
262341
* Handle SMTP authentication
263342
*/
264343
static int
265-
smtp_login(int fd, char *login, char* password, const struct smtp_features* features)
344+
smtp_auth(int fd, char *login, char* password, const struct smtp_features* features)
266345
{
267-
char *temp;
268-
int len, res = 0;
346+
int res = 1;
269347

270348
// CRAM-MD5
271349
if (features->auth.cram_md5) {
272350
res = smtp_auth_md5(fd, login, password);
273-
if (res == 0) {
274-
return (0);
275-
} else if (res == -2) {
276-
/*
277-
* If the return code is -2, then then the login attempt failed,
278-
* do not try other login mechanisms
279-
*/
280-
return (1);
351+
if (res != 1) {
352+
return (res);
281353
}
282354
}
283355

284-
// LOGIN
285-
if (features->auth.login) {
286-
if ((config.features & INSECURE) != 0 ||
356+
if ((config.features & INSECURE) != 0 ||
287357
(config.features & SECURETRANSFER) != 0) {
288-
/* Send AUTH command according to RFC 2554 */
289-
send_remote_command(fd, "AUTH LOGIN");
290-
if (read_remote(fd, 0, NULL) != 3) {
291-
syslog(LOG_NOTICE, "remote delivery deferred:"
292-
" AUTH login not available: %s",
293-
neterr);
294-
return (1);
295-
}
296-
297-
len = base64_encode(login, strlen(login), &temp);
298-
if (len < 0) {
299-
encerr:
300-
syslog(LOG_ERR, "can not encode auth reply: %m");
301-
return (1);
302-
}
303358

304-
send_remote_command(fd, "%s", temp);
305-
free(temp);
306-
res = read_remote(fd, 0, NULL);
307-
if (res != 3) {
308-
syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s",
309-
res == 5 ? "failed" : "deferred", neterr);
310-
return (res == 5 ? -1 : 1);
359+
// LOGIN
360+
if (features->auth.login) {
361+
res = smtp_auth_login(fd, login, password);
362+
if (res != 1) {
363+
return (res);
311364
}
365+
}
312366

313-
len = base64_encode(password, strlen(password), &temp);
314-
if (len < 0)
315-
goto encerr;
316-
317-
send_remote_command(fd, "%s", temp);
318-
free(temp);
319-
res = read_remote(fd, 0, NULL);
320-
if (res != 2) {
321-
syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s",
322-
res == 5 ? "failed" : "deferred", neterr);
323-
return (res == 5 ? -1 : 1);
367+
// PLAIN
368+
if (features->auth.plain) {
369+
res = smtp_auth_plain(fd, login, password);
370+
if (res != 1) {
371+
return (res);
324372
}
325-
} else {
326-
syslog(LOG_WARNING, "non-encrypted SMTP login is disabled in config, so skipping it. ");
327-
return (1);
328-
}
373+
}
374+
} else if (features->auth.login || features->auth.plain) {
375+
syslog(LOG_WARNING, "non-encrypted SMTP authentication is disabled in config, so skipping it.");
376+
return (1);
329377
}
330378

331-
return (0);
379+
return (res);
332380
}
333381

334382
static int
@@ -381,6 +429,9 @@ static void parse_auth_line(char* line, struct smtp_auth_mechanisms* auth) {
381429
else if (strcmp(method, "LOGIN") == 0)
382430
auth->login = 1;
383431

432+
else if (strcmp(method, "PLAIN") == 0)
433+
auth->plain = 1;
434+
384435
method = strtok(NULL, " ");
385436
}
386437
}
@@ -469,6 +520,9 @@ int perform_server_greeting(int fd, struct smtp_features* features) {
469520
if (features->auth.login) {
470521
syslog(LOG_DEBUG, " Server supports LOGIN authentication");
471522
}
523+
if (features->auth.plain) {
524+
syslog(LOG_DEBUG, " Server supports PLAIN authentication");
525+
}
472526

473527
return 0;
474528
}
@@ -553,17 +607,15 @@ deliver_to_host(struct qitem *it, struct mx_hostentry *host)
553607
* encryption.
554608
*/
555609
syslog(LOG_INFO, "using SMTP authentication for user %s", a->login);
556-
error = smtp_login(fd, a->login, a->password, &features);
610+
error = smtp_auth(fd, a->login, a->password, &features);
557611
if (error < 0) {
558-
syslog(LOG_ERR, "remote delivery failed:"
559-
" SMTP login failed: %m");
560-
snprintf(errmsg, sizeof(errmsg), "SMTP login to %s failed", host->host);
612+
snprintf(errmsg, sizeof(errmsg), "SMTP auth to %s failed", host->host);
561613
error = -1;
562614
goto out;
563615
}
564-
/* SMTP login is not available, so try without */
616+
/* SMTP auth is not available, so try without */
565617
else if (error > 0) {
566-
syslog(LOG_WARNING, "SMTP login not available. Trying without.");
618+
syslog(LOG_WARNING, "SMTP auth not available. Trying without.");
567619
}
568620
}
569621

0 commit comments

Comments
 (0)