@@ -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 */
264350static 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
357389static 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