From: Stephan Bosch Date: Fri, 2 Nov 2018 09:11:35 +0000 (+0100) Subject: lib-smtp: reply: Make parsing enhanced status codes available as a separate function. X-Git-Tag: 2.3.9~1096 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=173f199af0dfb3fe8fbf4b8c88227f177ab4a595;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: reply: Make parsing enhanced status codes available as a separate function. --- diff --git a/src/lib-smtp/smtp-reply-parser.c b/src/lib-smtp/smtp-reply-parser.c index d47eab4513..cd35ffb731 100644 --- a/src/lib-smtp/smtp-reply-parser.c +++ b/src/lib-smtp/smtp-reply-parser.c @@ -89,6 +89,59 @@ struct smtp_reply_parser { bool ehlo:1; }; +bool smtp_reply_parse_enhanced_code(const char *text, + struct smtp_reply_enhanced_code *enh_code_r, + const char **pos_r) +{ + const char *p = text; + unsigned int digits, x, y, z; + + i_zero(enh_code_r); + + /* status-code ::= class "." subject "." detail + class ::= "2" / "4" / "5" + subject ::= 1*3digit + detail ::= 1*3digit + */ + + /* class */ + if (p[1] != '.' || (p[0] != '2' && p[0] != '4' && p[0] != '5')) + return FALSE; + x = p[0] - '0'; + p += 2; + + /* subject */ + digits = 0; + y = 0; + while (*p != '\0' && i_isdigit(*p) && digits++ < 3) { + y = y*10 + (*p - '0'); + p++; + } + if (digits == 0 || *p != '.') + return FALSE; + p++; + + /* detail */ + digits = 0; + z = 0; + while (*p != '\0' && i_isdigit(*p) && digits++ < 3) { + z = z*10 + (*p - '0'); + p++; + } + if (digits == 0 || (pos_r == NULL && *p != '\0')) + return FALSE; + + if (pos_r != NULL) { + /* code is syntactically valid; strip code from textstring */ + *pos_r = p; + } + + enh_code_r->x = x; + enh_code_r->y = y; + enh_code_r->z = z; + return TRUE; +} + static inline void ATTR_FORMAT(2, 3) smtp_reply_parser_error(struct smtp_reply_parser *parser, const char *format, ...) @@ -272,84 +325,51 @@ static inline const char *_chr_sanitize(unsigned char c) } static void -smtp_reply_parse_enhanced_code(struct smtp_reply_parser *parser, - const char **pos) +smtp_reply_parser_parse_enhanced_code(const char *text, + struct smtp_reply_parser *parser, + const char **pos_r) { - const char *p = *pos; - unsigned int digits, x, y, z; - unsigned int prevx = parser->state.reply->enhanced_code.x, - prevy = parser->state.reply->enhanced_code.y, - prevz = parser->state.reply->enhanced_code.z; + struct smtp_reply_enhanced_code code; + struct smtp_reply_enhanced_code *cur_code = + &parser->state.reply->enhanced_code; - if (prevx == 9) + if (cur_code->x == 9) return; /* failed on earlier line */ - parser->state.reply->enhanced_code.x = 9; - parser->state.reply->enhanced_code.y = 0; - parser->state.reply->enhanced_code.z = 0; - - /* status-code ::= class "." subject "." detail - class ::= "2" / "4" / "5" - subject ::= 1*3digit - detail ::= 1*3digit - */ - - /* class */ - if (p[1] != '.' || (p[0] != '2' && p[0] != '4' && p[0] != '5')) + if (!smtp_reply_parse_enhanced_code(text, &code, pos_r)) { + /* failed to parse an enhanced code */ + i_zero(cur_code); + cur_code->x = 9; return; - x = p[0] - '0'; - p += 2; - - /* subject */ - digits = 0; - y = 0; - while (*p != '\0' && i_isdigit(*p) && digits++ < 3) { - y = y*10 + (*p - '0'); - p++; } - if (digits == 0 || *p != '.') - return; - p++; - /* detail */ - digits = 0; - z = 0; - while (*p != '\0' && i_isdigit(*p) && digits++ < 3) { - z = z*10 + (*p - '0'); - p++; - } - if (digits == 0 || (*p != ' ' && *p != '\r' && *p != '\n')) + if (**pos_r != ' ' && **pos_r != '\r' && **pos_r != '\n') return; - p++; - - /* code is syntactically valid; strip code from textstring */ - *pos = p; + (*pos_r)++; /* check for match with status */ - if (x != parser->state.reply->status / 100) { + if (code.x != parser->state.reply->status / 100) { /* ignore code */ return; } /* check for code consistency */ if (parser->state.line > 0 && - (prevx != x || prevy != y || prevz != z)) { + (cur_code->x != code.x || cur_code->y != code.y || + cur_code->z != code.z)) { /* ignore code */ return; } - parser->state.reply->enhanced_code.x = x; - parser->state.reply->enhanced_code.y = y; - parser->state.reply->enhanced_code.z = z; + *cur_code = code; } static void smtp_reply_parser_finish_line(struct smtp_reply_parser *parser) { const char *text = str_c(parser->strbuf); - if (parser->enhanced_codes && str_len(parser->strbuf) > 5) { - smtp_reply_parse_enhanced_code(parser, &text); - } + if (parser->enhanced_codes && str_len(parser->strbuf) > 5) + smtp_reply_parser_parse_enhanced_code(text, parser, &text); parser->state.line++; parser->state.reply_size += str_len(parser->strbuf); diff --git a/src/lib-smtp/smtp-reply-parser.h b/src/lib-smtp/smtp-reply-parser.h index bbafd7542b..4ffb32af24 100644 --- a/src/lib-smtp/smtp-reply-parser.h +++ b/src/lib-smtp/smtp-reply-parser.h @@ -5,6 +5,10 @@ struct smtp_reply_parser; +bool smtp_reply_parse_enhanced_code(const char *text, + struct smtp_reply_enhanced_code *enh_code_r, + const char **pos_r) ATTR_NULL(3); + struct smtp_reply_parser * smtp_reply_parser_init(struct istream *input, size_t max_reply_size); void smtp_reply_parser_deinit(struct smtp_reply_parser **_parser);