bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch#include "lib.h"
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch#include "str.h"
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch#include "base64.h"
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch#include "array.h"
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch#include "http-parser.h"
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch#include "http-auth.h"
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/* RFC 7235, Section 2.1:
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
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
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch OWS = *( SP / HTAB )
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ; optional whitespace
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch BWS = OWS
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ; "bad" whitespace
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/*
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Parsing
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstatic int
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_parse_token68(struct http_parser *parser, const char **token68_r)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const unsigned char *first;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* token68 = 1*( ALPHA / DIGIT /
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch "-" / "." / "_" / "~" / "+" / "/" ) *"="
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser->cur >= parser->end || !http_char_is_token68(*parser->cur))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 0;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch first = parser->cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser->cur < parser->end && http_char_is_token68(*parser->cur))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* *"=" */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser->cur < parser->end && *parser->cur == '=')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch *token68_r = t_strndup(first, parser->cur - first);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstatic int
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_parse_auth_param(struct http_parser *parser,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const char **param_r, const char **value_r)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const unsigned char *first = parser->cur, *end_token;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch int ret;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-param = token BWS "=" BWS ( token / quoted-string ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* token */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parser_skip_token(parser)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur = first;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return ret;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch end_token = parser->cur;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* BWS "=" BWS */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parse_ows(parser);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser->cur >= parser->end || *parser->cur != '=') {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur = first;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 0;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parse_ows(parser);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* ( token / quoted-string ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_token_or_qstring(parser, value_r)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur = first;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return ret;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch *param_r = t_strndup(first, end_token - first);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstatic int
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_parse_auth_params(struct http_parser *parser,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ARRAY_TYPE(http_auth_param) *params)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const unsigned char *last = parser->cur;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_param param;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch unsigned int count = 0;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch int ret;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&param);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while ((ret=http_parse_auth_param
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch (parser, &param.name, &param.value)) > 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (!array_is_created(params))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch t_array_init(params, 4);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch array_append(params, &param, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch count++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch last = parser->cur;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* OWS "," OWS
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch --> also allow empty elements
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (;;) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parse_ows(parser);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser->cur >= parser->end || *parser->cur != ',')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch break;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser->cur = last;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (ret < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return (count > 0 ? 1 : 0);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschint http_auth_parse_challenges(const unsigned char *data, size_t size,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ARRAY_TYPE(http_auth_challenge) *chlngs)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_parser parser;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch int ret;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parser_init(&parser, data, size);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* WWW-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* 1#element => *( "," OWS ) ... ; RFC 7230, Section 7 */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (;;) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ',')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch break;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser.cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parse_ows(&parser);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (;;) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_challenge chlng;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&chlng);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_token(&parser, &chlng.scheme)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (ret < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch break;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* [ 1*SP ... ] */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser.cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser.cur < parser.end && *parser.cur == ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser.cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* ( token68 / #auth-param ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_auth_params(&parser, &chlng.params)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (ret < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (http_parse_token68(&parser, &chlng.data) < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (!array_is_created(chlngs))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch t_array_init(chlngs, 4);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch array_append(chlngs, &chlng, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* OWS "," OWS
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch --> also allow empty elements
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (;;) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parse_ows(&parser);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ',')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch break;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser.cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur != parser.end)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschint http_auth_parse_credentials(const unsigned char *data, size_t size,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_credentials *crdts)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_parser parser;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch int ret;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_parser_init(&parser, data, size);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(crdts);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (http_parse_token(&parser, &crdts->scheme) <= 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* [ 1*SP ... ] */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur >= parser.end || *parser.cur != ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser.cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (parser.cur < parser.end && *parser.cur == ' ')
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch parser.cur++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* ( token68 / #auth-param ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ((ret=http_parse_auth_params(&parser, &crdts->params)) <= 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (ret < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (http_parse_token68(&parser, &crdts->data) < 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (parser.cur != parser.end)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return -1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return 1;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/*
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Construction
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstatic void
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_auth_create_param(string_t *out, const struct http_auth_param *param)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const char *p, *first;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-param = token BWS "=" BWS ( token / quoted-string ) */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, param->name);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, '=');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (p = param->value; *p != '\0' && http_char_is_token(*p); p++);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if ( *p != '\0' ) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, '"');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch p = first = param->value;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch while (*p != '\0') {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (*p == '\\' || *p == '"') {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_n(out, first, p-first);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, '\\');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch first = p;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch p++;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_n(out, first, p-first);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, '"');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch } else {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, param->value);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstatic void
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_auth_create_params(string_t *out,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const ARRAY_TYPE(http_auth_param) *params)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_param *prms;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch unsigned int count, i;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (!array_is_created(params))
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch prms = array_get(params, &count);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (i = 0; i < count; i++) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (i > 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, ", ");
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_create_param(out, &prms[i]);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Boschstatic void http_auth_check_token68(const char *data)
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch{
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch const char *p = data;
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch /* Make sure we're not working with nonsense. */
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch i_assert(http_char_is_token68(*p));
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch for (p++; *p != '\0' && *p != '='; p++)
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch i_assert(http_char_is_token68(*p));
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch for (; *p != '\0'; p++)
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch i_assert(*p == '=');
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch}
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_create_challenge(string_t *out,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_challenge *chlng)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, chlng->scheme);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (chlng->data != NULL) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP token68 */
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch http_auth_check_token68(chlng->data);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, ' ');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, chlng->data);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch } else {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP #auth-param */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, ' ');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_create_params(out, &chlng->params);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_create_challenges(string_t *out,
06c6330d64196161cfce3efa0f6c90bbf4e348adStephan Bosch const ARRAY_TYPE(http_auth_challenge) *chlngs)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_challenge *chlgs;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch unsigned int count, i;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* WWW-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authenticate = 1#challenge
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch chlgs = array_get(chlngs, &count);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch for (i = 0; i < count; i++) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (i > 0)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, ", ");
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_create_challenge(out, &chlgs[i]);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_create_credentials(string_t *out,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_credentials *crdts)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Proxy-Authorization = credentials
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch auth-scheme = token
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* auth-scheme */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, crdts->scheme);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (crdts->data != NULL) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP token68 */
68adc380ccd09c5acabb6d3a6d85d4264b193729Stephan Bosch http_auth_check_token68(crdts->data);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, ' ');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append(out, crdts->data);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch } else {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch /* SP #auth-param */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch str_append_c(out, ' ');
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_create_params(out, &crdts->params);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/*
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Manipulation
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstatic void
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_auth_params_clone(pool_t pool,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch ARRAY_TYPE(http_auth_param) *dst,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const ARRAY_TYPE(http_auth_param) *src)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_param *sparam;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
77f3d7fc65d4335e85faf088f056d462df17ffd5Stephan Bosch if (!array_is_created(src))
77f3d7fc65d4335e85faf088f056d462df17ffd5Stephan Bosch return;
77f3d7fc65d4335e85faf088f056d462df17ffd5Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch p_array_init(dst, pool, 4);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch array_foreach(src, sparam) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_param nparam;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&nparam);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch nparam.name = p_strdup(pool, sparam->name);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch nparam.value = p_strdup(pool, sparam->value);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch array_append(dst, &nparam, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_challenge_copy(pool_t pool,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_challenge *dst,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_challenge *src)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch dst->scheme = p_strdup(pool, src->scheme);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (src->data != NULL)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch dst->data = p_strdup(pool, src->data);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch else
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_params_clone(pool, &dst->params, &src->params);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschstruct http_auth_challenge *
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschhttp_auth_challenge_clone(pool_t pool,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const struct http_auth_challenge *src)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_challenge *new;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch new = p_new(pool, struct http_auth_challenge, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch http_auth_challenge_copy(pool, new, src);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch return new;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Boschvoid http_auth_credentials_copy(pool_t pool,
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch struct http_auth_credentials *dst,
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch const struct http_auth_credentials *src)
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch{
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch dst->scheme = p_strdup(pool, src->scheme);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch if (src->data != NULL)
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch dst->data = p_strdup(pool, src->data);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch else
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch http_auth_params_clone(pool, &dst->params, &src->params);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch}
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Boschstruct http_auth_credentials *
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Boschhttp_auth_credentials_clone(pool_t pool,
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch const struct http_auth_credentials *src)
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch{
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch struct http_auth_credentials *new;
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch new = p_new(pool, struct http_auth_credentials, 1);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch http_auth_credentials_copy(pool, new, src);
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch return new;
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch}
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/*
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch * Simple schemes
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschvoid http_auth_basic_challenge_init(struct http_auth_challenge *chlng,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch const char *realm)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch{
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(chlng);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch chlng->scheme = "Basic";
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (realm != NULL) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch struct http_auth_param param;
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&param);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch param.name = "realm";
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch param.value = t_strdup(realm);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch t_array_init(&chlng->params, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch array_append(&chlng->params, &param, 1);
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch }
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch}
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Boschvoid http_auth_basic_credentials_init(struct http_auth_credentials *crdts,
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch const char *username, const char *password)
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch{
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch const char *auth;
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch string_t *data;
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch i_assert(username != NULL && *username != '\0');
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch i_assert(strchr(username, ':') == NULL);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch data = t_str_new(64);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch auth = t_strconcat(username, ":", password, NULL);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch base64_encode(auth, strlen(auth), data);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(crdts);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch crdts->scheme = "Basic";
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch crdts->data = str_c(data);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch}