From: Stephan Bosch Date: Wed, 19 Feb 2025 00:49:12 +0000 (+0100) Subject: lib-sasl: sasl-server-mech-digest-md5 - Move parse_next() to lib-auth/auth-digest... X-Git-Tag: 2.4.2~146 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f20cb8909c3678c82799f8d677189c1b4c1dc2e8;p=thirdparty%2Fdovecot%2Fcore.git lib-sasl: sasl-server-mech-digest-md5 - Move parse_next() to lib-auth/auth-digest as auth_digest_parse_keyvalue() --- diff --git a/src/lib-auth/auth-digest.c b/src/lib-auth/auth-digest.c index 281dac3b94..06df4da42b 100644 --- a/src/lib-auth/auth-digest.c +++ b/src/lib-auth/auth-digest.c @@ -5,6 +5,69 @@ #include "auth-digest.h" +/* + * Parsing + */ + +/* Linear whitespace */ +#define IS_LWS(c) ((c) == ' ' || (c) == '\t') + +bool auth_digest_parse_keyvalue(char **data, char **key_r, char **value_r) +{ + /* @UNSAFE */ + char *p, *dest; + + p = *data; + while (IS_LWS(*p)) p++; + + /* get key */ + *key_r = p; + while (*p != '\0' && *p != '=' && *p != ',') + p++; + + if (*p != '=') { + *data = p; + return FALSE; + } + + *value_r = p+1; + + /* skip trailing whitespace in key */ + while (p > *data && IS_LWS(p[-1])) + p--; + *p = '\0'; + + /* get value */ + p = *value_r; + while (IS_LWS(*p)) p++; + + if (*p != '"') { + while (*p != '\0' && *p != ',') + p++; + + *data = p; + /* If there is more to parse, ensure it won't get skipped + because *p is set to NUL below */ + if (**data != '\0') (*data)++; + while (IS_LWS(p[-1])) + p--; + *p = '\0'; + } else { + /* quoted string */ + *value_r = dest = ++p; + while (*p != '\0' && *p != '"') { + if (*p == '\\' && p[1] != '\0') + p++; + *dest++ = *p++; + } + + *data = *p == '"' ? p+1 : p; + *dest = '\0'; + } + + return TRUE; +} + /* * Processing */ diff --git a/src/lib-auth/auth-digest.h b/src/lib-auth/auth-digest.h index 9b8f74896d..83c4302182 100644 --- a/src/lib-auth/auth-digest.h +++ b/src/lib-auth/auth-digest.h @@ -1,6 +1,12 @@ #ifndef AUTH_DIGEST_H #define AUTH_DIGEST_H +/* + * Parsing + */ + +bool auth_digest_parse_keyvalue(char **data, char **key_r, char **value_r); + /* * Processing */ diff --git a/src/lib-sasl/sasl-server-mech-digest-md5.c b/src/lib-sasl/sasl-server-mech-digest-md5.c index 35441fd72f..26353fff06 100644 --- a/src/lib-sasl/sasl-server-mech-digest-md5.c +++ b/src/lib-sasl/sasl-server-mech-digest-md5.c @@ -11,13 +11,11 @@ #include "str.h" #include "str-sanitize.h" #include "settings-parser.h" +#include "auth-digest.h" #include "password-scheme.h" #include "sasl-server-protected.h" -/* Linear whitespace */ -#define IS_LWS(c) ((c) == ' ' || (c) == '\t') - enum qop_option { QOP_AUTH = 0x01, /* authenticate */ QOP_AUTH_INT = 0x02, /* + integrity protection, not supported yet */ @@ -228,62 +226,6 @@ verify_credentials(struct sasl_server_mech_request *auth_request, strlen(request->rspauth)); } -static bool parse_next(char **data, char **key, char **value) -{ - /* @UNSAFE */ - char *p, *dest; - - p = *data; - while (IS_LWS(*p)) p++; - - /* get key */ - *key = p; - while (*p != '\0' && *p != '=' && *p != ',') - p++; - - if (*p != '=') { - *data = p; - return FALSE; - } - - *value = p+1; - - /* skip trailing whitespace in key */ - while (p > *data && IS_LWS(p[-1])) - p--; - *p = '\0'; - - /* get value */ - p = *value; - while (IS_LWS(*p)) p++; - - if (*p != '"') { - while (*p != '\0' && *p != ',') - p++; - - *data = p; - /* If there is more to parse, ensure it won't get skipped - because *p is set to NUL below */ - if (**data != '\0') (*data)++; - while (IS_LWS(p[-1])) - p--; - *p = '\0'; - } else { - /* quoted string */ - *value = dest = ++p; - while (*p != '\0' && *p != '"') { - if (*p == '\\' && p[1] != '\0') - p++; - *dest++ = *p++; - } - - *data = *p == '"' ? p+1 : p; - *dest = '\0'; - } - - return TRUE; -} - static bool auth_handle_response(struct digest_auth_request *request, char *key, char *value, const char **error) @@ -494,7 +436,7 @@ parse_digest_response(struct digest_auth_request *request, potential problems with NUL characters in strings. */ copy = t_strdup_noconst(t_strndup(data, size)); while (*copy != '\0') { - if (parse_next(©, &key, &value)) { + if (auth_digest_parse_keyvalue(©, &key, &value)) { if (!auth_handle_response(request, key, value, error)) { failed = TRUE; break;