hasl/hasl

Add HaslMechanism and unit tests for it

16 months ago, Gary Kramlich
f9aeb8a204c6
Parents 0ff0796c3f31
Children 680e1486f56a
Add HaslMechanism and unit tests for it
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hasl/haslmechanism.c Tue Feb 14 03:06:51 2023 -0600
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 Hasl Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "haslmechanism.h"
+
+G_DEFINE_TYPE(HaslMechanism, hasl_mechanism, G_TYPE_OBJECT)
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+hasl_mechanism_init(G_GNUC_UNUSED HaslMechanism *mechanism) {
+}
+
+static void
+hasl_mechanism_class_init(G_GNUC_UNUSED HaslMechanismClass *klass) {
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+gboolean
+hasl_mechanism_step(HaslMechanism *mechanism, HaslContext *ctx,
+ const guint8 *server_in, gsize server_in_length,
+ guint8 **client_out, gsize *client_out_length,
+ GError **error)
+{
+ HaslMechanismClass *klass = NULL;
+
+ g_return_val_if_fail(HASL_IS_MECHANISM(mechanism), TRUE);
+ g_return_val_if_fail(HASL_IS_CONTEXT(ctx), TRUE);
+ g_return_val_if_fail(client_out != NULL, TRUE);
+ g_return_val_if_fail(error != NULL && *error == NULL, TRUE);
+
+ klass = HASL_MECHANISM_GET_CLASS(mechanism);
+ if(klass != NULL && klass->step != NULL) {
+ return klass->step(mechanism, ctx, server_in, server_in_length,
+ client_out, client_out_length, error);
+ }
+
+ return TRUE;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hasl/haslmechanism.h Tue Feb 14 03:06:51 2023 -0600
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 Hasl Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef HASL_MECHANISM_H
+#define HASL_MECHANISM_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define HASL_TYPE_MECHANISM (hasl_mechanism_get_type())
+G_DECLARE_DERIVABLE_TYPE(HaslMechanism, hasl_mechanism, HASL, MECHANISM,
+ GObject)
+
+#include <hasl/haslcontext.h>
+
+struct _HaslMechanismClass {
+ /*< private >*/
+ GObjectClass parent;
+
+ /*< public >*/
+ gboolean (*step)(HaslMechanism *mechanism, HaslContext *ctx, const guint8 *server_in, gsize server_in_length, guint8 **client_out, gsize *client_out_length, GError **error);
+
+ /*< private >*/
+ gpointer reserved[8];
+};
+
+/**
+ * hasl_mechanism_step:
+ * @mechanism: The instance.
+ * @ctx: The [class@Hasl.Context] instance.
+ * @server_in: (nullable): Input from the server.
+ * @server_in_length: (out) (optional): The length of @server_in in bytes.
+ * @client_out: (transfer full): The data that the client should use.
+ * @client_out_length: (out) (optional): The length of @client_out in bytes.
+ * @error: (out): A return address for an error.
+ *
+ * Tells @mechanism to perform it's next step. If @mechanism is complete it
+ * should return %TRUE. If the mechanism was not successfully, it should return
+ * %TRUE but set @error.
+ *
+ * If %FALSE is returned, @ctx will continue passing messages to @mechanism
+ * until @mechanism says it's done by returning %TRUE or another error is
+ * encountered.
+ *
+ * Returns: %TRUE if the mechanism is done, otherwise %FALSE.
+ *
+ * Since: 0.1.0
+ */
+gboolean hasl_mechanism_step(HaslMechanism *mechanism, HaslContext *ctx, const guint8 *server_in, gsize server_in_length, guint8 **client_out, gsize *client_out_length, GError **error);
+
+G_END_DECLS
+
+#endif /* HASL_MECHANISM_H */
--- a/hasl/meson.build Mon Feb 13 08:34:41 2023 -0600
+++ b/hasl/meson.build Tue Feb 14 03:06:51 2023 -0600
@@ -1,9 +1,11 @@
HASL_SOURCES = [
'haslcontext.c',
+ 'haslmechanism.c',
]
HASL_HEADERS = [
'haslcontext.h',
+ 'haslmechanism.h',
]
HASL_GENERATED_TARGETS = []
@@ -33,6 +35,7 @@
c_args : ['-DHASL_COMPILATION', '-DG_LOG_USE_STRUCTURED',
'-DG_LOG_DOMAIN="Hasl"'],
dependencies: [glib, gobject],
+ include_directories : toplevel_inc,
install : true)
pkgconfig.generate(
--- a/hasl/tests/meson.build Mon Feb 13 08:34:41 2023 -0600
+++ b/hasl/tests/meson.build Tue Feb 14 03:06:51 2023 -0600
@@ -1,5 +1,6 @@
TESTS = [
- 'context'
+ 'context',
+ 'mechanism',
]
foreach program : TESTS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hasl/tests/test-mechanism.c Tue Feb 14 03:06:51 2023 -0600
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 Hasl Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include <hasl.h>
+
+/******************************************************************************
+ * Mechanism Implementation
+ *****************************************************************************/
+G_DECLARE_FINAL_TYPE(TestHaslMechanism, test_hasl_mechanism, TEST_HASL,
+ MECHANISM, HaslMechanism)
+
+struct _TestHaslMechanism {
+ HaslMechanism parent;
+};
+
+G_DEFINE_TYPE(TestHaslMechanism, test_hasl_mechanism, HASL_TYPE_MECHANISM)
+
+static gboolean
+test_hasl_mechanism_step(HaslMechanism *mechanism, HaslContext *ctx,
+ const guint8 *server_in, gsize server_in_length,
+ guint8 **client_out, gsize *client_out_length,
+ GError **error)
+{
+ g_assert_true(TEST_HASL_IS_MECHANISM(mechanism));
+ g_assert_true(HASL_IS_CONTEXT(ctx));
+
+ g_assert_cmpstr((const char *)server_in, ==, "server-in");
+ g_assert_cmpint(server_in_length, ==, strlen("server-in"));
+
+ g_assert_nonnull(client_out);
+ g_assert_nonnull(client_out_length);
+ g_assert_nonnull(error);
+
+ *client_out = (guint8 *)g_strdup("client-out");
+ *client_out_length = strlen("client-out");
+
+ g_set_error(error, g_quark_from_static_string("test-hasl"), 0,
+ "this is an error");
+
+ return TRUE;
+}
+
+static void
+test_hasl_mechanism_init(G_GNUC_UNUSED TestHaslMechanism *mechanism) {
+}
+
+static void
+test_hasl_mechanism_class_init(TestHaslMechanismClass *klass) {
+ HaslMechanismClass *mechanism_class = HASL_MECHANISM_CLASS(klass);
+
+ mechanism_class->step = test_hasl_mechanism_step;
+}
+
+/******************************************************************************
+ * Tests
+ *****************************************************************************/
+static void
+test_hasl_mechanism_step_implementation(void) {
+ HaslContext *ctx = NULL;
+ HaslMechanism *mechanism = NULL;
+ GError *error = NULL;
+ guint8 *client_out = NULL;
+ gsize client_out_length;
+ gboolean ret = FALSE;
+
+ ctx = hasl_context_new();
+ g_assert_true(HASL_IS_CONTEXT(ctx));
+
+ mechanism = g_object_new(test_hasl_mechanism_get_type(), NULL);
+ g_assert_true(HASL_IS_MECHANISM(mechanism));
+
+ ret = hasl_mechanism_step(mechanism, ctx,
+ (guint8 *)"server-in", strlen("server-in"),
+ &client_out, &client_out_length, &error);
+ g_assert_true(ret);
+
+ g_assert_nonnull(client_out);
+ g_assert_cmpstr((char *)client_out, ==, "client-out");
+ g_free(client_out);
+
+ g_assert_cmpint(client_out_length, ==, strlen("client-out"));
+
+ g_assert_error(error, g_quark_from_static_string("test-hasl"), 0);
+ g_clear_error(&error);
+
+ g_clear_object(&ctx);
+ g_clear_object(&mechanism);
+}
+
+static void
+test_hasl_mechanism_step_no_implementation(void) {
+ HaslContext *ctx = hasl_context_new();
+ HaslMechanism *mechanism = g_object_new(HASL_TYPE_MECHANISM, NULL);
+ GError *error = NULL;
+ guint8 *client_out = NULL;
+ gboolean ret = FALSE;
+
+ ret = hasl_mechanism_step(mechanism, ctx, NULL, -1, &client_out, NULL,
+ &error);
+ g_assert_no_error(error);
+ g_assert_true(ret);
+
+ g_assert_null(client_out);
+
+ g_clear_object(&ctx);
+ g_clear_object(&mechanism);
+}
+
+/******************************************************************************
+ * Main
+ *****************************************************************************/
+int
+main(int argc, char *argv[]) {
+ g_test_init(&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
+
+ g_test_add_func("/hasl/mechanism/step/implementation",
+ test_hasl_mechanism_step_implementation);
+ g_test_add_func("/hasl/mechanism/step/no-implementation",
+ test_hasl_mechanism_step_no_implementation);
+
+ return g_test_run();
+}