]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Return error from db_oauth2_init
authorAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 25 Mar 2024 08:29:32 +0000 (10:29 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:39:59 +0000 (10:39 +0200)
src/auth/auth-worker-server.c
src/auth/db-oauth2.c
src/auth/db-oauth2.h
src/auth/mech-oauth2.c
src/auth/passdb-oauth2.c

index 999d1287e1cbcb1634c3e3631ca9c3e5f5cebf15..a43af1156de301144d6ea42aa3370ef9098f956b 100644 (file)
@@ -1006,6 +1006,7 @@ auth_worker_server_create(struct auth *auth,
                          const struct master_service_connection *master_conn)
 {
        struct auth_worker_server *server;
+       const char *error;
 
        if (clients == NULL)
                clients = connection_list_init(&auth_worker_server_set,
@@ -1022,8 +1023,14 @@ auth_worker_server_create(struct auth *auth,
 
        auth_worker_refresh_proctitle(WORKER_STATE_HANDSHAKE);
 
-       if (*auth->protocol_set->oauth2_config_file != '\0')
-               server->oauth2 = db_oauth2_init(auth->protocol_set->oauth2_config_file);
+       if (*auth->protocol_set->oauth2_config_file != '\0') {
+               if (db_oauth2_init(auth->protocol_set->oauth2_config_file,
+                                  &server->oauth2, &error) < 0) {
+                       e_error(auth_event, "Cannot initialize oauth2: %s",
+                               error);
+                       auth_worker_server_error = TRUE;
+               }
+       }
        if (auth_worker_server_error)
                auth_worker_server_send_error();
        return server;
index c02e3484113af03c8ffb61fed74368be42e28f68..6cf7197a65a25cb6ce651685aa025d0d52b3394a 100644 (file)
@@ -147,6 +147,7 @@ static struct passdb_oauth2_settings default_oauth2_settings = {
 static void db_oauth2_callback(struct db_oauth2_request *req,
                               enum passdb_result result,
                               const char *error_prefix, const char *error);
+static void db_oauth2_free(struct db_oauth2 **_db);
 
 static const char *parse_setting(const char *key, const char *value,
                                 struct db_oauth2 *db)
@@ -155,25 +156,30 @@ static const char *parse_setting(const char *key, const char *value,
                                       &db->set_store, key, value);
 }
 
-static void db_oauth2_setup(struct db_oauth2 *db)
+static int db_oauth2_setup(struct db_oauth2 *db, const char **error_r)
 {
        const char *error;
-       if (!settings_read_nosection(db->config_path, parse_setting, db, &error))
-               i_fatal("oauth2 %s: %s", db->config_path, error);
+       if (!settings_read_nosection(db->config_path, parse_setting, db, &error)) {
+               *error_r = t_strdup_printf("oauth2 %s: %s", db->config_path, error);
+               return -1;
+       }
 
        db->tmpl = passdb_template_build(db->pool, db->set->pass_attrs);
 
        if (*db->set->local_validation_key_dict == '\0' &&
            *db->set->tokeninfo_url == '\0' &&
            (*db->set->grant_url == '\0' || *db->set->client_id == '\0') &&
-           *db->set->introspection_url == '\0')
-               i_fatal("oauth2: Password grant, tokeninfo, introspection URL or "
-                       "validation key dictionary must be given");
+           *db->set->introspection_url == '\0') {
+               *error_r = "oauth2: Password grant, tokeninfo, introspection URL or validation key dictionary must be given";
+               return -1;
+       }
 
        struct event *event = event_create(auth_event);
        event_set_ptr(event, SETTINGS_EVENT_FILTER_NAME, "oauth2");
-       if (http_client_init_auto(event, &db->client, &error) < 0)
-               i_fatal("%s", error);
+       if (http_client_init_auto(event, &db->client, &error) < 0) {
+               *error_r = t_strdup_printf("%s", error);
+               return -1;
+       }
        event_unref(&event);
 
        i_zero(&db->oauth2_set);
@@ -188,8 +194,10 @@ static void db_oauth2_setup(struct db_oauth2 *db)
        db->oauth2_set.scope = db->set->scope;
 
        if (*db->set->active_attribute == '\0' &&
-           *db->set->active_value != '\0')
-               i_fatal("oauth2: Cannot have empty active_attribute is active_value is set");
+           *db->set->active_value != '\0') {
+               *error_r = "oauth2: Cannot have empty active_attribute is active_value is set";
+               return -1;
+       }
 
        if (*db->set->introspection_mode == '\0' ||
            strcmp(db->set->introspection_mode, "auth") == 0) {
@@ -199,13 +207,15 @@ static void db_oauth2_setup(struct db_oauth2 *db)
        } else if (strcmp(db->set->introspection_mode, "post") == 0) {
                db->oauth2_set.introspection_mode = INTROSPECTION_MODE_POST;
        } else if (strcmp(db->set->introspection_mode, "local") == 0) {
-               if (*db->set->local_validation_key_dict == '\0')
-                       i_fatal("oauth2: local_validation_key_dict is required "
-                               "for local introspection.");
+               if (*db->set->local_validation_key_dict == '\0') {
+                       *error_r = "oauth2: local_validation_key_dict is required for local introspection.";
+                       return -1;
+               }
                db->oauth2_set.introspection_mode = INTROSPECTION_MODE_LOCAL;
        } else {
-               i_fatal("oauth2: Invalid value '%s' for introspection mode, must be on auth, get, post or local",
-                       db->set->introspection_mode);
+               *error_r = t_strdup_printf("oauth2: Invalid value '%s' for introspection mode, must be on auth, get, post or local",
+                                          db->set->introspection_mode);
+               return -1;
        }
 
        if (db->oauth2_set.introspection_mode == INTROSPECTION_MODE_LOCAL) {
@@ -214,8 +224,11 @@ static void db_oauth2_setup(struct db_oauth2 *db)
                        .event_parent = auth_event,
                };
                if (dict_init_legacy(db->set->local_validation_key_dict, &dict_set,
-                                    &db->oauth2_set.key_dict, &error) < 0)
-                       i_fatal("Cannot initialize key dict: %s", error);
+                                    &db->oauth2_set.key_dict, &error) < 0) {
+                       *error_r = t_strdup_printf("Cannot initialize key dict: %s",
+                                                  error);
+                       return -1;
+               }
                /* failure to initialize dcrypt is not fatal - we can still
                   validate HMAC based keys */
                (void)dcrypt_initialize(NULL, NULL, &error);
@@ -232,19 +245,24 @@ static void db_oauth2_setup(struct db_oauth2 *db)
                if (http_url_parse(db->set->openid_configuration_url, NULL, 0,
                                   pool_datastack_create(), &parsed_url,
                                   &error) < 0) {
-                       i_fatal("Invalid openid_configuration_url: %s",
-                               error);
+                       *error_r = t_strdup_printf("Invalid openid_configuration_url: %s",
+                                                  error);
+                       return -1;
                }
        }
