[Spice-devel] [PATCH spice-server v3 12/12] red-stream: Encapsulate all authentication state in RedSASLAuth
Christophe Fergeau
cfergeau at redhat.com
Fri Jan 5 13:28:17 UTC 2018
On Fri, Dec 22, 2017 at 10:07:13AM +0000, Frediano Ziglio wrote:
> Instead of having half state in RedSASL and half in RedSASLAuth
> move everything in RedSASLAuth. This also reduces memory usage
> when we are using SASL but we finish the authentication step.
>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
> server/red-stream.c | 138 +++++++++++++++++++++++++++-------------------------
> 1 file changed, 72 insertions(+), 66 deletions(-)
>
> diff --git a/server/red-stream.c b/server/red-stream.c
> index 0e372743a..898253c2e 100644
> --- a/server/red-stream.c
> +++ b/server/red-stream.c
> @@ -67,13 +67,6 @@ typedef struct RedSASL {
> unsigned int encodedOffset;
>
> SpiceBuffer inbuffer;
> -
> - char *mechlist;
> - char *mechname;
> -
> - /* temporary data during authentication */
> - unsigned int len;
> - char *data;
> } RedSASL;
> #endif
>
> @@ -351,13 +344,8 @@ void red_stream_free(RedStream *s)
> #if HAVE_SASL
> if (s->priv->sasl.conn) {
> s->priv->sasl.runSSF = s->priv->sasl.wantSSF = 0;
> - s->priv->sasl.len = 0;
> s->priv->sasl.encodedLength = s->priv->sasl.encodedOffset = 0;
> s->priv->sasl.encoded = NULL;
> - g_free(s->priv->sasl.mechlist);
> - g_free(s->priv->sasl.mechname);
> - s->priv->sasl.mechlist = NULL;
> - g_free(s->priv->sasl.data);
> sasl_dispose(&s->priv->sasl.conn);
> s->priv->sasl.conn = NULL;
> }
> @@ -735,17 +723,37 @@ static int auth_sasl_check_ssf(RedSASL *sasl, int *runSSF)
>
> typedef struct RedSASLAuth {
> RedStream *stream;
> + // list of mech allowed, allocated and freed by SASL
mech->mechanisms?
> + char *mechlist;
> + // mech received
> + char *mechname;
> + uint32_t len;
> + char *data;
> + // callback to call if success
> RedSaslResult result_cb;
> void *result_opaque;
> + // saved Async callback, we need to call if failed as
> + // we need to chain it in order to use a different opaque data
> AsyncReadError saved_error;
These 2 comments could have been added in the commit introducing
RedSASLAuth.
> } RedSASLAuth;
>
> +static void red_sasl_async_deinit(RedSASLAuth *opaque)
> +{
> + g_free(opaque->data);
> + opaque->data = NULL;
> + g_free(opaque->mechname);
> + opaque->mechname = NULL;
> + g_free(opaque->mechlist);
> + opaque->mechlist = NULL;
> + opaque->stream->priv->async_read.error = opaque->saved_error;
Not using red_stream_set_async_error_handler() here? (but this also
applies to "Handle SASL initialisation mainly in red-stream.c"
> +}
> +
> // handle SASL termination, either success or error
> // NOTE: After this function is called usually there should be a
> // return or the function should exit
> static void red_sasl_async_result(RedSASLAuth *auth, RedSaslError err)
> {
> - auth->stream->priv->async_read.error = auth->saved_error;
> + red_sasl_async_deinit(auth);
> auth->result_cb(auth->result_opaque, err);
> g_free(auth);
> }
I would keep the red_stream_set_async_error_handler() call here, and
instead have a red_sasl_auth_free() helper:
static void red_sasl_async_result(RedSASLAuth *auth, RedSaslError err)
{
auth->stream->priv->async_read.error = auth->saved_error;
auth->result_cb(auth->result_opaque, err);
red_sasl_auth_free(auth);
}
> @@ -753,7 +761,7 @@ static void red_sasl_async_result(RedSASLAuth *auth, RedSaslError err)
> static void red_sasl_error(void *opaque, int err)
> {
> RedSASLAuth *auth = opaque;
> - auth->stream->priv->async_read.error = auth->saved_error;
> + red_sasl_async_deinit(auth);
Same here
> if (auth->saved_error) {
> auth->saved_error(auth->result_opaque, err);
> }
>
> [...]
>
> static void red_sasl_handle_auth_mechlen(void *opaque)
> {
> - RedStream *stream = ((RedSASLAuth *)opaque)->stream;
> - RedSASL *sasl = &stream->priv->sasl;
> + RedSASLAuth *auth = opaque;
>
> - sasl->len = GUINT32_FROM_LE(sasl->len);
> - if (sasl->len < 1 || sasl->len > SASL_MAX_MECHNAME_LEN) {
> - spice_warning("Got bad client mechname len %d", sasl->len);
> - return red_sasl_async_result(opaque, RED_SASL_ERROR_INVALID_DATA);
> + uint32_t len = GUINT32_FROM_LE(auth->len);
You need to update auth->len here:
auth->len = GUINT32_FROM_LE(auth->len);
uint32_t len = auth->len;
I think I would do without the 'len' variable, auth->len is not that
long ;)
> + if (len < 1 || len > SASL_MAX_MECHNAME_LEN) {
> + spice_warning("Got bad client mechname len %d", auth->len);
> + return red_sasl_async_result(auth, RED_SASL_ERROR_INVALID_DATA);
> }
>
> - sasl->mechname = g_malloc(sasl->len + 1);
> + auth->mechname = g_malloc(len + 1);
>
> spice_debug("Wait for client mechname");
> - red_stream_async_read(stream, (uint8_t *)sasl->mechname, sasl->len,
> - red_sasl_handle_auth_mechname, opaque);
> + red_stream_async_read(auth->stream, (uint8_t *)auth->mechname, auth->len,
> + red_sasl_handle_auth_mechname, auth);
> }
>
> -bool red_sasl_start_auth(RedStream *stream, RedSaslResult result_cb, void *opaque)
> +bool red_sasl_start_auth(RedStream *stream, RedSaslResult result_cb, void *result_opaque)
This could go in "Handle SASL initialisation mainly in red-stream.c"
> {
> const char *mechlist = NULL;
> sasl_security_properties_t secprops;
> @@ -1047,11 +1054,9 @@ bool red_sasl_start_auth(RedStream *stream, RedSaslResult result_cb, void *opaqu
>
> spice_debug("Available mechanisms for client: '%s'", mechlist);
>
> - sasl->mechlist = g_strdup(mechlist);
> -
> mechlistlen = strlen(mechlist);
> if (!red_stream_write_u32(stream, mechlistlen)
> - || !red_stream_write_all(stream, sasl->mechlist, mechlistlen)) {
> + || !red_stream_write_all(stream, mechlist, mechlistlen)) {
> spice_warning("SASL mechanisms write error");
> goto error;
> }
> @@ -1059,12 +1064,13 @@ bool red_sasl_start_auth(RedStream *stream, RedSaslResult result_cb, void *opaqu
> auth = g_new0(RedSASLAuth, 1);
> auth->stream = stream;
> auth->result_cb = result_cb;
> - auth->result_opaque = opaque;
> + auth->result_opaque = result_opaque;
> auth->saved_error = stream->priv->async_read.error;
> - stream->priv->async_read.error = red_sasl_error;
> + red_stream_set_async_error_handler(stream, red_sasl_error);
Same for this change
Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20180105/ad0c3cae/attachment-0001.sig>
More information about the Spice-devel
mailing list