/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
#include "auth-common.h"
#include "safe-memset.h"
#include "str.h"
#include "mech.h"
#include "passdb.h"
#include "oauth2.h"
#include <ctype.h>
struct oauth2_auth_request {
bool failed;
};
/* RFC5801 based unescaping */
{
if (in[0] == ',')
return FALSE;
if (in[0] == '=') {
else
return FALSE;
in += 2;
} else {
}
}
return TRUE;
}
const char *error,
struct auth_request *request)
{
(struct oauth2_auth_request*)request;
switch (result) {
case PASSDB_RESULT_OK:
break;
break;
default:
/* we could get new token after this */
break;
}
}
static void
{
const char *error =
"{\"status\":\"401\",\"schemes\":\"bearer\",\"scope\":\"mail\"}";
}
static void
{
const char *error =
"{\"status\":\"invalid_token\"}";
}
/* Input syntax:
user=Username^Aauth=Bearer token^A^A
*/
static void
const unsigned char *data,
{
(struct oauth2_auth_request*)request;
/* Specification says that client is sent "invalid token" challenge
which the client is supposed to ack with empty response */
if (oauth2_req->failed) {
return;
}
/* split the data from ^A */
const char *error;
const char *const *ptr;
const char *const *fields =
/* xoauth2 does not require unescaping because the data
format does not contain anything to escape */
"%s", error);
return;
}
user_given = TRUE;
} else {
"Invalid continued data");
return;
}
}
/* do not fail on unexpected fields */
}
else {
}
}
/* Input syntax for data:
gs2flag,a=username,^Afield=...^Afield=...^Aauth=Bearer token^A^A
*/
static void
const unsigned char *data,
{
(struct oauth2_auth_request*)request;
if (oauth2_req->failed) {
return;
}
const char *error;
const char *username;
const char *const *ptr;
/* split the data from ^A */
const char **fields =
/* ensure initial field is OK */
"Invalid continued data");
return;
}
/* the first field is specified by RFC5801 as gs2-header */
switch(*ptr[0]) {
case 'f':
"Client requested non-standard mechanism");
return;
case 'p':
/* channel binding is not supported */
"Client requested and used channel-binding");
return;
case 'n':
case 'y':
/* we don't need to use channel-binding */
continue;
case 'a': /* authzid */
"Invalid username escaping");
return;
"%s", error);
} else {
user_given = TRUE;
}
break;
default:
"Invalid gs2-header in request");
return;
}
}
} else {
"Invalid continued data");
return;
}
}
/* do not fail on unexpected fields */
}
else {
}
}
{
}
"OAUTHBEARER",
/* while this does not transfer plaintext password,
the token is still considered as password */
.passdb_need = 0,
};
"XOAUTH2",
.passdb_need = 0,
};