Skip to content

Commit 74387ea

Browse files
committed
fixup! Add support for AUTH PLAIN
1 parent dc6bbc5 commit 74387ea

2 files changed

Lines changed: 114 additions & 84 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);

net.c

Lines changed: 111 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -258,100 +258,132 @@ 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, *authstr;
312+
int len, res = 0;
313+
314+
/* Send AUTH command according to RFC 2554 */
315+
send_remote_command(fd, "AUTH PLAIN");
316+
if (read_remote(fd, 0, NULL) != 3) {
317+
syslog(LOG_NOTICE, "remote delivery deferred:"
318+
" AUTH plain not available: %s",
319+
neterr);
320+
return (1);
321+
}
322+
323+
len = asprintf(&authstr, "%c%s%c%s", '/0', login, '/0', password);
324+
if (len < 0) {
325+
syslog(LOG_ERR, "can not format auth reply: %m");
326+
return (1);
327+
}
328+
329+
len = base64_encode(authstr, len, &temp);
330+
free(authstr);
331+
if (len < 0) {
332+
syslog(LOG_ERR, "can not encode auth reply: %m");
333+
return (1);
334+
}
335+
send_remote_command(fd, "%s", temp);
336+
free(temp);
337+
res = read_remote(fd, 0, NULL);
338+
if (res != 2) {
339+
syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s",
340+
res == 5 ? "failed" : "deferred", neterr);
341+
return (res == 5 ? -1 : 1);
342+
}
343+
344+
return 0;
345+
}
346+
261347
/*
262348
* Handle SMTP authentication
263349
*/
264350
static int
265-
smtp_login(int fd, char *login, char* password, const struct smtp_features* features)
351+
smtp_auth(int fd, char *login, char* password, const struct smtp_features* features)
266352
{
267-
char *temp;
268-
int len, res = 0;
353+
int res = 1;
269354

270355
// CRAM-MD5
271356
if (features->auth.cram_md5) {
272357
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);
358+
if (res != 1) {
359+
return res;
281360
}
282361
}
283362

284-
// LOGIN or PLAIN
285-
if (features->auth.login || features->auth.plain) {
286-
if ((config.features & INSECURE) != 0 ||
363+
if ((config.features & INSECURE) != 0 ||
287364
(config.features & SECURETRANSFER) != 0) {
288-
/* Send AUTH command according to RFC 2554 */
289-
const char *auth_mechanism = features->auth.login ? "LOGIN" : "PLAIN";
290-
send_remote_command(fd, "AUTH %s", auth_mechanism);
291-
if (read_remote(fd, 0, NULL) != 3) {
292-
syslog(LOG_NOTICE, "remote delivery deferred:"
293-
" AUTH %s not available: %s",
294-
auth_mechanism, neterr);
295-
return (1);
296-
}
297365

298-
if (features->auth.login) {
299-
// LOGIN mechanism
300-
len = base64_encode(login, strlen(login), &temp);
301-
if (len < 0) {
302-
encerr:
303-
syslog(LOG_ERR, "can not encode auth reply: %m");
304-
return (1);
305-
}
306-
307-
send_remote_command(fd, "%s", temp);
308-
free(temp);
309-
res = read_remote(fd, 0, NULL);
310-
if (res != 3) {
311-
syslog(LOG_NOTICE, "remote delivery %s: AUTH LOGIN failed: %s",
312-
res == 5 ? "failed" : "deferred", neterr);
313-
return (res == 5 ? -1 : 1);
314-
}
315-
316-
len = base64_encode(password, strlen(password), &temp);
317-
if (len < 0)
318-
goto encerr;
319-
320-
send_remote_command(fd, "%s", temp);
321-
free(temp);
322-
} else if (features->auth.plain) {
323-
// PLAIN mechanism
324-
size_t buflen = strlen(login) + strlen(password) + 3;
325-
char *plainbuf = malloc(buflen);
326-
if (plainbuf == NULL) {
327-
syslog(LOG_ERR, "remote delivery deferred: unable to allocate memory");
328-
return (1);
329-
}
330-
331-
snprintf(plainbuf, buflen, "%c%s%c%s", '\0', login, '\0', password);
332-
333-
len = base64_encode(plainbuf, buflen, &temp);
334-
free(plainbuf);
335-
if (len < 0)
336-
goto encerr;
337-
338-
send_remote_command(fd, "%s", temp);
339-
free(temp);
366+
// LOGIN
367+
if (features->auth.login) {
368+
res = smtp_auth_login(fd, login, password);
369+
if (res != 1) {
370+
return res;
340371
}
372+
}
341373

342-
res = read_remote(fd, 0, NULL);
343-
if (res != 2) {
344-
syslog(LOG_NOTICE, "remote delivery %s: AUTH PLAIN failed: %s",
345-
res == 5 ? "failed" : "deferred", neterr);
346-
return (res == 5 ? -1 : 1);
374+
// PLAIN
375+
if (features->auth.plain) {
376+
res = smtp_auth_plain(fd, login, password);
377+
if (res != 1) {
378+
return res;
347379
}
348-
} else {
349-
syslog(LOG_WARNING, "non-encrypted SMTP login is disabled in config, so skipping it. ");
350-
return (1);
351-
}
380+
}
381+
} else if (features->auth.login || features->auth.plain) {
382+
syslog(LOG_WARNING, "non-encrypted SMTP authentication is disabled in config, so skipping it. ");
383+
return (1);
352384
}
353385

354-
return (0);
386+
return res;
355387
}
356388

357389
static int
@@ -583,17 +615,15 @@ deliver_to_host(struct qitem *it, struct mx_hostentry *host)
583615
*/
584616
if (features.auth.cram_md5 || features.auth.login || features.auth.plain) {
585617
syslog(LOG_INFO, "using SMTP authentication for user %s", a->login);
586-
error = smtp_login(fd, a->login, a->password, &features);
618+
error = smtp_auth(fd, a->login, a->password, &features);
587619
if (error < 0) {
588-
syslog(LOG_ERR, "remote delivery failed:"
589-
" SMTP login failed: %m");
590-
snprintf(errmsg, sizeof(errmsg), "SMTP login to %s failed", host->host);
620+
snprintf(errmsg, sizeof(errmsg), "SMTP auth to %s failed", host->host);
591621
error = -1;
592622
goto out;
593623
}
594-
/* SMTP login is not available, so try without */
624+
/* SMTP auth is not available, so try without */
595625
else if (error > 0) {
596-
syslog(LOG_WARNING, "SMTP login not available. Trying without.");
626+
syslog(LOG_WARNING, "SMTP auth not available. Trying without.");
597627
}
598628
} else {
599629
syslog(LOG_ERR, "No supported AUTH mechanisms in common with server."

0 commit comments

Comments
 (0)