Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ struct mx_hostentry {
struct smtp_auth_mechanisms {
int cram_md5;
int login;
int plain;
};

struct smtp_features {
Expand Down
77 changes: 53 additions & 24 deletions net.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,44 +281,67 @@ smtp_login(int fd, char *login, char* password, const struct smtp_features* feat
}
}

// LOGIN
if (features->auth.login) {
// LOGIN or PLAIN
if (features->auth.login || features->auth.plain) {
if ((config.features & INSECURE) != 0 ||
(config.features & SECURETRANSFER) != 0) {
/* Send AUTH command according to RFC 2554 */
send_remote_command(fd, "AUTH LOGIN");
const char *auth_mechanism = features->auth.login ? "LOGIN" : "PLAIN";
send_remote_command(fd, "AUTH %s", auth_mechanism);
if (read_remote(fd, 0, NULL) != 3) {
syslog(LOG_NOTICE, "remote delivery deferred:"
" AUTH login not available: %s",
neterr);
" AUTH %s not available: %s",
auth_mechanism, neterr);
return (1);
}

len = base64_encode(login, strlen(login), &temp);
if (len < 0) {
if (features->auth.login) {
// LOGIN mechanism
len = base64_encode(login, strlen(login), &temp);
if (len < 0) {
encerr:
syslog(LOG_ERR, "can not encode auth reply: %m");
return (1);
}
syslog(LOG_ERR, "can not encode auth reply: %m");
return (1);
}

send_remote_command(fd, "%s", temp);
free(temp);
res = read_remote(fd, 0, NULL);
if (res != 3) {
syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s",
res == 5 ? "failed" : "deferred", neterr);
return (res == 5 ? -1 : 1);
}
send_remote_command(fd, "%s", temp);
free(temp);
res = read_remote(fd, 0, NULL);
if (res != 3) {
syslog(LOG_NOTICE, "remote delivery %s: AUTH LOGIN failed: %s",
res == 5 ? "failed" : "deferred", neterr);
return (res == 5 ? -1 : 1);
}

len = base64_encode(password, strlen(password), &temp);
if (len < 0)
goto encerr;

send_remote_command(fd, "%s", temp);
free(temp);
} else if (features->auth.plain) {
// PLAIN mechanism
size_t buflen = strlen(login) + strlen(password) + 3;
char *plainbuf = malloc(buflen);
if (plainbuf == NULL) {
syslog(LOG_ERR, "remote delivery deferred: unable to allocate memory");
return (1);
}

snprintf(plainbuf, buflen, "%c%s%c%s", '\0', login, '\0', password);

len = base64_encode(password, strlen(password), &temp);
if (len < 0)
goto encerr;
len = base64_encode(plainbuf, buflen, &temp);
free(plainbuf);
if (len < 0)
goto encerr;

send_remote_command(fd, "%s", temp);
free(temp);
}

send_remote_command(fd, "%s", temp);
free(temp);
res = read_remote(fd, 0, NULL);
if (res != 2) {
syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s",
syslog(LOG_NOTICE, "remote delivery %s: AUTH PLAIN failed: %s",
res == 5 ? "failed" : "deferred", neterr);
return (res == 5 ? -1 : 1);
}
Expand Down Expand Up @@ -381,6 +404,9 @@ static void parse_auth_line(char* line, struct smtp_auth_mechanisms* auth) {
else if (strcmp(method, "LOGIN") == 0)
auth->login = 1;

else if (strcmp(method, "PLAIN") == 0)
auth->plain = 1;

method = strtok(NULL, " ");
}
}
Expand Down Expand Up @@ -469,6 +495,9 @@ int perform_server_greeting(int fd, struct smtp_features* features) {
if (features->auth.login) {
syslog(LOG_DEBUG, " Server supports LOGIN authentication");
}
if (features->auth.plain) {
syslog(LOG_DEBUG, " Server supports PLAIN authentication");
}

return 0;
}
Expand Down