bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/* RFC 7235, Section 2.1:
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-param = token BWS "=" BWS ( token / quoted-string )
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch token68 = 1*( ALPHA / DIGIT /
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch "-" / "." / "_" / "~" / "+" / "/" ) *"="
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch OWS = *( SP / HTAB )
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ; optional whitespace
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ; "bad" whitespace
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_parse_token68(struct http_parser *parser, const char **token68_r)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* token68 = 1*( ALPHA / DIGIT /
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch "-" / "." / "_" / "~" / "+" / "/" ) *"="
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser->cur >= parser->end || !http_char_is_token68(*parser->cur))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser->cur < parser->end && http_char_is_token68(*parser->cur))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser->cur < parser->end && *parser->cur == '=')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch *token68_r = t_strndup(first, parser->cur - first);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_parse_auth_param(struct http_parser *parser,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const unsigned char *first = parser->cur, *end_token;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-param = token BWS "=" BWS ( token / quoted-string ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parser_skip_token(parser)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* BWS "=" BWS */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser->cur >= parser->end || *parser->cur != '=') {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* ( token / quoted-string ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_token_or_qstring(parser, value_r)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch *param_r = t_strndup(first, end_token - first);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_parse_auth_params(struct http_parser *parser,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* OWS "," OWS
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch --> also allow empty elements
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser->cur >= parser->end || *parser->cur != ',')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschint http_auth_parse_challenges(const unsigned char *data, size_t size,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* WWW-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* 1#element => *( "," OWS ) ... ; RFC 7230, Section 7 */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ',')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_token(&parser, &chlng.scheme)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* [ 1*SP ... ] */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser.cur < parser.end && *parser.cur == ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* ( token68 / #auth-param ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_auth_params(&parser, &chlng.params)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (http_parse_token68(&parser, &chlng.data) < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* OWS "," OWS
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch --> also allow empty elements
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ',')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschint http_auth_parse_credentials(const unsigned char *data, size_t size,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (http_parse_token(&parser, &crdts->scheme) <= 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* [ 1*SP ... ] */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser.cur < parser.end && *parser.cur == ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* ( token68 / #auth-param ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_auth_params(&parser, &crdts->params)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (http_parse_token68(&parser, &crdts->data) < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Construction
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_auth_create_param(string_t *out, const struct http_auth_param *param)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-param = token BWS "=" BWS ( token / quoted-string ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (p = param->value; *p != '\0' && http_char_is_token(*p); p++);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ( *p != '\0' ) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (*p != '\0') {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (i = 0; i < count; i++) {
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Boschstatic void http_auth_check_token68(const char *data)
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch const char *p = data;
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch /* Make sure we're not working with nonsense. */
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch for (; *p != '\0'; p++)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP token68 */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP #auth-param */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_create_challenges(string_t *out,
06c6330d64196161cfce3efa0f6c90bbf4e348adStephan Bosch const ARRAY_TYPE(http_auth_challenge) *chlngs)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* WWW-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (i = 0; i < count; i++) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_create_credentials(string_t *out,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP token68 */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP #auth-param */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Manipulation
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_params_clone(pool, &dst->params, &src->params);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch new = p_new(pool, struct http_auth_challenge, 1);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch http_auth_params_clone(pool, &dst->params, &src->params);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch new = p_new(pool, struct http_auth_credentials, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Simple schemes
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_basic_challenge_init(struct http_auth_challenge *chlng,
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Boschvoid http_auth_basic_credentials_init(struct http_auth_credentials *crdts,
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch i_assert(username != NULL && *username != '\0');