@@ -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 */
264343static 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
334382static 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