@@ -281,44 +281,67 @@ smtp_login(int fd, char *login, char* password, const struct smtp_features* feat
281281 }
282282 }
283283
284- // LOGIN
285- if (features -> auth .login ) {
284+ // LOGIN or PLAIN
285+ if (features -> auth .login || features -> auth . plain ) {
286286 if ((config .features & INSECURE ) != 0 ||
287287 (config .features & SECURETRANSFER ) != 0 ) {
288288 /* Send AUTH command according to RFC 2554 */
289- send_remote_command (fd , "AUTH LOGIN" );
289+ const char * auth_mechanism = features -> auth .login ? "LOGIN" : "PLAIN" ;
290+ send_remote_command (fd , "AUTH %s" , auth_mechanism );
290291 if (read_remote (fd , 0 , NULL ) != 3 ) {
291292 syslog (LOG_NOTICE , "remote delivery deferred:"
292- " AUTH login not available: %s" ,
293- neterr );
293+ " AUTH %s not available: %s" ,
294+ auth_mechanism , neterr );
294295 return (1 );
295296 }
296297
297- len = base64_encode (login , strlen (login ), & temp );
298- if (len < 0 ) {
298+ if (features -> auth .login ) {
299+ // LOGIN mechanism
300+ len = base64_encode (login , strlen (login ), & temp );
301+ if (len < 0 ) {
299302encerr :
300- syslog (LOG_ERR , "can not encode auth reply: %m" );
301- return (1 );
302- }
303+ syslog (LOG_ERR , "can not encode auth reply: %m" );
304+ return (1 );
305+ }
303306
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 );
311- }
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 );
312332
313- len = base64_encode (password , strlen (password ), & temp );
314- if (len < 0 )
315- goto encerr ;
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 );
340+ }
316341
317- send_remote_command (fd , "%s" , temp );
318- free (temp );
319342 res = read_remote (fd , 0 , NULL );
320343 if (res != 2 ) {
321- syslog (LOG_NOTICE , "remote delivery %s: Authentication failed: %s" ,
344+ syslog (LOG_NOTICE , "remote delivery %s: AUTH PLAIN failed: %s" ,
322345 res == 5 ? "failed" : "deferred" , neterr );
323346 return (res == 5 ? -1 : 1 );
324347 }
@@ -381,6 +404,9 @@ static void parse_auth_line(char* line, struct smtp_auth_mechanisms* auth) {
381404 else if (strcmp (method , "LOGIN" ) == 0 )
382405 auth -> login = 1 ;
383406
407+ else if (strcmp (method , "PLAIN" ) == 0 )
408+ auth -> plain = 1 ;
409+
384410 method = strtok (NULL , " " );
385411 }
386412}
@@ -469,6 +495,9 @@ int perform_server_greeting(int fd, struct smtp_features* features) {
469495 if (features -> auth .login ) {
470496 syslog (LOG_DEBUG , " Server supports LOGIN authentication" );
471497 }
498+ if (features -> auth .plain ) {
499+ syslog (LOG_DEBUG , " Server supports PLAIN authentication" );
500+ }
472501
473502 return 0 ;
474503}
0 commit comments