bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include "auth-common.h"
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include "safe-memset.h"
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include "str.h"
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include "mech.h"
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include "passdb.h"
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include "oauth2.h"
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi#include <ctype.h>
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistruct oauth2_auth_request {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi struct auth_request auth;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi bool failed;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi};
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi/* RFC5801 based unescaping */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic bool oauth2_unescape_username(const char *in, const char **username_r)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi string_t *out;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi out = t_str_new(64);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi for (; *in != '\0'; in++) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (in[0] == ',')
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return FALSE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (in[0] == '=') {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (in[1] == '2' && in[2] == 'C')
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi str_append_c(out, ',');
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi else if (in[1] == '3' && in[2] == 'D')
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi str_append_c(out, '=');
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi else
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return FALSE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi in += 2;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi } else {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi str_append_c(out, *in);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi *username_r = str_c(out);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return TRUE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic void oauth2_verify_callback(enum passdb_result result,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *error,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi struct auth_request *request)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi struct oauth2_auth_request *oauth2_req =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi (struct oauth2_auth_request*)request;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi i_assert(result == PASSDB_RESULT_OK || error != NULL);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi switch (result) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case PASSDB_RESULT_OK:
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_success(request, "", 0);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi break;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case PASSDB_RESULT_INTERNAL_FAILURE:
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_internal_failure(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi break;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi default:
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* we could get new token after this */
89f6c7c1fa06abb88596c9b403adc9c079386a54Stephan Bosch if (request->mech_password != NULL)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi request->mech_password = NULL;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_handler_reply_continue(request, error, strlen(error));
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi oauth2_req->failed = TRUE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi break;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic void
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomixoauth2_verify_callback(enum passdb_result result, struct auth_request *request)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *error =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "{\"status\":\"401\",\"schemes\":\"bearer\",\"scope\":\"mail\"}";
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi oauth2_verify_callback(result, error, request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic void
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomioauthbearer_verify_callback(enum passdb_result result, struct auth_request *request)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *error =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "{\"status\":\"invalid_token\"}";
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi oauth2_verify_callback(result, error, request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi/* Input syntax:
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi user=Username^Aauth=Bearer token^A^A
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi*/
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic void
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomimech_xoauth2_auth_continue(struct auth_request *request,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const unsigned char *data,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi size_t data_size)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi struct oauth2_auth_request *oauth2_req =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi (struct oauth2_auth_request*)request;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* Specification says that client is sent "invalid token" challenge
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi which the client is supposed to ack with empty response */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (oauth2_req->failed) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* split the data from ^A */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi bool user_given = FALSE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *error;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *token = NULL;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *const *ptr;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *const *fields =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi t_strsplit(t_strndup(data, data_size), "\x01");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi for(ptr = fields; *ptr != NULL; ptr++) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (strncmp(*ptr,"user=", 5) == 0) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* xoauth2 does not require unescaping because the data
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi format does not contain anything to escape */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *username = (*ptr)+5;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (!auth_request_set_username(request, username, &error)) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "%s", error);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi user_given = TRUE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi } else if (strncmp(*ptr,"auth=", 5) == 0) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *value = (*ptr)+5;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (strncasecmp(value, "bearer ", 7) == 0 &&
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi oauth2_valid_token(value+7)) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi token = value+7;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi } else {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "Invalid continued data");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* do not fail on unexpected fields */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (user_given && token != NULL)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_verify_plain(request, token,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi xoauth2_verify_callback);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi else {
aee9f241f3c2b2afab2262969e59df5ac8c6ccc2Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH, "Username or token missing");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi/* Input syntax for data:
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi gs2flag,a=username,^Afield=...^Afield=...^Aauth=Bearer token^A^A
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi*/
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic void
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomimech_oauthbearer_auth_continue(struct auth_request *request,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const unsigned char *data,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi size_t data_size)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi struct oauth2_auth_request *oauth2_req =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi (struct oauth2_auth_request*)request;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (oauth2_req->failed) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi bool user_given = FALSE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *error;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *username;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *const *ptr;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* split the data from ^A */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char **fields =
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi t_strsplit(t_strndup(data, data_size), "\x01");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *token = NULL;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* ensure initial field is OK */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (*fields == NULL || *(fields[0]) == '\0') {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "Invalid continued data");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* the first field is specified by RFC5801 as gs2-header */
8054b019bdca47df5676e40e19cbde7e68827640Aki Tuomi for(ptr = t_strsplit_spaces(fields[0], ","); *ptr != NULL; ptr++) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi switch(*ptr[0]) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case 'f':
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "Client requested non-standard mechanism");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case 'p':
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* channel binding is not supported */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "Client requested and used channel-binding");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case 'n':
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case 'y':
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* we don't need to use channel-binding */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi continue;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi case 'a': /* authzid */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if ((*ptr)[1] != '=' ||
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi !oauth2_unescape_username((*ptr)+2, &username)) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
aee9f241f3c2b2afab2262969e59df5ac8c6ccc2Aki Tuomi "Invalid username escaping");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi } else if (!auth_request_set_username(request, username, &error)) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "%s", error);
ec87095cf79f20c693feff56fe0aa9c6b4c6450aAki Tuomi } else {
ec87095cf79f20c693feff56fe0aa9c6b4c6450aAki Tuomi user_given = TRUE;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
8054b019bdca47df5676e40e19cbde7e68827640Aki Tuomi break;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi default:
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "Invalid gs2-header in request");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi for(ptr = fields; *ptr != NULL; ptr++) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (strncmp(*ptr,"auth=", 5) == 0) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi const char *value = (*ptr)+5;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (strncasecmp(value, "bearer ", 7) == 0 &&
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi oauth2_valid_token(value+7)) {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi token = value+7;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi } else {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "Invalid continued data");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* do not fail on unexpected fields */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi if (user_given && token != NULL)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_verify_plain(request, token,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi oauthbearer_verify_callback);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi else {
aee9f241f3c2b2afab2262969e59df5ac8c6ccc2Aki Tuomi auth_request_log_info(request, AUTH_SUBSYS_MECH, "Missing username or token");
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi auth_request_fail(request);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi }
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomistatic struct auth_request *mech_oauth2_auth_new(void)
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi{
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi struct oauth2_auth_request *request;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi pool_t pool;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi pool = pool_alloconly_create(MEMPOOL_GROWING"oauth2_auth_request", 2048);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi request = p_new(pool, struct oauth2_auth_request, 1);
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi request->auth.pool = pool;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi return &request->auth;
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi}
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomiconst struct mech_module mech_oauthbearer = {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "OAUTHBEARER",
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi /* while this does not transfer plaintext password,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi the token is still considered as password */
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi .flags = MECH_SEC_PLAINTEXT,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi .passdb_need = 0,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_oauth2_auth_new,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_generic_auth_initial,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_oauthbearer_auth_continue,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_generic_auth_free
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi};
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomiconst struct mech_module mech_xoauth2 = {
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi "XOAUTH2",
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi .flags = MECH_SEC_PLAINTEXT,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi .passdb_need = 0,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_oauth2_auth_new,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_generic_auth_initial,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_xoauth2_auth_continue,
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi mech_generic_auth_free
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi};
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi
d1c565179ff8b17fe9ff21a3f1cb2f9c4d4f5836Aki Tuomi