summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2017-12-12 17:20:39 +0000
committerFrediano Ziglio <fziglio@redhat.com>2018-01-09 17:06:08 +0000
commitcb70583e5c6922c50544a4ba8808839ee68c2093 (patch)
tree502c85d7a97f2f8e68c8650bbe1e07ccfe93574e
parent5c516a6e42f149e7ed7cac15d138e2b487804d9c (diff)
red-stream: Unify start and step passes
Most of these function are identical. Only difference were basically debugging message but now with a proper tests are less important. The mechname field is used to differentiate between first step and following ones. Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Christophe Fergeau <cfergeau@redhat.com>
-rw-r--r--server/red-stream.c156
1 files changed, 32 insertions, 124 deletions
diff --git a/server/red-stream.c b/server/red-stream.c
index 5c2c2739..242e552c 100644
--- a/server/red-stream.c
+++ b/server/red-stream.c
@@ -782,111 +782,6 @@ static void red_sasl_error(void *opaque, int err)
static void red_sasl_handle_auth_steplen(void *opaque);
-static void red_sasl_handle_auth_step(void *opaque)
-{
- RedStream *stream = ((RedSASLAuth *)opaque)->stream;
- const char *serverout;
- unsigned int serveroutlen;
- int err;
- char *clientdata = NULL;
- RedSASL *sasl = &stream->priv->sasl;
- uint32_t datalen = sasl->len;
-
- /* NB, distinction of NULL vs "" is *critical* in SASL */
- if (datalen) {
- clientdata = sasl->data;
- clientdata[datalen - 1] = '\0'; /* Wire includes '\0', but make sure */
- datalen--; /* Don't count NULL byte when passing to _start() */
- }
-
- spice_debug("Step using SASL Data %p (%d bytes)",
- clientdata, datalen);
- err = sasl_server_step(sasl->conn,
- clientdata,
- datalen,
- &serverout,
- &serveroutlen);
- if (err != SASL_OK &&
- err != SASL_CONTINUE) {
- spice_warning("sasl step failed %d (%s)",
- err, sasl_errdetail(sasl->conn));
- return red_sasl_async_result(opaque, RED_SASL_ERROR_GENERIC);
- }
-
- if (serveroutlen > SASL_DATA_MAX_LEN) {
- spice_warning("sasl step reply data too long %d",
- serveroutlen);
- return red_sasl_async_result(opaque, RED_SASL_ERROR_GENERIC);
- }
-
- spice_debug("SASL return data %d bytes, %p", serveroutlen, serverout);
-
- if (serveroutlen) {
- serveroutlen += 1;
- red_stream_write_u32_le(stream, serveroutlen);
- red_stream_write_all(stream, serverout, serveroutlen);
- } else {
- red_stream_write_u32_le(stream, serveroutlen);
- }
-
- /* Whether auth is complete */
- red_stream_write_u8(stream, err == SASL_CONTINUE ? 0 : 1);
-
- if (err == SASL_CONTINUE) {
- spice_debug("%s", "Authentication must continue (step)");
- /* Wait for step length */
- red_stream_async_read(stream, (uint8_t *)&sasl->len, sizeof(uint32_t),
- red_sasl_handle_auth_steplen, opaque);
- return;
- } else {
- int ssf;
-
- if (auth_sasl_check_ssf(sasl, &ssf) == 0) {
- spice_warning("Authentication rejected for weak SSF");
- goto authreject;
- }
-
- spice_debug("Authentication successful");
- red_stream_write_u32_le(stream, SPICE_LINK_ERR_OK); /* Accept auth */
-
- /*
- * Delay writing in SSF encoded until now
- */
- sasl->runSSF = ssf;
- red_stream_disable_writev(stream); /* make sure writev isn't called directly anymore */
-
- return red_sasl_async_result(opaque, RED_SASL_ERROR_OK);
- }
-
-authreject:
- red_stream_write_u32_le(stream, 1); /* Reject auth */
- red_stream_write_u32_le(stream, sizeof("Authentication failed"));
- red_stream_write_all(stream, "Authentication failed", sizeof("Authentication failed"));
-
- red_sasl_async_result(opaque, RED_SASL_ERROR_AUTH_FAILED);
-}
-
-static void red_sasl_handle_auth_steplen(void *opaque)
-{
- RedStream *stream = ((RedSASLAuth *)opaque)->stream;
- RedSASL *sasl = &stream->priv->sasl;
-
- sasl->len = GUINT32_FROM_LE(sasl->len);
- spice_debug("Got steplen %d", sasl->len);
- if (sasl->len > SASL_DATA_MAX_LEN) {
- spice_warning("Too much SASL data %d", sasl->len);
- return red_sasl_async_result(opaque, RED_SASL_ERROR_GENERIC);
- }
-
- if (sasl->len == 0) {
- red_sasl_handle_auth_step(opaque);
- } else {
- sasl->data = g_realloc(sasl->data, sasl->len);
- red_stream_async_read(stream, (uint8_t *)sasl->data, sasl->len,
- red_sasl_handle_auth_step, opaque);
- }
-}
-
/*
* Start Msg
*
@@ -902,7 +797,7 @@ static void red_sasl_handle_auth_steplen(void *opaque)
* u8 continue
*/
-static void red_sasl_handle_auth_start(void *opaque)
+static void red_sasl_handle_auth_step(void *opaque)
{
RedStream *stream = ((RedSASLAuth *)opaque)->stream;
const char *serverout;
@@ -915,27 +810,38 @@ static void red_sasl_handle_auth_start(void *opaque)
/* NB, distinction of NULL vs "" is *critical* in SASL */
if (datalen) {
clientdata = sasl->data;
- clientdata[datalen - 1] = '\0'; /* Should be on wire, but make sure */
+ clientdata[datalen - 1] = '\0'; /* Wire includes '\0', but make sure */
datalen--; /* Don't count NULL byte when passing to _start() */
}
- spice_debug("Start SASL auth with mechanism %s. Data %p (%d bytes)",
- sasl->mechname, clientdata, datalen);
- err = sasl_server_start(sasl->conn,
- sasl->mechname,
- clientdata,
- datalen,
- &serverout,
- &serveroutlen);
+ if (sasl->mechname != NULL) {
+ spice_debug("Start SASL auth with mechanism %s. Data %p (%d bytes)",
+ sasl->mechname, clientdata, datalen);
+ err = sasl_server_start(sasl->conn,
+ sasl->mechname,
+ clientdata,
+ datalen,
+ &serverout,
+ &serveroutlen);
+ g_free(sasl->mechname);
+ sasl->mechname = NULL;
+ } else {
+ spice_debug("Step using SASL Data %p (%d bytes)", clientdata, datalen);
+ err = sasl_server_step(sasl->conn,
+ clientdata,
+ datalen,
+ &serverout,
+ &serveroutlen);
+ }
if (err != SASL_OK &&
err != SASL_CONTINUE) {
- spice_warning("sasl start failed %d (%s)",
+ spice_warning("sasl step failed %d (%s)",
err, sasl_errdetail(sasl->conn));
return red_sasl_async_result(opaque, RED_SASL_ERROR_GENERIC);
}
if (serveroutlen > SASL_DATA_MAX_LEN) {
- spice_warning("sasl start reply data too long %d",
+ spice_warning("sasl step reply data too long %d",
serveroutlen);
return red_sasl_async_result(opaque, RED_SASL_ERROR_GENERIC);
}
@@ -954,7 +860,7 @@ static void red_sasl_handle_auth_start(void *opaque)
red_stream_write_u8(stream, err == SASL_CONTINUE ? 0 : 1);
if (err == SASL_CONTINUE) {
- spice_debug("%s", "Authentication must continue (start)");
+ spice_debug("%s", "Authentication must continue");
/* Wait for step length */
red_stream_async_read(stream, (uint8_t *)&sasl->len, sizeof(uint32_t),
red_sasl_handle_auth_steplen, opaque);
@@ -987,27 +893,29 @@ authreject:
red_sasl_async_result(opaque, RED_SASL_ERROR_AUTH_FAILED);
}
-static void red_sasl_handle_auth_startlen(void *opaque)
+static void red_sasl_handle_auth_steplen(void *opaque)
{
RedStream *stream = ((RedSASLAuth *)opaque)->stream;
RedSASL *sasl = &stream->priv->sasl;
sasl->len = GUINT32_FROM_LE(sasl->len);
- spice_debug("Got client start len %d", sasl->len);
+ spice_debug("Got steplen %d", sasl->len);
if (sasl->len > SASL_DATA_MAX_LEN) {
spice_warning("Too much SASL data %d", sasl->len);
- return red_sasl_async_result(opaque, RED_SASL_ERROR_INVALID_DATA);
+ return red_sasl_async_result(opaque, sasl->mechname ? RED_SASL_ERROR_INVALID_DATA : RED_SASL_ERROR_GENERIC);
}
if (sasl->len == 0) {
- return red_sasl_handle_auth_start(opaque);
+ return red_sasl_handle_auth_step(opaque);
}
sasl->data = g_realloc(sasl->data, sasl->len);
red_stream_async_read(stream, (uint8_t *)sasl->data, sasl->len,
- red_sasl_handle_auth_start, opaque);
+ red_sasl_handle_auth_step, opaque);
}
+
+
static void red_sasl_handle_auth_mechname(void *opaque)
{
RedStream *stream = ((RedSASLAuth *)opaque)->stream;
@@ -1027,7 +935,7 @@ static void red_sasl_handle_auth_mechname(void *opaque)
spice_debug("Validated mechname '%s'", sasl->mechname);
red_stream_async_read(stream, (uint8_t *)&sasl->len, sizeof(uint32_t),
- red_sasl_handle_auth_startlen, opaque);
+ red_sasl_handle_auth_steplen, opaque);
}
static void red_sasl_handle_auth_mechlen(void *opaque)