Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read access tokens from the backend server #4

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
aclocal.m4
autom4te.cache
compile
confdefs.h
conftest.*
config.guess
config.h
config.h.in
Expand All @@ -25,3 +27,6 @@ missing
*.o
*.so
stamp-h1
*.swp
*.swo
test_xoauth2_token_conv
11 changes: 11 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
SUBDIRS = . tests
ACLOCAL_AMFLAGS = -I m4
CYRYS_SASL_PREFIX = @CYRUS_SASL_PREFIX@
CYRYS_SASL_CPPFLAGS = @CYRUS_SASL_CPPFLAGS@
CYRUS_SASL_LDFLAGS = @CYRUS_SASL_LDFLAGS@
XOAUTH2_TOKEN_CONV_EXTRA_LIBS = @XOAUTH2_TOKEN_CONV_EXTRA_LIBS@

noinst_LTLIBRARIES = libxoauth2_token_conv.la
libxoauth2_token_conv_la_SOURCES = xoauth2_socket_common.c xoauth2_token_conv.c
if XOAUTH2_WIN32
libxoauth2_token_conv_la_SOURCES += xoauth2_socket_win32.c
else
libxoauth2_token_conv_la_SOURCES += xoauth2_socket_unix.c
endif

pkglibdir = ${CYRUS_SASL_PREFIX}/lib/sasl2
pkglib_LTLIBRARIES = libxoauth2.la
libxoauth2_la_CPPFLAGS = ${CYRUS_SASL_CPPFLAGS}
libxoauth2_la_LDFLAGS = ${CYRUS_SASL_LDFLAGS} -module
libxoauth2_la_SOURCES = xoauth2_str.c xoauth2_init.c xoauth2_server.c xoauth2_client.c
libxoauth2_la_LIBADD = libxoauth2_token_conv.la ${XOAUTH2_TOKEN_CONV_EXTRA_LIBS}
18 changes: 17 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,28 @@ AC_CONFIG_MACRO_DIR([m4])
LT_INIT
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([Makefile tests/Makefile])

CYRUS_SASL_CPPFLAGS=
CYRUS_SASL_PREFIX=/usr
CYRUS_SASL_LDFLAGS=
XOAUTH2_WIN32=
XOAUTH2_TOKEN_CONV_EXTRA_LIBS=

# Cygwin stuff
case "$host" in
*-*-cygwin*)
CYRUS_SASL_LDFLAGS=-no-undefined
;;
*-*-mingw32*)
CPPFLAGS="${CPPFLAGS} -DXOAUTH2_WIN32 -D_WIN32 -D_WIN32_WINNT=_WIN32_WINNT_VISTA"
XOAUTH2_TOKEN_CONV_EXTRA_LIBS="-lws2_32"
XOAUTH2_WIN32=1
;;
esac

AM_CONDITIONAL([XOAUTH2_WIN32], [test x$XOAUTH2_WIN32 != x])

