]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: smtp-command-parser - Always safely clear potentially secret authentication...
authorStephan Bosch <stephan.bosch@open-xchange.com>
Mon, 2 Oct 2023 23:27:29 +0000 (01:27 +0200)
committerstephan.bosch <stephan.bosch@open-xchange.com>
Mon, 23 Oct 2023 15:50:54 +0000 (15:50 +0000)
src/lib-smtp/smtp-command-parser.c
src/lib-smtp/smtp-command-parser.h

index 7386634e5966f00f0abf1faadcc904b96c402805..5a9f17d0f3ff8f553e6745be4d2f8b0015c24d85 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "buffer.h"
 #include "unichar.h"
+#include "safe-memset.h"
 #include "istream.h"
 #include "istream-failure-at.h"
 #include "istream-sized.h"
@@ -50,6 +51,7 @@ struct smtp_command_parser {
        char *error;
 
        bool auth_response:1;
+       bool auth_response_buffered:1;
 };
 
 static inline void ATTR_FORMAT(3, 4)
@@ -97,10 +99,25 @@ smtp_command_parser_init(struct istream *input,
        return parser;
 }
 
+void smtp_command_parser_clear(struct smtp_command_parser *parser)
+{
+       if (parser->auth_response_buffered) {
+               if (parser->line_buffer != NULL)
+                       buffer_clear_safe(parser->line_buffer);
+               if (parser->state.cmd_params != NULL) {
+                       safe_memset(parser->state.cmd_params, 0,
+                                   strlen(parser->state.cmd_params));
+               }
+       }
+       parser->auth_response_buffered = FALSE;
+}
+
 void smtp_command_parser_deinit(struct smtp_command_parser **_parser)
 {
        struct smtp_command_parser *parser = *_parser;
 
+       smtp_command_parser_clear(parser);
+
        i_stream_unref(&parser->data);
        buffer_free(&parser->line_buffer);
        i_free(parser->state.cmd_name);
@@ -113,6 +130,8 @@ void smtp_command_parser_deinit(struct smtp_command_parser **_parser)
 
 static void smtp_command_parser_restart(struct smtp_command_parser *parser)
 {
+       smtp_command_parser_clear(parser);
+
        buffer_free(&parser->line_buffer);
        i_free(parser->state.cmd_name);
        i_free(parser->state.cmd_params);
@@ -238,6 +257,8 @@ static int smtp_command_parse_parameters(struct smtp_command_parser *parser)
                                parser->line_buffer = buffer_create_dynamic(
                                        default_pool, buf_size);
                        }
+                       if (parser->auth_response)
+                               parser->auth_response_buffered = TRUE;
                        buffer_append(parser->line_buffer, parser->cur,
                                      (p - parser->cur));
 
@@ -267,6 +288,8 @@ static int smtp_command_parse_parameters(struct smtp_command_parser *parser)
                return -1;
        }
 
+       if (parser->auth_response)
+               parser->auth_response_buffered = TRUE;
        if (parser->line_buffer == NULL) {
                /* Buffered only in input stream */
                parser->state.cmd_params = i_strdup_until(parser->cur, mp);
index c9b56a1b8a826869228833a5b9bab61bf7ba7412..9e378be67a86b3be30d170da12e4b602b839be0e 100644 (file)
@@ -24,6 +24,13 @@ smtp_command_parser_init(struct istream *input,
                         const struct smtp_command_limits *limits) ATTR_NULL(2);
 void smtp_command_parser_deinit(struct smtp_command_parser **_parser);
 
+/* Clear any sensitive data in the parser. Any returned auth response line will
+   be cleared now. Call this as soon as the returned auth response is not
+   needed anymore. It will be cleared eventually when the parser continues with
+   the next command/auth response and when it is deinitialized, but that is not
+   optimal. */
+void smtp_command_parser_clear(struct smtp_command_parser *parser);
+
 void smtp_command_parser_set_stream(struct smtp_command_parser *parser,
                                    struct istream *input);