+
+       return 0;
 }
 
-struct db_oauth2 *db_oauth2_init(const char *config_path)
+int db_oauth2_init(const char *config_path, struct db_oauth2 **db_r,
+                  const char **error_r)
 {
        struct db_oauth2 *db;
 
        for(db = db_oauth2_head; db != NULL; db = db->next) {
                if (strcmp(db->config_path, config_path) == 0) {
-                       return db;
+                       *db_r = db;
+                       return 0;
                }
        }
 
@@ -254,9 +272,14 @@ struct db_oauth2 *db_oauth2_init(const char *config_path)
        db->config_path = p_strdup(pool, config_path);
        db->set = &default_oauth2_settings;
        DLLIST_PREPEND(&db_oauth2_head, db);
-       db_oauth2_setup(db);
 
-       return db;
+       if (db_oauth2_setup(db, error_r) < 0) {
+               db_oauth2_free(&db);
+               return -1;
+       }
+
+       *db_r = db;
+       return 0;
 }
 
 static void db_oauth2_free(struct db_oauth2 **_db)
@@ -283,7 +306,8 @@ static void db_oauth2_free(struct db_oauth2 **_db)
                                           "", "aborted");
                }
        }
-       http_client_deinit(&db->client);
+       if (db->client != NULL)
+               http_client_deinit(&db->client);
        if (db->oauth2_set.key_dict != NULL)
                dict_deinit(&db->oauth2_set.key_dict);
        oauth2_validation_key_cache_deinit(&db->oauth2_set.key_cache);
index 1b83d6cf7e230415f4d17fcdad03c30f56c5bd16..a23f56a3625c51b8f4f011a88f8932ad9205f67d 100644 (file)
@@ -30,7 +30,8 @@ struct db_oauth2_request {
 };
 
 
-struct db_oauth2 *db_oauth2_init(const char *config_path);
+int db_oauth2_init(const char *config_path, struct db_oauth2 **db_r,
+                  const char **error_r);
 
 bool db_oauth2_uses_password_grant(const struct db_oauth2 *db);
 bool db_oauth2_use_worker(const struct db_oauth2 *db);
index 3a44849ec6ebedbbd5c111d455a25b296f8ae789..3abc90e05c5c3851089a5d234cc76e5ec3633d57 100644 (file)
@@ -200,15 +200,18 @@ mech_oauth2_verify_token(struct oauth2_auth_request *oauth2_req, const char *tok
 
 static void oauth2_init_db(struct oauth2_auth_request *oauth2_req)
 {
+       const char *error;
        if (oauth2_req->db != NULL)
                return;
-       if (*oauth2_req->auth.set->oauth2_config_file != '\0')
-               oauth2_req->db = db_oauth2_init(oauth2_req->auth.set->oauth2_config_file);
-       else {
-               e_error(oauth2_req->auth.mech_event, "Cannot initialize oauth2");
-               oauth2_req->failed = TRUE;
-               auth_request_internal_failure(&oauth2_req->auth);
-       }
+       if (*oauth2_req->auth.set->oauth2_config_file != '\0') {
+               if (db_oauth2_init(oauth2_req->auth.set->oauth2_config_file,
+                                  &oauth2_req->db, &error) >= 0)
+                       return;
+       } else
+               error = "No config file specified";
+       e_error(oauth2_req->auth.mech_event, "Cannot initialize oauth2: %s", error);
+       oauth2_req->failed = TRUE;
+       auth_request_internal_failure(&oauth2_req->auth);
 }
 
 /* Input syntax:
@@ -421,5 +424,3 @@ const struct mech_module mech_xoauth2 = {
        mech_xoauth2_auth_continue,
        mech_generic_auth_free
 };
-
-
index f75b894190ba7fb975fb3dc52e7a8a941665b715..dd59b1b4a50626f3fe68f4093470b0a41588f6da 100644 (file)
@@ -47,9 +47,11 @@ static struct passdb_module *
 oauth2_preinit(pool_t pool, const char *args)
 {
        struct oauth2_passdb_module *module;
+       const char *error;
 
        module = p_new(pool, struct oauth2_passdb_module, 1);
-       module->db = db_oauth2_init(args);
+       if (db_oauth2_init(args, &module->db, &error) < 0)
+               i_fatal("%s", error);
        module->module.default_pass_scheme = "PLAIN";
 
        if (db_oauth2_uses_password_grant(module->db)) {