AC_ARG_WITH(
[cyrus-sasl],
AS_HELP_STRING([--with-cyrus-sasl=[[PREFIX]]], [Installation prefix of Cyrus-SASL (defaults to /usr)]),
Expand All @@ -61,7 +70,14 @@ if test -z "$CYRUS_SASL_PREFIX"; then
AC_MSG_ERROR([Cyrus-SASL not found under $CYRUS_SASL_PREFIX])
fi

AC_CHECK_HEADERS([winsock2.h ws2tcpip.h], [], [], [/**/])
AC_CHECK_HEADERS([alloca.h unistd.h poll.h sys/ioctl.h sys/socket.h sys/types.h sys/uio.h sys/un.h netinet/in.h netinet/in6.h netdb.h])

AC_TYPE_UINT32_T

AC_SUBST([CYRUS_SASL_CPPFLAGS], [$CYRUS_SASL_CPPFLAGS])
AC_SUBST([CYRUS_SASL_LDFLAGS], [$CYRUS_SASL_LDFLAGS])
AC_SUBST([CYRUS_SASL_PREFIX], [$CYRUS_SASL_PREFIX])
AC_SUBST([XOAUTH2_WIN32], [$XOAUTH2_WIN32])
AC_SUBST([XOAUTH2_TOKEN_CONV_EXTRA_LIBS], [$XOAUTH2_TOKEN_CONV_EXTRA_LIBS])
AC_OUTPUT
1 change: 1 addition & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test_xoauth2_token_conv*
9 changes: 9 additions & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CYRYS_SASL_PREFIX = @CYRUS_SASL_PREFIX@
CYRYS_SASL_CPPFLAGS = @CYRUS_SASL_CPPFLAGS@
CYRUS_SASL_LDFLAGS = @CYRUS_SASL_LDFLAGS@
XOAUTH2_TOKEN_CONV_EXTRA_LIBS = @XOAUTH2_TOKEN_CONV_EXTRA_LIBS@

noinst_PROGRAMS = test_xoauth2_token_conv
test_xoauth2_token_conv_SOURCES = test_xoauth2_token_conv.c test_xoauth2_token_conv.h ../xoauth2_str.c
test_xoauth2_token_conv_CPPFLAGS = ${CYRUS_SASL_CPPFLAGS}
test_xoauth2_token_conv_LDADD = ../libxoauth2_token_conv.la ${CYRUS_SASL_LDFLAGS} ${XOAUTH2_TOKEN_CONV_EXTRA_LIBS}
76 changes: 76 additions & 0 deletions tests/test_xoauth2_token_conv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <locale.h>

#include "xoauth2_token_conv.h"
#include "xoauth2_socket.h"

static void _log(UNUSED(sasl_conn_t *conn), int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fputs("\n", stderr);
va_end(ap);
}

static const xoauth2_plugin_token_conv_settings_t settings = { 2000, 2000, 2000 };

static int do_converse(const sasl_utils_t *utils, const char *addr)
{
int err;
xoauth2_plugin_token_conv_t token_conv;
xoauth2_plugin_str_t str;

err = xoauth2_plugin_str_init(utils, &str);
if (SASL_OK != err) {
xoauth2_plugin_token_conv_free(utils, &token_conv);
return err;
}

{
int i;
for (i = 0; i < 3; i++) {
int j;
err = xoauth2_plugin_token_conv_init(utils, &token_conv, &settings, addr);
if (SASL_OK != err) {
xoauth2_plugin_str_free(utils, &str);
return err;
}
for (j = 0; j < 3; j++) {
str.len = 0;
err = xoauth2_plugin_token_conv_retrieve_access_token(utils, &token_conv, &str, "AUTHID!", sizeof("AUTHID!") - 1);
if (SASL_OK != err) {
xoauth2_plugin_str_free(utils, &str);
xoauth2_plugin_token_conv_free(utils, &token_conv);
return err;
}
fprintf(stderr, "(%d) %s\n", str.len, str.buf);
}
xoauth2_plugin_token_conv_free(utils, &token_conv);
}
}

xoauth2_plugin_str_free(utils, &str);

return SASL_OK;
}

int main()
{
sasl_utils_t utils;

setlocale(LC_ALL, "");

utils.log = _log;
utils.malloc = malloc;
utils.calloc = calloc;
utils.realloc = realloc;
utils.free = free;

xoauth2_plugin_socket_setup();
do_converse(&utils, "tcp:127.0.0.1:65321");
do_converse(&utils, "unix:/tmp/test.sock");
xoauth2_plugin_socket_teardown();
}
51 changes: 51 additions & 0 deletions tests/token_conv_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import io
import asyncio
import socket
import struct


async def handler(reader, writer):
r = await reader.read(8)
print(r)
writer.write(b"\x81\x9d\x74\x13")
await asyncio.sleep(1)
writer.write(b"\x00\x00\x00\x01")
await asyncio.sleep(1)
while True:
r = await reader.read(4)
if len(r) == 0:
break
l, = struct.unpack(">I", r)
print(l)
in_ = await reader.read(l)
print(in_)
payload = b"hello world"
writer.write(struct.pack(">I", len(payload)) + payload)


async def main():
server1 = await asyncio.start_server(
handler,
family=socket.AF_INET,
host="127.0.0.1",
port=65321,
)
server2 = await asyncio.start_server(
handler,
family=socket.AF_INET6,
host="::",
port=65321,
)
server3 = await asyncio.start_unix_server(
handler,
path="/tmp/test.sock",
)
await server1.start_serving()
await server2.start_serving()
await server3.start_serving()
await server1.wait_closed()
await server2.wait_closed()
await server3.wait_closed()


asyncio.run(main())
97 changes: 90 additions & 7 deletions xoauth2_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,51 @@
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#include "xoauth2_plugin.h"
#include "xoauth2_token_conv.h"

typedef struct _xoauth2_plugin_client_global_context_t {
int token_conv_enabled;
xoauth2_plugin_token_conv_t token_conv;
} xoauth2_plugin_client_global_context_t;

static const xoauth2_plugin_token_conv_settings_t settings = {
2000, /* connect */
2000, /* write */
2000 /* read */
};

static int xoauth2_plugin_client_global_context_init(
const sasl_utils_t *utils,
xoauth2_plugin_client_global_context_t *glob_context)
{
glob_context->token_conv_enabled = 0;
{
const char *token_conv_conn_spec = getenv("SASL_XOAUTH2_CLIENT_TOKEN_CONV");

if (token_conv_conn_spec && strlen(token_conv_conn_spec) != 0) {
glob_context->token_conv_enabled = 1;
return xoauth2_plugin_token_conv_init(utils, &glob_context->token_conv, &settings, token_conv_conn_spec);
}
}
return SASL_OK;
}

static void xoauth2_plugin_client_global_context_free(
const sasl_utils_t *utils,
xoauth2_plugin_client_global_context_t *glob_context)
{
if (glob_context->token_conv_enabled) {
xoauth2_plugin_token_conv_free(utils, &glob_context->token_conv);
}
}

static int xoauth2_plugin_client_mech_new(
UNUSED(void *glob_context),
void *glob_context,
sasl_client_params_t *params,
void **pcontext)
{
Expand All @@ -44,10 +83,17 @@ static int xoauth2_plugin_client_mech_new(

context->state = 0;
context->resp.buf = NULL;
context->glob_context = glob_context;
err = xoauth2_plugin_str_init(utils, &context->outbuf);
if (err != SASL_OK) {
SASL_free(context);
return err;
return err;
}
err = xoauth2_plugin_str_init(utils, &context->token);
if (err != SASL_OK) {
xoauth2_plugin_str_free(utils, &context->outbuf);
SASL_free(context);
return err;
}
*pcontext = context;
return SASL_OK;
Expand Down Expand Up @@ -137,7 +183,7 @@ static int get_cb_value(const sasl_utils_t *utils, unsigned id, const char **res
if (secret->len >= UINT_MAX) {
return SASL_BADPROT;
}
*result = secret->data;
*result = (const char *)secret->data;
*result_len = secret->len;
}
break;
Expand Down Expand Up @@ -226,6 +272,27 @@ static int xoauth2_plugin_client_mech_step1(
}
}

if (context->glob_context->token_conv_enabled &&
!authid_wanted &&
(
password_wanted
|| resp.token_len == 0
|| (resp.token_len == 1 && strncmp(resp.token, "-", 1) == 0)
)) {
err = xoauth2_plugin_token_conv_retrieve_access_token(
utils,
&context->glob_context->token_conv,
&context->token,
resp.authid,
resp.authid_len);
if (SASL_OK != err) {
goto out;
}
resp.token = context->token.buf;
resp.token_len = context->token.len;
password_wanted = 0;
}

if (!authid_wanted && !password_wanted) {
err = params->canon_user(
utils->conn, resp.authid, resp.authid_len,
Expand All @@ -250,7 +317,7 @@ static int xoauth2_plugin_client_mech_step1(
if (!prompt_returned) {
SASL_log((utils->conn, SASL_LOG_ERR, "failed to allocate buffer"));
err = SASL_NOMEM;
return err;
goto out;
}
memset(prompt_returned, 0, sizeof(sasl_interact_t) * prompts);
p = prompt_returned;
Expand Down Expand Up @@ -369,10 +436,16 @@ static void xoauth2_plugin_client_mech_dispose(
return;
}

xoauth2_plugin_str_free(utils, &context->token);
xoauth2_plugin_str_free(utils, &context->outbuf);
SASL_free(context);
}

static void xoauth2_plugin_client_mech_free(void *glob_context, const sasl_utils_t *utils)
{
xoauth2_plugin_client_global_context_free(utils, (xoauth2_plugin_client_global_context_t *)glob_context);
}

static sasl_client_plug_t xoauth2_client_plugins[] =
{
{
Expand All @@ -387,15 +460,17 @@ static sasl_client_plug_t xoauth2_client_plugins[] =
&xoauth2_plugin_client_mech_new, /* mech_new */
&xoauth2_plugin_client_mech_step, /* mech_step */
&xoauth2_plugin_client_mech_dispose,/* mech_dispose */
NULL, /* mech_free */
&xoauth2_plugin_client_mech_free, /* mech_free */
NULL, /* idle */
NULL, /* spare */
NULL /* spare */
}
};

static xoauth2_plugin_client_global_context_t xoauth2_client_global_context;

int xoauth2_client_plug_init(
sasl_utils_t *utils,
const sasl_utils_t *utils,
int maxversion,
int *out_version,
sasl_client_plug_t **pluglist,
Expand All @@ -406,10 +481,18 @@ int xoauth2_client_plug_init(
return SASL_BADVERS;
}

{
int err = xoauth2_plugin_client_global_context_init(utils, &xoauth2_client_global_context);
if (SASL_OK != err) {
SASL_seterror((utils->conn, 0, "xoauth2: global context initialization failed (%d)", err));
return SASL_FAIL;
}
xoauth2_client_plugins[0].glob_context = &xoauth2_client_global_context;
}

*out_version = SASL_CLIENT_PLUG_VERSION;
*pluglist = xoauth2_client_plugins;
*plugcount = sizeof(xoauth2_client_plugins) / sizeof(*xoauth2_client_plugins);

return SASL_OK;
}

Loading