--- 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 @@
/******************************************************************************
*****************************************************************************/
+hasl_mechanism_possible(HaslMechanism *mechanism, HaslContext *ctx, + 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); 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 @@
+ 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);
@@ -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 + * 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); #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 @@
+#define TEST_HASL_DOMAIN (g_quark_from_static_string("test-hasl")) /******************************************************************************
* Mechanism Implementation
*****************************************************************************/
@@ -27,10 +29,27 @@
struct _TestHaslMechanism {
+ GError *possible_error; G_DEFINE_TYPE(TestHaslMechanism, test_hasl_mechanism, HASL_TYPE_MECHANISM)
+test_hasl_mechanism_possible(HaslMechanism *mechanism, + G_GNUC_UNUSED HaslContext *ctx, + 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,
+ 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 @@
*****************************************************************************/
+test_hasl_mechanism_implementation_possible_true(void) { + TestHaslMechanism *test_mechanism = NULL; + HaslMechanism *mechanism = NULL; + HaslContext *ctx = NULL; + 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_clear_object(&mechanism); +test_hasl_mechanism_implementation_possible_false(void) { + TestHaslMechanism *test_mechanism = NULL; + HaslMechanism *mechanism = NULL; + HaslContext *ctx = NULL; + 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_object(&mechanism); test_hasl_mechanism_step_implementation(void) {
HaslMechanism *mechanism = NULL;
@@ -122,6 +190,25 @@
g_clear_object(&mechanism);
+test_hasl_mechanism_no_implementation_possible(void) { + HaslMechanism *mechanism = NULL; + HaslContext *context = NULL; + 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_clear_object(&context); + g_clear_object(&mechanism); /******************************************************************************
*****************************************************************************/
@@ -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",