hasl/hasl

Parents 7ac03df6d1c5
Children b994226ade51
Add a possible virtual function to HaslMechanism to determine whether or not that mechanism should be attempted
--- a/hasl/haslmechanism.c Tue Feb 14 22:09:23 2023 -0600
+++ b/hasl/haslmechanism.c Tue Feb 14 22:49:40 2023 -0600
@@ -33,6 +33,24 @@
/******************************************************************************
* Public API
*****************************************************************************/
+gboolean
+hasl_mechanism_possible(HaslMechanism *mechanism, HaslContext *ctx,
+ GError **error)
+{
+ HaslMechanismClass *klass = NULL;
+
+ g_return_val_if_fail(HASL_IS_MECHANISM(mechanism), FALSE);
+ g_return_val_if_fail(HASL_IS_CONTEXT(ctx), FALSE);
+ g_return_val_if_fail(error != NULL && *error == NULL, FALSE);
+
+ klass = HASL_MECHANISM_GET_CLASS(mechanism);
+ if(klass != NULL && klass->possible != NULL) {
+ return klass->possible(mechanism, ctx, error);
+ }
+
+ return TRUE;
+}
+
HaslMechanismResult
hasl_mechanism_step(HaslMechanism *mechanism, HaslContext *ctx,
const guint8 *server_in, gsize server_in_length,
--- a/hasl/haslmechanism.h Tue Feb 14 22:09:23 2023 -0600
+++ b/hasl/haslmechanism.h Tue Feb 14 22:49:40 2023 -0600
@@ -50,6 +50,8 @@
GObjectClass parent;
/*< public >*/
+ gboolean (*possible)(HaslMechanism *mechanism, HaslContext *ctx, GError **error);
+
HaslMechanismResult (*step)(HaslMechanism *mechanism, HaslContext *ctx, const guint8 *server_in, gsize server_in_length, guint8 **client_out, gsize *client_out_length, GError **error);
/*< private >*/
@@ -80,6 +82,30 @@
*/
HaslMechanismResult hasl_mechanism_step(HaslMechanism *mechanism, HaslContext *ctx, const guint8 *server_in, gsize server_in_length, guint8 **client_out, gsize *client_out_length, GError **error);
+/**
+ * hasl_mechanism_possible:
+ * @mechanism: The instance.
+ * @ctx: The [class@Hasl.Context] instance.
+ * @error: The return address for a #GError.
+ *
+ * This is used by @ctx to determine if it should even attempt @mechanism.
+ *
+ * Determines whether or not the information in @ctx is there for @mechanism
+ * to work.
+ *
+ * For example, the PLAIN mechanism should only be attempted if
+ * [property@Hasl.Context:tls] is %TRUE or if
+ * [property@Hasl.Context:allow-plain-in-clear] is %TRUE.
+ *
+ * Mechanisms should also implement this checking authzid, username, and
+ * password as necessary to avoid multiple round trips with the server that we
+ * now aren't going to work.
+ *
+ * Returns: %TRUE if @mechanism should be attempted otherwise %FALSE with
+ * @error optionally set.
+ */
+gboolean hasl_mechanism_possible(HaslMechanism *mechanism, HaslContext *ctx, GError **error);
+
G_END_DECLS
#endif /* HASL_MECHANISM_H */
--- a/hasl/tests/test-mechanism.c Tue Feb 14 22:09:23 2023 -0600
+++ b/hasl/tests/test-mechanism.c Tue Feb 14 22:49:40 2023 -0600
@@ -19,6 +19,8 @@
#include <hasl.h>
+#define TEST_HASL_DOMAIN (g_quark_from_static_string("test-hasl"))
+
/******************************************************************************
* Mechanism Implementation
*****************************************************************************/
@@ -27,10 +29,27 @@
struct _TestHaslMechanism {
HaslMechanism parent;
+
+ gboolean possible;
+ GError *possible_error;
};
G_DEFINE_TYPE(TestHaslMechanism, test_hasl_mechanism, HASL_TYPE_MECHANISM)
+static gboolean
+test_hasl_mechanism_possible(HaslMechanism *mechanism,
+ G_GNUC_UNUSED HaslContext *ctx,
+ GError **error)
+{
+ TestHaslMechanism *test_mechanism = (TestHaslMechanism *)mechanism;
+
+ if(test_mechanism->possible_error != NULL) {
+ g_propagate_error(error, test_mechanism->possible_error);
+ }
+
+ return test_mechanism->possible;
+}
+
static HaslMechanismResult
test_hasl_mechanism_step(HaslMechanism *mechanism, HaslContext *ctx,
const guint8 *server_in, gsize server_in_length,
@@ -50,8 +69,7 @@
*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");
+ g_set_error(error, TEST_HASL_DOMAIN, 0, "this is an error");
return HASL_MECHANISM_RESULT_ERROR;
}
@@ -64,6 +82,7 @@
test_hasl_mechanism_class_init(TestHaslMechanismClass *klass) {
HaslMechanismClass *mechanism_class = HASL_MECHANISM_CLASS(klass);
+ mechanism_class->possible = test_hasl_mechanism_possible;
mechanism_class->step = test_hasl_mechanism_step;
}
@@ -71,6 +90,55 @@
* Tests
*****************************************************************************/
static void
+test_hasl_mechanism_implementation_possible_true(void) {
+ TestHaslMechanism *test_mechanism = NULL;
+ HaslMechanism *mechanism = NULL;
+ HaslContext *ctx = NULL;
+ GError *error = NULL;
+ gboolean ret = FALSE;
+
+ mechanism = g_object_new(test_hasl_mechanism_get_type(), NULL);
+ test_mechanism = TEST_HASL_MECHANISM(mechanism);
+ test_mechanism->possible = TRUE;
+
+ ctx = hasl_context_new();
+
+ ret = hasl_mechanism_possible(mechanism, ctx, &error);
+ g_assert_no_error(error);
+ g_assert_true(ret);
+
+ g_clear_object(&mechanism);
+ g_clear_object(&ctx);
+}
+
+static void
+test_hasl_mechanism_implementation_possible_false(void) {
+ TestHaslMechanism *test_mechanism = NULL;
+ HaslMechanism *mechanism = NULL;
+ HaslContext *ctx = NULL;
+ GError *error = NULL;
+ gboolean ret = FALSE;
+
+ mechanism = g_object_new(test_hasl_mechanism_get_type(), NULL);
+
+ test_mechanism = TEST_HASL_MECHANISM(mechanism);
+ test_mechanism->possible = FALSE;
+ test_mechanism->possible_error = g_error_new(TEST_HASL_DOMAIN, 0, "error");
+
+ ctx = hasl_context_new();
+
+ ret = hasl_mechanism_possible(mechanism, ctx, &error);
+
+ g_assert_error(error, TEST_HASL_DOMAIN, 0);
+ g_clear_error(&error);
+
+ g_assert_false(ret);
+
+ g_clear_object(&mechanism);
+ g_clear_object(&ctx);
+}
+
+static void
test_hasl_mechanism_step_implementation(void) {
HaslContext *ctx = NULL;
HaslMechanism *mechanism = NULL;
@@ -122,6 +190,25 @@
g_clear_object(&mechanism);
}
+static void
+test_hasl_mechanism_no_implementation_possible(void) {
+ HaslMechanism *mechanism = NULL;
+ HaslContext *context = NULL;
+ GError *error = NULL;
+ gboolean ret = FALSE;
+
+ mechanism = g_object_new(HASL_TYPE_MECHANISM, NULL);
+ context = hasl_context_new();
+
+ ret = hasl_mechanism_possible(mechanism, context, &error);
+
+ g_assert_no_error(error);
+ g_assert_true(ret);
+
+ g_clear_object(&context);
+ g_clear_object(&mechanism);
+}
+
/******************************************************************************
* Main
*****************************************************************************/
@@ -129,6 +216,14 @@
main(int argc, char *argv[]) {
g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/hasl/mechanism/implementation/possible/true",
+ test_hasl_mechanism_implementation_possible_true);
+ g_test_add_func("/hasl/mechanism/implementation/possible/false",
+ test_hasl_mechanism_implementation_possible_false);
+
+ g_test_add_func("/hasl/mechanism/no-implementation/possible",
+ test_hasl_mechanism_no_implementation_possible);
+
g_test_add_func("/hasl/mechanism/step/implementation",
test_hasl_mechanism_step_implementation);
g_test_add_func("/hasl/mechanism/step/no-implementation",