]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: API change - var_expand*() now returns error string.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 31 Oct 2016 19:48:16 +0000 (21:48 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 2 Nov 2016 12:11:23 +0000 (14:11 +0200)
This allows callers to fail properly if the format string is invalid.

66 files changed:
src/auth/auth-cache.c
src/auth/auth-policy.c
src/auth/auth-request-var-expand.c
src/auth/auth-request-var-expand.h
src/auth/auth-request.c
src/auth/db-checkpassword.c
src/auth/db-dict.c
src/auth/db-ldap.c
src/auth/db-passwd-file.c
src/auth/passdb-imap.c
src/auth/passdb-ldap.c
src/auth/passdb-pam.c
src/auth/passdb-passwd-file.c
src/auth/passdb-sql.c
src/auth/passdb-static.c
src/auth/passdb-template.c
src/auth/passdb-template.h
src/auth/test-auth-cache.c
src/auth/test-auth-request-var-expand.c
src/auth/userdb-dict.c
src/auth/userdb-ldap.c
src/auth/userdb-passwd-file.c
src/auth/userdb-passwd.c
src/auth/userdb-sql.c
src/auth/userdb-static.c
src/auth/userdb-template.c
src/auth/userdb-template.h
src/director/director-request.c
src/director/director.c
src/director/doveadm-connection.c
src/director/notify-connection.c
src/director/test-user-directory.c
src/director/user-directory.c
src/director/user-directory.h
src/doveadm/doveadm-auth-server.c
src/doveadm/doveadm-auth.c
src/doveadm/doveadm-director.c
src/doveadm/doveadm-dsync.c
src/doveadm/doveadm-print-formatted.c
src/imap-hibernate/imap-client.c
src/imap-urlauth/imap-urlauth-worker.c
src/imap/imap-client.c
src/imap/main.c
src/lda/main.c
src/lib-lda/mail-deliver.c
src/lib-lda/mail-send.c
src/lib-mail/mail-user-hash.c
src/lib-mail/mail-user-hash.h
src/lib-settings/settings-parser.c
src/lib-settings/settings-parser.h
src/lib-sql/driver-cassandra.c
src/lib-storage/index/shared/shared-storage.c
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-user.c
src/lib/test-var-expand.c
src/lib/var-expand.c
src/lib/var-expand.h
src/lmtp/client.c
src/lmtp/commands.c
src/login-common/client-common.c
src/login-common/login-proxy.c
src/login-common/login-settings.c
src/plugins/acl/acl-shared-storage.c
src/plugins/dict-ldap/dict-ldap.c
src/pop3/pop3-client.c
src/pop3/pop3-commands.c

index 58f3dd5d2bea38a77681316fca3ceb9e75614833..eaad8b1105e3d811e9d67fc339967ff973f23737 100644 (file)
@@ -340,13 +340,21 @@ static const char *
 auth_request_expand_cache_key(const struct auth_request *request,
                              const char *key)
 {
+       static bool error_logged = FALSE;
+       const char *value, *error;
+
        /* Uniquely identify the request's passdb/userdb with the P/U prefix
           and by "%!", which expands to the passdb/userdb ID number. */
        key = t_strconcat(request->userdb_lookup ? "U" : "P", "%!",
                          request->master_user == NULL ? "" : "+%{master_user}",
                          "\t", key, NULL);
 
-       return t_auth_request_var_expand(key, request, auth_cache_escape);
+       if (t_auth_request_var_expand(key, request, auth_cache_escape,
+                                     &value, &error) <= 0 && !error_logged) {
+               error_logged = TRUE;
+               i_error("Failed to expand auth cache key %s: %s", key, error);
+       }
+       return value;
 }
 
 const char *
index cefd3b34f424bec84ae96d86ffdc6246f29293ca..c79aba93954d9b056f7877dcbd12f9ca2cbd54ca 100755 (executable)
@@ -465,9 +465,13 @@ void auth_policy_create_json(struct policy_lookup_ctx *context,
        const char *hashed_password = binary_to_hex(str_data(buffer), str_len(buffer));
        str_append_c(context->json, '{');
        var_table = policy_get_var_expand_table(context->request, hashed_password);
-       auth_request_var_expand_with_table(context->json, auth_policy_json_template,
-                                          context->request, var_table,
-                                          auth_policy_escape_function);
+       const char *error;
+       if (auth_request_var_expand_with_table(context->json, auth_policy_json_template,
+                                              context->request, var_table,
+                                              auth_policy_escape_function, &error) <= 0) {
+               auth_request_log_error(context->request, "policy",
+                       "Failed to expand auth policy template: %s", error);
+       }
        if (include_success) {
                str_append(context->json, ",\"success\":");
                if (!context->request->failed && context->request->successful &&
index f5d6c2d96d2a0a0f3d69d606b915b72dae38d0b3..ccc49f1f17a25c235ba4970e8a0ca0ae8698e1d3 100644 (file)
@@ -226,35 +226,39 @@ const struct var_expand_func_table auth_request_var_funcs_table[] = {
        { NULL, NULL }
 };
 
-void auth_request_var_expand(string_t *dest, const char *str,
-                            const struct auth_request *auth_request,
-                            auth_request_escape_func_t *escape_func)
+int auth_request_var_expand(string_t *dest, const char *str,
+                           const struct auth_request *auth_request,
+                           auth_request_escape_func_t *escape_func,
+                           const char **error_r)
 {
-       auth_request_var_expand_with_table(dest, str, auth_request,
+       return auth_request_var_expand_with_table(dest, str, auth_request,
                auth_request_get_var_expand_table(auth_request, escape_func),
-               escape_func);
+               escape_func, error_r);
 }
 
-void auth_request_var_expand_with_table(string_t *dest, const char *str,
-                                       const struct auth_request *auth_request,
-                                       const struct var_expand_table *table,
-                                       auth_request_escape_func_t *escape_func)
+int auth_request_var_expand_with_table(string_t *dest, const char *str,
+                                      const struct auth_request *auth_request,
+                                      const struct var_expand_table *table,
+                                      auth_request_escape_func_t *escape_func,
+                                      const char **error_r)
 {
        struct auth_request_var_expand_ctx ctx;
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.auth_request = auth_request;
        ctx.escape_func = escape_func == NULL ? escape_none : escape_func;
-       var_expand_with_funcs(dest, str, table,
-                             auth_request_var_funcs_table, &ctx);
+       return var_expand_with_funcs(dest, str, table,
+                                    auth_request_var_funcs_table, &ctx, error_r);
 }
 
-const char *
-t_auth_request_var_expand(const char *str,
-                         const struct auth_request *auth_request,
-                         auth_request_escape_func_t *escape_func)
+int t_auth_request_var_expand(const char *str,
+                             const struct auth_request *auth_request ATTR_UNUSED,
+                             auth_request_escape_func_t *escape_func ATTR_UNUSED,
+                             const char **value_r, const char **error_r)
 {
        string_t *dest = t_str_new(128);
-       auth_request_var_expand(dest, str, auth_request, escape_func);
-       return str_c(dest);
+       int ret = auth_request_var_expand(dest, str, auth_request,
+                                         escape_func, error_r);
+       *value_r = str_c(dest);
+       return ret;
 }
index 0d228daad2fa4308636aa248b4fc5360abd6ead3..7ad2b14a31cd7abab36c5dfffad8fd18c6eaf50a 100644 (file)
@@ -21,17 +21,19 @@ auth_request_get_var_expand_table_full(const struct auth_request *auth_request,
                                       auth_request_escape_func_t *escape_func,
                                       unsigned int *count) ATTR_NULL(2);
 
-void auth_request_var_expand(string_t *dest, const char *str,
-                            const struct auth_request *auth_request,
-                            auth_request_escape_func_t *escape_func);
-void auth_request_var_expand_with_table(string_t *dest, const char *str,
-                                       const struct auth_request *auth_request,
-                                       const struct var_expand_table *table,
-                                       auth_request_escape_func_t *escape_func);
-const char *
-t_auth_request_var_expand(const char *str,
-                         const struct auth_request *auth_request,
-                         auth_request_escape_func_t *escape_func);
+int auth_request_var_expand(string_t *dest, const char *str,
+                           const struct auth_request *auth_request,
+                           auth_request_escape_func_t *escape_func,
+                           const char **error_r);
+int auth_request_var_expand_with_table(string_t *dest, const char *str,
+                                      const struct auth_request *auth_request,
+                                      const struct var_expand_table *table,
+                                      auth_request_escape_func_t *escape_func,
+                                      const char **error_r);
+int t_auth_request_var_expand(const char *str,
+                             const struct auth_request *auth_request,
+                             auth_request_escape_func_t *escape_func,
+                             const char **value_r, const char **error_r);
 
 const char *auth_request_str_escape(const char *string,
                                    const struct auth_request *request);
index a715807e9a687ef15763729b84cd2d7e60babad4..f0de6233f52c190430aed86417a06cbb919240d5 100644 (file)
@@ -798,7 +798,14 @@ static void
 auth_request_verify_plain_callback_finish(enum passdb_result result,
                                          struct auth_request *request)
 {
-       passdb_template_export(request->passdb->override_fields_tmpl, request);
+       const char *error;
+
+       if (passdb_template_export(request->passdb->override_fields_tmpl,
+                                  request, &error) < 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand override_fields: %s", error);
+               result = PASSDB_RESULT_INTERNAL_FAILURE;
+       }
        if (!auth_request_handle_passdb_callback(&result, request)) {
                /* try next passdb */
                auth_request_verify_plain(request, request->mech_password,
@@ -949,7 +956,7 @@ void auth_request_verify_plain_continue(struct auth_request *request,
 
        struct auth_passdb *passdb;
        enum passdb_result result;
-       const char *cache_key;
+       const char *cache_key, *error;
        const char *password = request->mech_password;
 
        i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
@@ -987,8 +994,13 @@ void auth_request_verify_plain_continue(struct auth_request *request,
                        PASSDB_RESULT_INTERNAL_FAILURE, request);
        } else if (passdb->passdb->blocking) {
                passdb_blocking_verify_plain(request);
+       } else if (passdb_template_export(passdb->default_fields_tmpl,
+                                         request, &error) < 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand default_fields: %s", error);
+               auth_request_verify_plain_callback(
+                       PASSDB_RESULT_INTERNAL_FAILURE, request);
        } else {
-               passdb_template_export(passdb->default_fields_tmpl, request);
                passdb->passdb->iface.verify_plain(request, password,
                                           auth_request_verify_plain_callback);
        }
@@ -1000,7 +1012,14 @@ auth_request_lookup_credentials_finish(enum passdb_result result,
                                        size_t size,
                                        struct auth_request *request)
 {
-       passdb_template_export(request->passdb->override_fields_tmpl, request);
+       const char *error;
+
+       if (passdb_template_export(request->passdb->override_fields_tmpl,
+                                  request, &error) < 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand override_fields: %s", error);
+               result = PASSDB_RESULT_INTERNAL_FAILURE;
+       }
        if (!auth_request_handle_passdb_callback(&result, request)) {
                /* try next passdb */
                if (request->skip_password_check &&
@@ -1113,7 +1132,7 @@ void auth_request_lookup_credentials_policy_continue(struct auth_request *reques
                                                     lookup_credentials_callback_t *callback)
 {
        struct auth_passdb *passdb;
-       const char *cache_key, *cache_cred, *cache_scheme;
+       const char *cache_key, *cache_cred, *cache_scheme, *error;
        enum passdb_result result;
 
        i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
@@ -1150,8 +1169,14 @@ void auth_request_lookup_credentials_policy_continue(struct auth_request *reques
                                        uchar_empty_ptr, 0, request);
        } else if (passdb->passdb->blocking) {
                passdb_blocking_lookup_credentials(request);
+       } else if (passdb_template_export(passdb->default_fields_tmpl,
+                                         request, &error) < 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand default_fields: %s", error);
+               auth_request_lookup_credentials_callback(
+                                       PASSDB_RESULT_INTERNAL_FAILURE,
+                                       uchar_empty_ptr, 0, request);
        } else {
-               passdb_template_export(passdb->default_fields_tmpl, request);
                passdb->passdb->iface.lookup_credentials(request,
                        auth_request_lookup_credentials_callback);
        }
@@ -1266,6 +1291,7 @@ void auth_request_userdb_callback(enum userdb_result result,
        struct auth_userdb *userdb = request->userdb;
        struct auth_userdb *next_userdb;
        enum auth_db_rule result_rule;
+       const char *error;
        bool userdb_continue = FALSE;
 
        switch (result) {
@@ -1317,7 +1343,14 @@ void auth_request_userdb_callback(enum userdb_result result,
                if (result == USERDB_RESULT_OK) {
                        /* this userdb lookup succeeded, preserve its extra
                           fields */
-                       userdb_template_export(userdb->override_fields_tmpl, request);
+                       if (userdb_template_export(userdb->override_fields_tmpl,
+                                                  request, &error) < 0) {
+                               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                                       "Failed to expand override_fields: %s", error);
+                               request->private_callback.userdb(
+                                       USERDB_RESULT_INTERNAL_FAILURE, request);
+                               return;
+                       }
                        auth_fields_snapshot(request->userdb_reply);
                } else {
                        /* this userdb lookup failed, remove any extra fields
@@ -1332,8 +1365,14 @@ void auth_request_userdb_callback(enum userdb_result result,
        }
 
        if (request->userdb_success) {
-               result = USERDB_RESULT_OK;
-               userdb_template_export(userdb->override_fields_tmpl, request);
+               if (userdb_template_export(userdb->override_fields_tmpl,
+                                          request, &error) < 0) {
+                       auth_request_log_error(request, AUTH_SUBSYS_DB,
+                               "Failed to expand override_fields: %s", error);
+                       result = USERDB_RESULT_INTERNAL_FAILURE;
+               } else {
+                       result = USERDB_RESULT_OK;
+               }
        } else if (request->userdbs_seen_internal_failure ||
                   result == USERDB_RESULT_INTERNAL_FAILURE) {
                /* one of the userdb lookups failed. the user might have been
@@ -1379,7 +1418,7 @@ void auth_request_lookup_user(struct auth_request *request,
                              userdb_callback_t *callback)
 {
        struct auth_userdb *userdb = request->userdb;
-       const char *cache_key;
+       const char *cache_key, *error;
 
        request->private_callback.userdb = callback;
        request->userdb_lookup = TRUE;
@@ -1390,7 +1429,14 @@ void auth_request_lookup_user(struct auth_request *request,
                /* we still want to set default_fields. these override any
                   existing fields set by previous userdbs (because if that is
                   unwanted, ":protected" can be used). */
-               userdb_template_export(userdb->default_fields_tmpl, request);
+               if (userdb_template_export(userdb->default_fields_tmpl,
+                                          request, &error) < 0) {
+                       auth_request_log_error(request, AUTH_SUBSYS_DB,
+                               "Failed to expand default_fields: %s", error);
+                       auth_request_userdb_callback(
+                               USERDB_RESULT_INTERNAL_FAILURE, request);
+                       return;
+               }
        }
 
        /* (for now) auth_cache is shared between passdb and userdb */
@@ -1448,6 +1494,7 @@ auth_request_fix_username(struct auth_request *request, const char *username,
                /* username format given, put it through variable expansion.
                   we'll have to temporarily replace request->user to get
                   %u to be the wanted username */
+               const char *error;
                char *old_username;
                string_t *dest;
 
@@ -1455,7 +1502,12 @@ auth_request_fix_username(struct auth_request *request, const char *username,
                request->user = user;
 
                dest = t_str_new(256);
-               auth_request_var_expand(dest, set->username_format, request, NULL);
+               if (auth_request_var_expand(dest, set->username_format,
+                                           request, NULL, &error) <= 0) {
+                       *error_r = t_strdup_printf(
+                               "Failed to expand username_format=%s: %s",
+                               set->username_format, error);
+               }
                user = p_strdup(request->pool, str_c(dest));
 
                request->user = old_username;
@@ -1858,8 +1910,14 @@ void auth_request_set_fields(struct auth_request *request,
 
 void auth_request_init_userdb_reply(struct auth_request *request)
 {
+       const char *error;
+
        request->userdb_reply = auth_fields_init(request->pool);
-       userdb_template_export(request->userdb->default_fields_tmpl, request);
+       if (userdb_template_export(request->userdb->default_fields_tmpl,
+                                  request, &error) <= 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand default_fields: %s", error);
+       }
 }
 
 static void auth_request_set_uidgid_file(struct auth_request *request,
@@ -1867,10 +1925,15 @@ static void auth_request_set_uidgid_file(struct auth_request *request,
 {
        string_t *path;
        struct stat st;
+       const char *error;
 
        path = t_str_new(256);
-       auth_request_var_expand(path, path_template, request, NULL);
-       if (stat(str_c(path), &st) < 0) {
+       if (auth_request_var_expand(path, path_template, request,
+                                   NULL, &error) <= 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand uidgid_file=%s: %s", path_template, error);
+               request->userdb_lookup_tempfailed = TRUE;
+       } else if (stat(str_c(path), &st) < 0) {
                auth_request_log_error(request, AUTH_SUBSYS_DB,
                                        "stat(%s) failed: %m", str_c(path));
                request->userdb_lookup_tempfailed = TRUE;
index 79ba1373fc3f15c1521babe4bedd4bafffd315aa..b433d51191ad0a0e830b6709b078b3dd5f7cc644 100644 (file)
@@ -294,9 +294,14 @@ checkpassword_get_cmd(struct auth_request *request, const char *args,
                      const char *checkpassword_reply_path)
 {
        string_t *str;
+       const char *error;
 
        str = t_str_new(256);
-       auth_request_var_expand(str, args, request, NULL);
+       if (auth_request_var_expand(str, args, request, NULL, &error) <= 0) {
+               i_error("Failed to expand checkpassword_path=%s: %s",
+                       args, error);
+       }
+
        return t_strconcat(str_c(str), " ", checkpassword_reply_path, NULL);
 }
 
index 9cd60d0f833552a00097c42b3f70a7a9176da7a3..c10a5e3f2511934ab71a114a9c4229bd200f318a 100644 (file)
@@ -413,7 +413,12 @@ static int db_dict_iter_lookup_key_values(struct db_dict_value_iter *iter)
                        continue;
 
                str_truncate(path, strlen(DICT_PATH_SHARED));
-               var_expand(path, key->key->key, iter->var_expand_table);
+               ret = var_expand(path, key->key->key, iter->var_expand_table, &error);
+               if (ret <= 0) {
+                       auth_request_log_error(iter->auth_request, AUTH_SUBSYS_DB,
+                               "Failed to expand key %s: %s", key->key->key, error);
+                       return -1;
+               }
                ret = dict_lookup(iter->conn->dict, iter->pool,
                                  str_c(path), &key->value, &error);
                if (ret > 0) {
@@ -465,9 +470,15 @@ int db_dict_value_iter_init(struct dict_connection *conn,
                struct db_dict_key *new_key = p_new(iter->pool, struct db_dict_key, 1);
                memcpy(new_key, key, sizeof(struct db_dict_key));
                string_t *expanded_key = str_new(iter->pool, strlen(key->key));
-               auth_request_var_expand_with_table(expanded_key, key->key, auth_request,
-                                                  iter->var_expand_table,
-                                                  NULL);
+               const char *error;
+               if (auth_request_var_expand_with_table(expanded_key, key->key, auth_request,
+                                                      iter->var_expand_table,
+                                                      NULL, &error) <= 0) {
+                       auth_request_log_error(iter->auth_request, AUTH_SUBSYS_DB,
+                               "Failed to expand key %s: %s", key->key, error);
+                       pool_unref(&pool);
+                       return -1;
+               }
                new_key->key = str_c(expanded_key);
                iterkey->key = new_key;
        }
@@ -600,14 +611,21 @@ bool db_dict_value_iter_next(struct db_dict_value_iter *iter,
                { NULL, NULL }
        };
        const struct db_dict_field *field;
+       const char *error;
 
        if (iter->field_idx == array_count(iter->fields))
                return db_dict_value_iter_object_next(iter, key_r, value_r);
        field = array_idx(iter->fields, iter->field_idx++);
 
        str_truncate(iter->tmpstr, 0);
-       var_expand_with_funcs(iter->tmpstr, field->value,
-                             iter->var_expand_table, var_funcs_table, iter);
+       if (var_expand_with_funcs(iter->tmpstr, field->value,
+                                 iter->var_expand_table, var_funcs_table,
+                                 iter, &error) <= 0) {
+               iter->error = p_strdup_printf(iter->pool,
+                       "Failed to expand %s=%s: %s",
+                       field->name, field->value, error);
+               return FALSE;
+       }
        *key_r = field->name;
        *value_r = str_c(iter->tmpstr);
        return TRUE;
index 7374e0dca9da3d95e0d8cbb34f9ca1b170afd02c..9fd4ac33f0c2b4a7d2eee8b52c251283211dc99e 100644 (file)
@@ -624,7 +624,7 @@ ldap_request_send_subquery(struct ldap_connection *conn,
                { NULL, NULL }
        };
        const struct ldap_field *field;
-       const char *p;
+       const char *p, *error;
        char *name;
        struct ldap_field_find_subquery_context ctx;
        string_t *tmp_str = t_str_new(64);
@@ -637,8 +637,14 @@ ldap_request_send_subquery(struct ldap_connection *conn,
        array_foreach(request->attr_map, field) {
                if (field->ldap_attr_name[0] == '\0') {
                        str_truncate(tmp_str, 0);
-                       var_expand_with_funcs(tmp_str, field->value, NULL,
-                                             var_funcs_table, &ctx);
+                       if (var_expand_with_funcs(tmp_str, field->value, NULL,
+                                                 var_funcs_table, &ctx, &error) <= 0) {
+                               auth_request_log_error(request->request.auth_request,
+                                       AUTH_SUBSYS_DB,
+                                       "Failed to expand subquery %s: %s",
+                                       field->value, error);
+                               return -1;
+                       }
                } else {
                        p = strchr(field->ldap_attr_name, '@');
                        if (p != NULL &&
@@ -1369,7 +1375,7 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
        struct ldap_field_find_context ctx;
        struct ldap_field *field;
        string_t *tmp_str;
-       const char *const *attr, *attr_data, *p;
+       const char *const *attr, *attr_data, *p, *error;
        char *ldap_attr, *name, *templ;
        unsigned int i;
 
@@ -1406,8 +1412,11 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
                } else {
                        *templ++ = '\0';
                        str_truncate(tmp_str, 0);
-                       var_expand_with_funcs(tmp_str, templ, NULL,
-                                             var_funcs_table, &ctx);
+                       if (var_expand_with_funcs(tmp_str, templ, NULL,
+                                                 var_funcs_table, &ctx, &error) <= 0) {
+                               i_error("LDAP %s: Failed to expand attr_names=%s: %s",
+                                       conn->config_path, name, error);
+                       }
                        if (strchr(templ, '%') == NULL) {
                                /* backwards compatibility:
                                   attr=name=prefix means same as
@@ -1667,7 +1676,7 @@ db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx,
                            struct db_ldap_value *ldap_value)
 {
        const struct var_expand_table *var_table;
-       const char *const *values;
+       const char *const *values, *error;
 
        if (ldap_value != NULL)
                values = ldap_value->values;
@@ -1699,8 +1708,12 @@ db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx,
                      (and less importantly the same for other variables) */
                var_table = db_ldap_value_get_var_expand_table(ctx->auth_request,
                                                               values[0]);
-               var_expand_with_funcs(ctx->var, field->value, var_table,
-                                     ldap_var_funcs_table, ctx);
+               if (var_expand_with_funcs(ctx->var, field->value, var_table,
+                                         ldap_var_funcs_table, ctx, &error) <= 0) {
+                       auth_request_log_warning(ctx->auth_request, AUTH_SUBSYS_DB,
+                               "Failed to expand template %s: %s",
+                               field->value, error);
+               }
                ctx->val_1_arr[0] = str_c(ctx->var);
                values = ctx->val_1_arr;
        }
@@ -1711,9 +1724,11 @@ bool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
                                 const char **name_r,
                                 const char *const **values_r)
 {
+       const struct var_expand_table *tab;
        const struct ldap_field *field;
        struct db_ldap_value *ldap_value;
        unsigned int pos;
+       const char *error;
 
        do {
                if (ctx->attr_idx == array_count(ctx->attr_map))
@@ -1740,9 +1755,12 @@ bool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
                str_append_c(ctx->var, '\0');
                pos = str_len(ctx->var);
 
-               var_expand_with_funcs(ctx->var, field->name,
-                       auth_request_get_var_expand_table(ctx->auth_request, NULL),
-                       ldap_var_funcs_table, ctx);
+               tab = auth_request_get_var_expand_table(ctx->auth_request, NULL);
+               if (var_expand_with_funcs(ctx->var, field->name, tab,
+                                         ldap_var_funcs_table, ctx, &error) <= 0) {
+                       auth_request_log_warning(ctx->auth_request, AUTH_SUBSYS_DB,
+                               "Failed to expand %s: %s", field->name, error);
+               }
                *name_r = str_c(ctx->var) + pos;
        }
 
index 819cfcf6cc7d624fe2ce3b5fab8bfaa5f5398da7..49fdde6582e786c163969caeb8c6d262e4a31ea1 100644 (file)
@@ -349,10 +349,12 @@ db_passwd_file_init(const char *path, bool userdb, bool debug)
                /* just extra escaped % chars. remove them. */
                struct var_expand_table empty_table[1];
                string_t *dest;
+               const char *error;
 
                empty_table[0].key = '\0';
                dest = t_str_new(256);
-               var_expand(dest, path, empty_table);
+               if (var_expand(dest, path, empty_table, &error) <= 0)
+                       i_unreached();
                path = str_c(dest);
        }
 
@@ -435,12 +437,19 @@ int db_passwd_file_lookup(struct db_passwd_file *db,
 {
        struct passwd_file *pw;
        string_t *username, *dest;
+       const char *error;
 
        if (!db->vars)
                pw = db->default_file;
        else {
                dest = t_str_new(256);
-               auth_request_var_expand(dest, db->path, request, path_fix);
+               if (auth_request_var_expand(dest, db->path, request, path_fix,
+                                           &error) <= 0) {
+                       auth_request_log_error(request, AUTH_SUBSYS_DB,
+                               "Failed to expand passwd-file path %s: %s",
+                               db->path, error);
+                       return -1;
+               }
 
                pw = hash_table_lookup(db->files, str_c(dest));
                if (pw == NULL) {
@@ -455,8 +464,13 @@ int db_passwd_file_lookup(struct db_passwd_file *db,
        }
 
        username = t_str_new(256);
-       auth_request_var_expand(username, username_format, request,
-                               auth_request_str_escape);
+       if (auth_request_var_expand(username, username_format, request,
+                                   auth_request_str_escape, &error) <= 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand username_format=%s: %s",
+                       username_format, error);
+               return -1;
+       }
 
        auth_request_log_debug(request, AUTH_SUBSYS_DB,
                               "lookup: user=%s file=%s",
index bbce9020eb2b7897229a16e5ba97e1d0e9fa5945..9a5a1b7bd9b71067c7acd048a4d1931796aa685b 100644 (file)
@@ -76,6 +76,7 @@ passdb_imap_verify_plain(struct auth_request *auth_request,
                (struct imap_passdb_module *)_module;
        struct imap_auth_request *request;
        struct imapc_client_settings set;
+       const char *error;
        string_t *str;
 
        set = module->set;
@@ -88,11 +89,25 @@ passdb_imap_verify_plain(struct auth_request *auth_request,
 
        if (module->set_have_vars) {
                str = t_str_new(128);
-               auth_request_var_expand(str, set.username, auth_request, NULL);
+               if (auth_request_var_expand(str, set.username, auth_request,
+                                           NULL, &error) <= 0) {
+                       auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                               "Failed to expand username=%s: %s",
+                               set.username, error);
+                       callback(PASSDB_RESULT_INTERNAL_FAILURE, auth_request);
+                       return;
+               }
                set.username = t_strdup(str_c(str));
 
                str_truncate(str, 0);
-               auth_request_var_expand(str, set.host, auth_request, NULL);
+               if (auth_request_var_expand(str, set.host, auth_request,
+                                           NULL, &error) <= 0) {
+                       auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                               "Failed to expand host=%s: %s",
+                               set.host, error);
+                       callback(PASSDB_RESULT_INTERNAL_FAILURE, auth_request);
+                       return;
+               }
                set.host = t_strdup(str_c(str));
        }
        auth_request_log_debug(auth_request, AUTH_SUBSYS_DB,
index 2f876df87e4de294f78b2a27159bd98f491cc8d0..65b0d1d26af0545d989b8ce0a90aa69af267a4e8 100644 (file)
@@ -203,6 +203,20 @@ static void ldap_auth_bind(struct ldap_connection *conn,
        db_ldap_request(conn, &brequest->request);
 }
 
+static void passdb_ldap_request_fail(struct passdb_ldap_request *request,
+                                    enum passdb_result passdb_result)
+{
+       struct auth_request *auth_request = request->request.ldap.auth_request;
+
+       if (auth_request->credentials_scheme != NULL) {
+               request->callback.lookup_credentials(passdb_result, NULL, 0,
+                                                    auth_request);
+       } else {
+               request->callback.verify_plain(passdb_result, auth_request);
+       }
+       auth_request_unref(&auth_request);
+}
+
 static void
 ldap_bind_lookup_dn_fail(struct auth_request *auth_request,
                         struct passdb_ldap_request *request,
@@ -222,13 +236,7 @@ ldap_bind_lookup_dn_fail(struct auth_request *auth_request,
                passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
        }
 
-       if (auth_request->credentials_scheme != NULL) {
-               request->callback.lookup_credentials(passdb_result, NULL, 0,
-                                                    auth_request);
-       } else {
-               request->callback.verify_plain(passdb_result, auth_request);
-       }
-       auth_request_unref(&auth_request);
+       passdb_ldap_request_fail(request, passdb_result);
 }
 
 static void ldap_bind_lookup_dn_callback(struct ldap_connection *conn,
@@ -288,18 +296,31 @@ static void ldap_lookup_pass(struct auth_request *auth_request,
        struct ldap_connection *conn = module->conn;
        struct ldap_request_search *srequest = &request->request.search;
        const char **attr_names = (const char **)conn->pass_attr_names;
+       const char *error;
        string_t *str;
 
        request->require_password = require_password;
        srequest->request.type = LDAP_REQUEST_TYPE_SEARCH;
 
        str = t_str_new(512);
-       auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.base, auth_request,
+                                   ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand base=%s: %s", conn->set.base, error);
+               passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
+               return;
+       }
        srequest->base = p_strdup(auth_request->pool, str_c(str));
 
        str_truncate(str, 0);
-       auth_request_var_expand(str, conn->set.pass_filter,
-                               auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.pass_filter,
+                                   auth_request, ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand pass_filter=%s: %s",
+                       conn->set.pass_filter, error);
+               passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
+               return;
+       }
        srequest->filter = p_strdup(auth_request->pool, str_c(str));
        srequest->attr_map = &conn->pass_attr_map;
        srequest->attributes = conn->pass_attr_names;
@@ -322,17 +343,30 @@ static void ldap_bind_lookup_dn(struct auth_request *auth_request,
                (struct ldap_passdb_module *)_module;
        struct ldap_connection *conn = module->conn;
        struct ldap_request_search *srequest = &request->request.search;
+       const char *error;
        string_t *str;
 
        srequest->request.type = LDAP_REQUEST_TYPE_SEARCH;
 
        str = t_str_new(512);
-       auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.base, auth_request,
+                                   ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand base=%s: %s", conn->set.base, error);
+               passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
+               return;
+       }
        srequest->base = p_strdup(auth_request->pool, str_c(str));
 
        str_truncate(str, 0);
-       auth_request_var_expand(str, conn->set.pass_filter,
-                               auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.pass_filter,
+                                   auth_request, ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand pass_filter=%s: %s",
+                       conn->set.pass_filter, error);
+               passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
+               return;
+       }
        srequest->filter = p_strdup(auth_request->pool, str_c(str));
 
        /* we don't need the attributes to perform authentication, but they
@@ -359,11 +393,19 @@ ldap_verify_plain_auth_bind_userdn(struct auth_request *auth_request,
        struct ldap_connection *conn = module->conn;
        struct ldap_request_bind *brequest = &request->request.bind;
        string_t *dn;
+       const char *error;
 
        brequest->request.type = LDAP_REQUEST_TYPE_BIND;
 
        dn = t_str_new(512);
-       auth_request_var_expand(dn, conn->set.auth_bind_userdn, auth_request, ldap_escape);
+       if (auth_request_var_expand(dn, conn->set.auth_bind_userdn,
+                                   auth_request, ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand auth_bind_userdn=%s: %s",
+                       conn->set.auth_bind_userdn, error);
+               passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
+               return;
+       }
 
        brequest->dn = p_strdup(auth_request->pool, str_c(dn));
         ldap_auth_bind(conn, brequest);
index 9824431b290736d26a3190371ecc49505f2c1b55..ffddf39286c5d4a197fe8d494704e0462a41d669 100644 (file)
@@ -312,14 +312,21 @@ pam_verify_plain(struct auth_request *request, const char *password,
         struct passdb_module *_module = request->passdb->passdb;
         struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
        enum passdb_result result;
-       const char *service;
+       const char *service, *error;
 
        if (module->requests_left > 0) {
                if (--module->requests_left == 0)
                        worker_restart_request = TRUE;
        }
 
-       service = t_auth_request_var_expand(module->service_name, request, NULL);
+       if (t_auth_request_var_expand(module->service_name, request, NULL,
+                                     &service, &error) <= 0) {
+               auth_request_log_debug(request, AUTH_SUBSYS_DB,
+                       "Failed to expand service %s: %s",
+                       module->service_name, error);
+               callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
+               return;
+       }
 
        auth_request_log_debug(request, AUTH_SUBSYS_DB,
                               "lookup service=%s", service);
index 8978fd2baa71d1130b8f4d31a40231178b1f4be9..d4a3aac0ed8c3a76d1a29c2bbbc6cc4b356e5524 100644 (file)
@@ -17,12 +17,12 @@ struct passwd_file_passdb_module {
        const char *username_format;
 };
 
-static void
+static int
 passwd_file_add_extra_fields(struct auth_request *request, char *const *fields)
 {
        string_t *str = t_str_new(512);
         const struct var_expand_table *table;
-       const char *key, *value;
+       const char *key, *value, *error;
        unsigned int i;
 
        table = auth_request_get_var_expand_table(request, NULL);
@@ -32,8 +32,13 @@ passwd_file_add_extra_fields(struct auth_request *request, char *const *fields)
                if (value != NULL) {
                        key = t_strdup_until(fields[i], value);
                        str_truncate(str, 0);
-                       auth_request_var_expand_with_table(str, value + 1,
-                                                          request, table, NULL);
+                       if (auth_request_var_expand_with_table(str, value + 1,
+                                       request, table, NULL, &error) <= 0) {
+                               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                                       "Failed to expand extra field %s: %s",
+                                       fields[i], error);
+                               return -1;
+                       }
                        value = str_c(str);
                } else {
                        key = fields[i];
@@ -41,12 +46,13 @@ passwd_file_add_extra_fields(struct auth_request *request, char *const *fields)
                }
                auth_request_set_field(request, key, value, NULL);
        }
+       return 0;
 }
 
-static void passwd_file_save_results(struct auth_request *request,
-                                    const struct passwd_user *pu,
-                                    const char **crypted_pass_r,
-                                    const char **scheme_r)
+static int passwd_file_save_results(struct auth_request *request,
+                                   const struct passwd_user *pu,
+                                   const char **crypted_pass_r,
+                                   const char **scheme_r)
 {
        *crypted_pass_r = pu->password != NULL ? pu->password : "";
        *scheme_r = password_get_scheme(crypted_pass_r);
@@ -57,8 +63,11 @@ static void passwd_file_save_results(struct auth_request *request,
        auth_request_set_field(request, "password",
                               *crypted_pass_r, *scheme_r);
 
-       if (pu->extra_fields != NULL)
-               passwd_file_add_extra_fields(request, pu->extra_fields);
+       if (pu->extra_fields != NULL) {
+               if (passwd_file_add_extra_fields(request, pu->extra_fields) < 0)
+                       return -1;
+       }
+       return 0;
 }
 
 static void
@@ -80,7 +89,10 @@ passwd_file_verify_plain(struct auth_request *request, const char *password,
                return;
        }
 
-       passwd_file_save_results(request, pu, &crypted_pass, &scheme);
+       if (passwd_file_save_results(request, pu, &crypted_pass, &scheme) < 0) {
+               callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
+               return;
+       }
 
        ret = auth_request_password_verify(request, password, crypted_pass,
                                           scheme, AUTH_SUBSYS_DB);
@@ -108,7 +120,10 @@ passwd_file_lookup_credentials(struct auth_request *request,
                return;
        }
 
-       passwd_file_save_results(request, pu, &crypted_pass, &scheme);
+       if (passwd_file_save_results(request, pu, &crypted_pass, &scheme) < 0) {
+               callback(PASSDB_RESULT_INTERNAL_FAILURE, NULL, 0, request);
+               return;
+       }
 
        passdb_handle_credentials(PASSDB_RESULT_OK, crypted_pass, scheme,
                                  callback, request);
index 1ad1cae7f465472bef3273e72009ee2ea33c161e..6440e43861777d03cf5ce751ef5588879f9d5ef7 100644 (file)
@@ -154,11 +154,18 @@ static void sql_lookup_pass(struct passdb_sql_request *sql_request)
        struct passdb_module *_module =
                sql_request->auth_request->passdb->passdb;
        struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
-       const char *query;
-
-       query = t_auth_request_var_expand(module->conn->set.password_query,
-                                         sql_request->auth_request,
-                                         passdb_sql_escape);
+       const char *query, *error;
+
+       if (t_auth_request_var_expand(module->conn->set.password_query,
+                                     sql_request->auth_request,
+                                     passdb_sql_escape, &query, &error) <= 0) {
+               auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand password_query=%s: %s",
+                       module->conn->set.password_query, error);
+               sql_request->callback.verify_plain(PASSDB_RESULT_INTERNAL_FAILURE,
+                                                  sql_request->auth_request);
+               return;
+       }
 
        auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
                               "query: %s", query);
@@ -227,12 +234,19 @@ static void sql_set_credentials(struct auth_request *request,
                (struct sql_passdb_module *) request->passdb->passdb;
        struct sql_transaction_context *transaction;
        struct passdb_sql_request *sql_request;
-       const char *query;
+       const char *query, *error;
 
        request->mech_password = p_strdup(request->pool, new_credentials);
 
-       query = t_auth_request_var_expand(module->conn->set.update_query,
-                                         request, passdb_sql_escape);
+       if (t_auth_request_var_expand(module->conn->set.update_query,
+                                     request, passdb_sql_escape,
+                                     &query, &error) <= 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand update_query=%s: %s",
+                       module->conn->set.update_query, error);
+               callback(FALSE, request);
+               return;
+       }
 
        sql_request = i_new(struct passdb_sql_request, 1);
        sql_request->auth_request = request;
index 631b967c894fe96166bdb65a4803b62c83a2a093..0b6fee4b3f5ce8accf34a6843db1c48d3664bc98 100644 (file)
@@ -12,17 +12,28 @@ struct static_passdb_module {
 };
 
 static enum passdb_result
-static_save_fields(struct auth_request *request, const char **password_r, const char **scheme_r)
+static_save_fields(struct auth_request *request, const char **password_r,
+                  const char **scheme_r)
 {
        struct static_passdb_module *module =
                (struct static_passdb_module *)request->passdb->passdb;
+       const char *error;
 
        auth_request_log_debug(request, AUTH_SUBSYS_DB, "lookup");
-       passdb_template_export(module->tmpl, request);
+       if (passdb_template_export(module->tmpl, request, &error) < 0) {
+               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                       "Failed to expand template: %s", error);
+               return PASSDB_RESULT_INTERNAL_FAILURE;
+       }
 
        if (module->static_password_tmpl != NULL) {
-               *password_r = t_auth_request_var_expand(
-                       module->static_password_tmpl, request, NULL);
+               if (t_auth_request_var_expand(module->static_password_tmpl,
+                               request, NULL, password_r, &error) <= 0) {
+                       auth_request_log_error(request, AUTH_SUBSYS_DB,
+                               "Failed to expand password=%s: %s",
+                               module->static_password_tmpl, error);
+                       return PASSDB_RESULT_INTERNAL_FAILURE;
+               }
        } else if (auth_fields_exists(request->extra_fields, "nopassword")) {
                *password_r = "";
        } else {
index 6153af4111a34b7a71d8c2ad28359041f178cdd8..143d3ab15871894995583360d14e152f5a2485be 100644 (file)
@@ -35,8 +35,9 @@ struct passdb_template *passdb_template_build(pool_t pool, const char *args)
        return tmpl;
 }
 
-void passdb_template_export(struct passdb_template *tmpl,
-                           struct auth_request *auth_request)
+int passdb_template_export(struct passdb_template *tmpl,
+                          struct auth_request *auth_request,
+                          const char **error_r)
 {
         const struct var_expand_table *table;
        string_t *str;
@@ -44,7 +45,7 @@ void passdb_template_export(struct passdb_template *tmpl,
        unsigned int i, count;
 
        if (passdb_template_is_empty(tmpl))
-               return;
+               return 0;
 
        str = t_str_new(256);
        table = auth_request_get_var_expand_table(auth_request, NULL);
@@ -56,13 +57,15 @@ void passdb_template_export(struct passdb_template *tmpl,
                        value = "";
                else {
                        str_truncate(str, 0);
-                       auth_request_var_expand_with_table(str, args[i+1],
-                               auth_request, table, NULL);
+                       if (auth_request_var_expand_with_table(str, args[i+1],
+                                       auth_request, table, NULL, error_r) <= 0)
+                               return -1;
                        value = str_c(str);
                }
                auth_request_set_field(auth_request, args[i], value,
                                       STATIC_PASS_SCHEME);
        }
+       return 0;
 }
 
 bool passdb_template_remove(struct passdb_template *tmpl,
index b4a1f00357cd96d0f9ec0e9d2f62938130196bea..df03e33c002eefdec3073f6d556c610fa22c59bd 100644 (file)
@@ -4,8 +4,9 @@
 #define STATIC_PASS_SCHEME "PLAIN"
 
 struct passdb_template *passdb_template_build(pool_t pool, const char *args);
-void passdb_template_export(struct passdb_template *tmpl,
-                           struct auth_request *auth_request);
+int passdb_template_export(struct passdb_template *tmpl,
+                          struct auth_request *auth_request,
+                          const char **error_r);
 bool passdb_template_remove(struct passdb_template *tmpl,
                            const char *key, const char **value_r);
 bool passdb_template_is_empty(struct passdb_template *tmpl);
index 14f4740194f8de19d68cbfc21d26382205eda09b..134dad4850bf1bfc7e8e3cb94e4c05a9f42ea991 100644 (file)
@@ -18,14 +18,15 @@ const struct var_expand_table auth_request_var_expand_static_tab[] = {
        { '\0', NULL, NULL }
 };
 
-const char *
-t_auth_request_var_expand(const char *str,
-                         const struct auth_request *auth_request ATTR_UNUSED,
-                         auth_request_escape_func_t *escape_func ATTR_UNUSED)
+int t_auth_request_var_expand(const char *str,
+                             const struct auth_request *auth_request ATTR_UNUSED,
+                             auth_request_escape_func_t *escape_func ATTR_UNUSED,
+                             const char **value_r, const char **error_r)
 {
        string_t *dest = t_str_new(128);
-       var_expand(dest, str, auth_request_var_expand_static_tab);
-       return str_c(dest);
+       int ret = var_expand(dest, str, auth_request_var_expand_static_tab, error_r);
+       *value_r = str_c(dest);
+       return ret;
 }
 
 static void test_auth_cache_parse_key(void)
index 801bf04274e84970d99b3800e57633abd6be48e2..bf4e3a767d8596a816916221db814b4cd7300376 100644 (file)
@@ -71,9 +71,12 @@ test_escape(const char *string, const struct auth_request *request)
 
 static bool test_empty_request(string_t *str, const char *input)
 {
+       const struct var_expand_table *tab =
+               auth_request_get_var_expand_table(&empty_test_request, NULL);
+       const char *error;
+
        str_truncate(str, 0);
-       var_expand(str, input,
-                  auth_request_get_var_expand_table(&empty_test_request, NULL));
+       test_assert(var_expand(str, input, tab, &error) == 1);
        return strspn(str_c(str), "\n0") == str_len(str);
 }
 
@@ -90,17 +93,18 @@ static void test_auth_request_var_expand_shortlong(void)
                "+user@+domain1@+domain2\n+user\n+domain1@+domain2\n+service\n\n"
                "7.91.205.21\n73.150.2.210\n54321\n+password\n+mech\nsecured\n"
                "21\n210\nvalid\n";
+       const struct var_expand_table *tab;
        string_t *str = t_str_new(256);
+       const char *error;
 
        test_begin("auth request var expand short and long");
 
-       var_expand(str, test_input_short,
-                  auth_request_get_var_expand_table(&test_request, test_escape));
+       tab = auth_request_get_var_expand_table(&test_request, test_escape);
+       test_assert(var_expand(str, test_input_short, tab, &error) == 1);
        test_assert(strcmp(str_c(str), test_output) == 0);
 
        str_truncate(str, 0);
-       var_expand(str, test_input_long,
-                  auth_request_get_var_expand_table(&test_request, test_escape));
+       test_assert(var_expand(str, test_input_long, tab, &error) == 1);
        test_assert(strcmp(str_c(str), test_output) == 0);
 
        /* test with empty input that it won't crash */
@@ -114,14 +118,16 @@ static void test_auth_request_var_expand_flags(void)
 {
        static const char *test_input = "%!\n%{secured}\n%{cert}\n";
        string_t *str = t_str_new(10);
+       const char *error;
 
        test_begin("auth request var expand flags");
 
        test_request.userdb_lookup = FALSE;
        test_request.secured = FALSE;
        test_request.valid_client_cert = FALSE;
-       var_expand(str, test_input,
-                  auth_request_get_var_expand_table(&test_request, test_escape));
+       test_assert(var_expand(str, test_input,
+               auth_request_get_var_expand_table(&test_request, test_escape),
+               &error) == 1);
        test_assert(strcmp(str_c(str), "40\n\n\n") == 0);
 
        test_request.userdb_lookup = TRUE;
@@ -129,8 +135,9 @@ static void test_auth_request_var_expand_flags(void)
        test_request.valid_client_cert = TRUE;
 
        str_truncate(str, 0);
-       var_expand(str, test_input,
-                  auth_request_get_var_expand_table(&test_request, test_escape));
+       test_assert(var_expand(str, test_input,
+               auth_request_get_var_expand_table(&test_request, test_escape),
+               &error) == 1);
        test_assert(strcmp(str_c(str), "41\nsecured\nvalid\n") == 0);
 
        test_assert(test_empty_request(str, test_input));
@@ -150,11 +157,13 @@ static void test_auth_request_var_expand_long(void)
                "+masteruser@+masterdomain1@+masterdomain2\n5000\n"
                "+origuser@+origdomain1@+origdomain2\n+origuser\n+origdomain1@+origdomain2\n";
        string_t *str = t_str_new(256);
+       const char *error;
 
        test_begin("auth request var expand long-only");
 
-       var_expand(str, test_input,
-                  auth_request_get_var_expand_table(&test_request, test_escape));
+       test_assert(var_expand(str, test_input,
+               auth_request_get_var_expand_table(&test_request, test_escape),
+               &error) == 1);
        test_assert(strcmp(str_c(str), test_output) == 0);
 
        test_assert(test_empty_request(str, test_input));
@@ -173,14 +182,16 @@ static void test_auth_request_var_expand_usernames(void)
        static const char *test_input =
                "%{username}\n%{domain}\n%{domain_first}\n%{domain_last}\n%{user}";
        string_t *str = t_str_new(64);
+       const char *error;
        unsigned int i;
 
        test_begin("auth request var expand usernames");
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                test_request.user = t_strdup_noconst(tests[i].username);
                str_truncate(str, 0);
-               var_expand(str, test_input,
-                          auth_request_get_var_expand_table(&test_request, test_escape));
+               test_assert(var_expand(str, test_input,
+                       auth_request_get_var_expand_table(&test_request, test_escape),
+                       &error) == 1);
                test_assert_idx(strcmp(str_c(str), tests[i].output) == 0, i);
        }
        test_request.user = default_test_request.user;
@@ -190,7 +201,7 @@ static void test_auth_request_var_expand_usernames(void)
 static void test_auth_request_var_expand_funcs(void)
 {
        pool_t pool;
-       const char *value;
+       const char *value, *error;
 
        test_begin("auth request var expand funcs");
 
@@ -204,20 +215,20 @@ static void test_auth_request_var_expand_funcs(void)
        auth_fields_add(test_request.userdb_reply, "ukey1", "-uval1", 0);
        auth_fields_add(test_request.userdb_reply, "ukey2", "", 0);
 
-       value = t_auth_request_var_expand(
+       test_assert(t_auth_request_var_expand(
                        "%{passdb:pkey1}\n%{passdb:pkey1:default1}\n"
                        "%{passdb:pkey2}\n%{passdb:pkey2:default2}\n"
                        "%{passdb:pkey3}\n%{passdb:pkey3:default3}\n"
                        "%{passdb:ukey1}\n%{passdb:ukey1:default4}\n",
-                       &test_request, test_escape);
+                       &test_request, test_escape, &value, &error) == 0);
        test_assert(strcmp(value, "+pval1\n+pval1\n\n\n\ndefault3\n\ndefault4\n") == 0);
 
-       value = t_auth_request_var_expand(
+       test_assert(t_auth_request_var_expand(
                        "%{userdb:ukey1}\n%{userdb:ukey1:default1}\n"
                        "%{userdb:ukey2}\n%{userdb:ukey2:default2}\n"
                        "%{userdb:ukey3}\n%{userdb:ukey3:default3}\n"
                        "%{userdb:pkey1}\n%{userdb:pkey1:default4}\n",
-                       &test_request, test_escape);
+                       &test_request, test_escape, &value, &error) == 0);
        test_assert(strcmp(value, "+uval1\n+uval1\n\n\n\ndefault3\n\ndefault4\n") == 0);
 
        pool_unref(&pool);
index 90ddb400a4764854e82603afadadb1a48183a613..f594b57a9982f90c3d911e2867f49e28c8bf2089 100644 (file)
@@ -88,6 +88,7 @@ userdb_dict_iterate_init(struct auth_request *auth_request,
                (struct dict_userdb_module *)_module;
        struct dict_userdb_iterate_context *ctx;
        string_t *path;
+       const char *error;
 
        ctx = i_new(struct dict_userdb_iterate_context, 1);
        ctx->ctx.auth_request = auth_request;
@@ -106,8 +107,14 @@ userdb_dict_iterate_init(struct auth_request *auth_request,
 
        path = t_str_new(128);
        str_append(path, DICT_PATH_SHARED);
-       auth_request_var_expand(path, module->conn->set.iterate_prefix,
-                               auth_request, NULL);
+       if (auth_request_var_expand(path, module->conn->set.iterate_prefix,
+                                   auth_request, NULL, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand iterate_prefix=%s: %s",
+                       module->conn->set.iterate_prefix, error);
+               ctx->ctx.failed = TRUE;
+               return &ctx->ctx;
+       }
        ctx->key_prefix = p_strdup(auth_request->pool, str_c(path));
        ctx->key_prefix_len = strlen(ctx->key_prefix);
 
index 670f3e6571be87ad90438675e4ae6ca3e8106a0c..ad73187fe36fd28bab13c4f20540a2395382d6cc 100644 (file)
@@ -110,6 +110,7 @@ static void userdb_ldap_lookup(struct auth_request *auth_request,
        struct ldap_connection *conn = module->conn;
        const char **attr_names = (const char **)conn->user_attr_names;
        struct userdb_ldap_request *request;
+       const char *error;
        string_t *str;
 
        auth_request_ref(auth_request);
@@ -117,11 +118,24 @@ static void userdb_ldap_lookup(struct auth_request *auth_request,
        request->userdb_callback = callback;
 
        str = t_str_new(512);
-       auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.base, auth_request,
+                                   ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand base=%s: %s", conn->set.base, error);
+               callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+               return;
+       }
        request->request.base = p_strdup(auth_request->pool, str_c(str));
 
        str_truncate(str, 0);
-       auth_request_var_expand(str, conn->set.user_filter, auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.user_filter, auth_request,
+                                   ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand user_filter=%s: %s",
+                       conn->set.user_filter, error);
+               callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+               return;
+       }
        request->request.filter = p_strdup(auth_request->pool, str_c(str));
 
        request->request.attr_map = &conn->user_attr_map;
@@ -191,6 +205,7 @@ userdb_ldap_iterate_init(struct auth_request *auth_request,
        struct ldap_userdb_iterate_context *ctx;
        struct userdb_iter_ldap_request *request;
        const char **attr_names = (const char **)conn->iterate_attr_names;
+       const char *error;
        string_t *str;
 
        ctx = i_new(struct ldap_userdb_iterate_context, 1);
@@ -205,12 +220,22 @@ userdb_ldap_iterate_init(struct auth_request *auth_request,
        request->request.request.auth_request = auth_request;
 
        str = t_str_new(512);
-       auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.base, auth_request,
+                                   ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand base=%s: %s", conn->set.base, error);
+               ctx->ctx.failed = TRUE;
+       }
        request->request.base = p_strdup(auth_request->pool, str_c(str));
 
        str_truncate(str, 0);
-       auth_request_var_expand(str, conn->set.iterate_filter,
-                               auth_request, ldap_escape);
+       if (auth_request_var_expand(str, conn->set.iterate_filter,
+                                   auth_request, ldap_escape, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand iterate_filter=%s: %s",
+                       conn->set.iterate_filter, error);
+               ctx->ctx.failed = TRUE;
+       }
        request->request.filter = p_strdup(auth_request->pool, str_c(str));
        request->request.attr_map = &conn->iterate_attr_map;
        request->request.attributes = conn->iterate_attr_names;
index f2e536c884e5fc119f18667f4d7bf434c01de633..4da76858d6416eca345acddfa6ad556b006e37f8 100644 (file)
@@ -27,12 +27,12 @@ struct passwd_file_userdb_module {
        const char *username_format;
 };
 
-static void
+static int
 passwd_file_add_extra_fields(struct auth_request *request, char *const *fields)
 {
        string_t *str = t_str_new(512);
         const struct var_expand_table *table;
-       const char *key, *value;
+       const char *key, *value, *error;
        unsigned int i;
 
        table = auth_request_get_var_expand_table(request, NULL);
@@ -46,14 +46,20 @@ passwd_file_add_extra_fields(struct auth_request *request, char *const *fields)
                if (value != NULL) {
                        key = t_strdup_until(key, value);
                        str_truncate(str, 0);
-                       auth_request_var_expand_with_table(str, value + 1,
-                                                          request, table, NULL);
+                       if (auth_request_var_expand_with_table(str, value + 1,
+                                       request, table, NULL, &error) <= 0) {
+                               auth_request_log_error(request, AUTH_SUBSYS_DB,
+                                       "Failed to expand extra field %s: %s",
+                                       fields[i], error);
+                               return -1;
+                       }
                        value = str_c(str);
                } else {
                        value = "";
                }
                auth_request_set_userdb_field(request, key, value);
        }
+       return 0;
 }
 
 static void passwd_file_lookup(struct auth_request *auth_request,
@@ -68,7 +74,8 @@ static void passwd_file_lookup(struct auth_request *auth_request,
        ret = db_passwd_file_lookup(module->pwf, auth_request,
                                    module->username_format, &pu);
        if (ret <= 0 || pu->uid == 0) {
-               callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
+               callback(ret < 0 ? USERDB_RESULT_INTERNAL_FAILURE :
+                        USERDB_RESULT_USER_UNKNOWN, auth_request);
                return;
        }
 
@@ -84,8 +91,11 @@ static void passwd_file_lookup(struct auth_request *auth_request,
        if (pu->home != NULL)
                auth_request_set_userdb_field(auth_request, "home", pu->home);
 
-       if (pu->extra_fields != NULL)
-               passwd_file_add_extra_fields(auth_request, pu->extra_fields);
+       if (pu->extra_fields != NULL &&
+           passwd_file_add_extra_fields(auth_request, pu->extra_fields) < 0) {
+               callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+               return;
+       }
 
        callback(USERDB_RESULT_OK, auth_request);
 }
index a1f187140c91c7818c9156a2a44d8689520353ed..68154ac0655c55e412d935388d3e3e8072861610 100644 (file)
@@ -84,6 +84,7 @@ static void passwd_lookup(struct auth_request *auth_request,
                (struct passwd_userdb_module *)_module;
        struct passwd pw;
        struct timeval start_tv;
+       const char *error;
        int ret;
 
        auth_request_log_debug(auth_request, AUTH_SUBSYS_DB, "lookup");
@@ -114,7 +115,11 @@ static void passwd_lookup(struct auth_request *auth_request,
        auth_request_set_userdb_field(auth_request, "gid", dec2str(pw.pw_gid));
        auth_request_set_userdb_field(auth_request, "home", pw.pw_dir);
 
-       userdb_template_export(module->tmpl, auth_request);
+       if (userdb_template_export(module->tmpl, auth_request, &error) < 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                                      "Failed to expand template: %s", error);
+               callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+       }
 
        callback(USERDB_RESULT_OK, auth_request);
 }
index 7bdd6b111ccfee27fa79321bd219028918208f0f..a45c321523127e6da83b88b747a4bcda9d134b59 100644 (file)
@@ -105,10 +105,17 @@ static void userdb_sql_lookup(struct auth_request *auth_request,
        struct sql_userdb_module *module =
                (struct sql_userdb_module *)_module;
        struct userdb_sql_request *sql_request;
-       const char *query;
-
-       query = t_auth_request_var_expand(module->conn->set.user_query,
-                       auth_request, userdb_sql_escape);
+       const char *query, *error;
+
+       if (t_auth_request_var_expand(module->conn->set.user_query,
+                                     auth_request, userdb_sql_escape,
+                                     &query, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand user_query=%s: %s",
+                       module->conn->set.user_query, error);
+               callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+               return;
+       }
 
        auth_request_ref(auth_request);
        sql_request = i_new(struct userdb_sql_request, 1);
@@ -141,10 +148,15 @@ userdb_sql_iterate_init(struct auth_request *auth_request,
        struct sql_userdb_module *module =
                (struct sql_userdb_module *)_module;
        struct sql_userdb_iterate_context *ctx;
-       const char *query;
-
-       query = t_auth_request_var_expand(module->conn->set.iterate_query,
-                  auth_request, userdb_sql_escape);
+       const char *query, *error;
+
+       if (t_auth_request_var_expand(module->conn->set.iterate_query,
+                                     auth_request, userdb_sql_escape,
+                                     &query, &error) <= 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                       "Failed to expand iterate_query=%s: %s",
+                       module->conn->set.iterate_query, error);
+       }
 
        ctx = i_new(struct sql_userdb_iterate_context, 1);
        ctx->ctx.auth_request = auth_request;
index 5578512300454ffe2bad5e30abf806573a5f2509..964484dbfc1081bfd47d1e5bfd7672f9ba0d4174 100644 (file)
@@ -27,8 +27,13 @@ static void static_lookup_real(struct auth_request *auth_request,
        struct userdb_module *_module = auth_request->userdb->userdb;
        struct static_userdb_module *module =
                (struct static_userdb_module *)_module;
+       const char *error;
 
-       userdb_template_export(module->tmpl, auth_request);
+       if (userdb_template_export(module->tmpl, auth_request, &error) < 0) {
+               auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
+                                      "Failed to expand template: %s", error);
+               callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+       }
        callback(USERDB_RESULT_OK, auth_request);
 }
 
index 840f303b0322acd7796b5d0e27fab20727483fc4..f854b4b537e3475b49cf1fbb1bf2e670cc3e2aaa 100644 (file)
@@ -58,8 +58,9 @@ userdb_template_build(pool_t pool, const char *userdb_name, const char *args)
        return tmpl;
 }
 
-void userdb_template_export(struct userdb_template *tmpl,
-                           struct auth_request *auth_request)
+int userdb_template_export(struct userdb_template *tmpl,
+                          struct auth_request *auth_request,
+                          const char **error_r)
 {
         const struct var_expand_table *table;
        string_t *str;
@@ -67,7 +68,7 @@ void userdb_template_export(struct userdb_template *tmpl,
        unsigned int i, count;
 
        if (userdb_template_is_empty(tmpl))
-               return;
+               return 0;
 
        str = t_str_new(256);
        table = auth_request_get_var_expand_table(auth_request, NULL);
@@ -79,12 +80,14 @@ void userdb_template_export(struct userdb_template *tmpl,
                        value = "";
                else {
                        str_truncate(str, 0);
-                       auth_request_var_expand_with_table(str, args[i+1],
-                               auth_request, table, NULL);
+                       if (auth_request_var_expand_with_table(str, args[i+1],
+                                       auth_request, table, NULL, error_r) <= 0)
+                               return -1;
                        value = str_c(str);
                }
                auth_request_set_userdb_field(auth_request, args[i], value);
        }
+       return 0;
 }
 
 bool userdb_template_remove(struct userdb_template *tmpl,
index 3af7452ef3cf1efb69b16ae2dd3cc81e073c04c1..bf1ce8181d4ab0f0f0136bd19bd79969c30da59b 100644 (file)
@@ -3,8 +3,9 @@
 
 struct userdb_template *
 userdb_template_build(pool_t pool, const char *userdb_name, const char *args);
-void userdb_template_export(struct userdb_template *tmpl,
-                           struct auth_request *auth_request);
+int userdb_template_export(struct userdb_template *tmpl,
+                          struct auth_request *auth_request,
+                          const char **error_r);
 bool userdb_template_remove(struct userdb_template *tmpl,
                            const char *key, const char **value_r);
 bool userdb_template_is_empty(struct userdb_template *tmpl);
index c7c6d952c5478761d5ada8d9646355e9f5937d41..01aba8abf51bf77250258dd8538639dee7cf9281 100644 (file)
@@ -125,8 +125,13 @@ void director_request(struct director *dir, const char *username,
                      director_request_callback *callback, void *context)
 {
        struct director_request *request;
-       unsigned int username_hash =
-               user_directory_get_username_hash(dir->users, username);
+       unsigned int username_hash;
+
+       if (!user_directory_get_username_hash(dir->users, username,
+                                             &username_hash)) {
+               callback(NULL, NULL, "Failed to expand director_username_hash", context);
+               return;
+       }
 
        dir->num_requests++;
 
index 3f7deb70ed9c1af0135be487dd57bb2c51671041..57ceb037a6d6d0a45d6750d234b7e456ef287d51 100644 (file)
@@ -762,6 +762,7 @@ director_flush_user(struct director *dir, struct user *user)
                { 'h', user->host->hostname, "host" },
                { '\0', NULL, NULL }
        };
+       const char *error;
 
        /* Execute flush script, if set. Only the director that started the
           user moving will call the flush script. Having each director do it
@@ -782,10 +783,14 @@ director_flush_user(struct director *dir, struct user *user)
        ctx->host_ip = user->host->ip;
 
        string_t *s_sock = str_new(default_pool, 32);
-       var_expand(s_sock, dir->set->director_flush_socket, tab);
+       if (var_expand(s_sock, dir->set->director_flush_socket, tab, &error) <= 0) {
+               i_error("Failed to expand director_flush_socket=%s: %s",
+                       dir->set->director_flush_socket, error);
+               director_user_kill_finish_delayed(dir, user, FALSE);
+               return;
+       }
        ctx->socket_path = str_free_without_data(&s_sock);
 
-       const char *error;
        struct program_client_settings set = {
                .client_connect_timeout_msecs = 10000,
                .dns_client_socket_path = DIRECTOR_DNS_SOCKET_PATH,
index cadca4054f30a618fb6f6fdd7bc6ce40e74dedbe..e2125820d1c83e5314145ff683b91c41e578e18d 100644 (file)
@@ -564,8 +564,13 @@ doveadm_cmd_user_lookup(struct doveadm_connection *conn,
                username = args[0];
                tag = args[1] != NULL ? args[1] : "";
        }
-       if (str_to_uint(username, &username_hash) < 0)
-               username_hash = user_directory_get_username_hash(conn->dir->users, username);
+       if (str_to_uint(username, &username_hash) < 0) {
+               if (!user_directory_get_username_hash(conn->dir->users,
+                                                     args[0], &username_hash)) {
+                       o_stream_nsend_str(conn->output, "TRYAGAIN\n");
+                       return 1;
+               }
+       }
 
        /* get user's current host */
        user = user_directory_lookup(conn->dir->users, username_hash);
@@ -648,8 +653,13 @@ doveadm_cmd_user_move(struct doveadm_connection *conn, const char *const *args)
                return 1;
        }
 
-       if (str_to_uint(args[0], &username_hash) < 0)
-               username_hash = user_directory_get_username_hash(conn->dir->users, args[0]);
+       if (str_to_uint(args[0], &username_hash) < 0) {
+               if (!user_directory_get_username_hash(conn->dir->users,
+                                                     args[0], &username_hash)) {
+                       o_stream_nsend_str(conn->output, "TRYAGAIN\n");
+                       return 1;
+               }
+       }
        user = user_directory_lookup(conn->dir->users, username_hash);
        if (user != NULL && USER_IS_BEING_KILLED(user)) {
                o_stream_nsend_str(conn->output, "TRYAGAIN\n");
index b2cb8efae6bd443c2bf398d3830722dbfc936fd3..76ecfd3aa5a2f355214774b61b63310b66d4b1e5 100644 (file)
@@ -25,7 +25,9 @@ static void notify_connection_input(struct notify_connection *conn)
        int diff;
 
        while ((line = i_stream_read_next_line(conn->input)) != NULL) {
-               hash = user_directory_get_username_hash(conn->dir->users, line);
+               if (!user_directory_get_username_hash(conn->dir->users, line, &hash))
+                       continue;
+
                user = user_directory_lookup(conn->dir->users, hash);
                if (user != NULL) {
                        diff = ioloop_time - user->timestamp;
index a392da369fcde6b7d7a1c257a8e61217b4694a8c..9b97a00a93885f483b1f7d3547eee4da4cfe155f 100644 (file)
 
 #define USER_DIR_TIMEOUT 1000000
 
-unsigned int mail_user_hash(const char *username ATTR_UNUSED,
-                           const char *format ATTR_UNUSED) { return 0; }
+bool mail_user_hash(const char *username ATTR_UNUSED,
+                   const char *format ATTR_UNUSED,
+                   unsigned int *hash_r, const char **error_r ATTR_UNUSED)
+{
+       *hash_r = 0;
+       return TRUE;
+}
 
 static void
 verify_user_directory(struct user_directory *dir, unsigned int user_count)
index 1e57e5784cc4ec87522b00895c57d38b2cc3c706..aa1c365855698d2c40f6cec3c7a556a773642b4f 100644 (file)
@@ -256,10 +256,17 @@ void user_directory_sort(struct user_directory *dir)
        array_free(&users);
 }
 
-unsigned int user_directory_get_username_hash(struct user_directory *dir,
-                                             const char *username)
+bool user_directory_get_username_hash(struct user_directory *dir,
+                                     const char *username,
+                                     unsigned int *hash_r)
 {
-       return mail_user_hash(username, dir->username_hash_fmt);
+       const char *error;
+
+       if (mail_user_hash(username, dir->username_hash_fmt, hash_r, &error))
+               return TRUE;
+       i_error("Failed to expand director_user_expire=%s: %s",
+               dir->username_hash_fmt, error);
+       return FALSE;
 }
 
 bool user_directory_user_is_recently_updated(struct user_directory *dir,
index 24538fa27fd896e871d99467a877890a4fdb83e9..0be4a8c829eb03d7257184ada67b2ed4271f635b 100644 (file)
@@ -52,8 +52,9 @@ void user_directory_remove_host(struct user_directory *dir,
    timestamps based on remote director's user list after handshake. */
 void user_directory_sort(struct user_directory *dir);
 
-unsigned int user_directory_get_username_hash(struct user_directory *dir,
-                                             const char *username);
+bool user_directory_get_username_hash(struct user_directory *dir,
+                                     const char *username,
+                                     unsigned int *hash_r);
 
 bool user_directory_user_is_recently_updated(struct user_directory *dir,
                                             struct user *user);
index 2b550da066985a8b658b0a4af82b2f6970d586c8..e9a52581627ecb7f6cacbe3366417ffcc41e9762 100644 (file)
@@ -327,18 +327,26 @@ cmd_user_mail_input(struct mail_storage_service_ctx *storage_service,
                cmd_user_mail_print_fields(input, user, userdb_fields, show_field);
        else {
                string_t *str = t_str_new(128);
-               var_expand_with_funcs(str, expand_field,
-                                     mail_user_var_expand_table(user),
-                                     mail_user_var_expand_func_table, user);
-               string_t *value = t_str_new(128);
-               json_append_escaped(value, expand_field);
-               o_stream_nsend_str(doveadm_print_ostream, "\"");
-               o_stream_nsend_str(doveadm_print_ostream, str_c(value));
-               o_stream_nsend_str(doveadm_print_ostream, "\":\"");
-               str_truncate(value, 0);
-               json_append_escaped(value, str_c(str));
-               o_stream_nsend_str(doveadm_print_ostream, str_c(value));
-               o_stream_nsend_str(doveadm_print_ostream, "\"");
+               if (var_expand_with_funcs(str, expand_field,
+                                         mail_user_var_expand_table(user),
+                                         mail_user_var_expand_func_table, user,
+                                         &error) <= 0) {
+                       string_t *str = t_str_new(128);
+                       str_printfa(str, "\"error\":\"Failed to expand field: ");
+                       json_append_escaped(str, error);
+                       str_append_c(str, '"');
+                       o_stream_nsend(doveadm_print_ostream, str_data(str), str_len(str));
+               } else {
+                       string_t *value = t_str_new(128);
+                       json_append_escaped(value, expand_field);
+                       o_stream_nsend_str(doveadm_print_ostream, "\"");
+                       o_stream_nsend_str(doveadm_print_ostream, str_c(value));
+                       o_stream_nsend_str(doveadm_print_ostream, "\":\"");
+                       str_truncate(value, 0);
+                       json_append_escaped(value, str_c(str));
+                       o_stream_nsend_str(doveadm_print_ostream, str_c(value));
+                       o_stream_nsend_str(doveadm_print_ostream, "\"");
+               }
 
        }
 
index 064a986085919b2363f66dab3dabd4f20992e0d3..73812f4eaf973aa1618247f61be082b36e36326d 100644 (file)
@@ -579,10 +579,14 @@ cmd_user_mail_input(struct mail_storage_service_ctx *storage_service,
                cmd_user_mail_print_fields(input, user, userdb_fields, show_field);
        else {
                string_t *str = t_str_new(128);
-               var_expand_with_funcs(str, expand_field,
-                                     mail_user_var_expand_table(user),
-                                     mail_user_var_expand_func_table, user);
-               printf("%s\n", str_c(str));
+               if (var_expand_with_funcs(str, expand_field,
+                                         mail_user_var_expand_table(user),
+                                         mail_user_var_expand_func_table, user,
+                                         &error) <= 0) {
+                       i_error("Failed to expand %s: %s", expand_field, error);
+               } else {
+                       printf("%s\n", str_c(str));
+               }
        }
 
        mail_user_unref(&user);
index 4eee4a2b0b394daefbcd3510d05ca1bd6a685f1b..9561456fc1b0dd17bce487e4717fcd3a0b0fe3e0 100644 (file)
@@ -235,6 +235,19 @@ static void cmd_director_status(struct doveadm_cmd_context *cctx)
        director_disconnect(ctx);
 }
 
+static bool user_hash_expand(const char *username, unsigned int *hash_r)
+{
+       const char *error;
+
+       if (!mail_user_hash(username, doveadm_settings->director_username_hash,
+                           hash_r, &error)) {
+               i_error("Failed to expand director_username_hash=%s: %s",
+                       doveadm_settings->director_username_hash, error);
+               return FALSE;
+       }
+       return TRUE;
+}
+
 static void
 user_list_add(const char *username, pool_t pool,
              HASH_TABLE_TYPE(user_list) users)
@@ -242,9 +255,11 @@ user_list_add(const char *username, pool_t pool,
        struct user_list *user, *old_user;
        unsigned int user_hash;
 
+       if (!user_hash_expand(username, &user_hash))
+               return;
+
        user = p_new(pool, struct user_list, 1);
        user->name = p_strdup(pool, username);
-       user_hash = mail_user_hash(username, doveadm_settings->director_username_hash);
 
        old_user = hash_table_lookup(users, POINTER_CAST(user_hash));
        if (old_user != NULL)
@@ -340,10 +355,11 @@ static void cmd_director_map(struct doveadm_cmd_context *cctx)
 
        if (ctx->user_map) {
                /* user -> hash mapping */
-               user_hash = mail_user_hash(ctx->host, doveadm_settings->director_username_hash);
-               doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
-               doveadm_print_header("hash", "hash", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
-               doveadm_print(t_strdup_printf("%u", user_hash));
+               if (user_hash_expand(ctx->host, &user_hash)) {
+                       doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
+                       doveadm_print_header("hash", "hash", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
+                       doveadm_print(t_strdup_printf("%u", user_hash));
+               }
                director_disconnect(ctx);
                return;
        }
@@ -570,9 +586,8 @@ static void cmd_director_move(struct doveadm_cmd_context *cctx)
                return;
        }
 
-       user_hash = mail_user_hash(ctx->user, doveadm_settings->director_username_hash);
-
-       if (director_get_host(ctx->host, &ips, &ips_count) != 0) {
+       if (!user_hash_expand(ctx->user, &user_hash) ||
+           director_get_host(ctx->host, &ips, &ips_count) != 0) {
                director_disconnect(ctx);
                return;
        }
index c55e59b7fd0f2d92f6aa5f6ca05d48e64d7f742d..fe144877c4cfc063c354791dc1eae07327795778 100644 (file)
@@ -228,7 +228,7 @@ get_ssh_cmd_args(const char *host, const char *login, const char *mail_user)
        struct var_expand_table *tab;
        ARRAY_TYPE(const_string) cmd_args;
        string_t *str, *str2;
-       const char *value, *const *args;
+       const char *value, *const *args, *error;
 
        tab = t_malloc_no0(sizeof(static_tab));
        memcpy(tab, static_tab, sizeof(static_tab));
@@ -250,8 +250,11 @@ get_ssh_cmd_args(const char *host, const char *login, const char *mail_user)
                           text in the parameter, skip it. */
                        str_truncate(str, 0);
                        str_truncate(str2, 0);
-                       var_expand(str, *args, tab);
-                       var_expand(str2, *args, static_tab);
+                       if (var_expand(str, *args, tab, &error) <= 0 ||
+                           var_expand(str2, *args, static_tab, &error) <= 0) {
+                               i_error("Failed to expand dsync_remote_cmd=%s: %s",
+                                       *args, error);
+                       }
                        if (strcmp(str_c(str), str_c(str2)) == 0 &&
                            str_len(str) > 0)
                                continue;
index 28347eb81d48406c7c3db2542e6e03ac36c13904..4d844bbf43b68321903f50a406e7b63bccc51715 100644 (file)
@@ -56,11 +56,15 @@ static void doveadm_print_formatted_print(const char *value)
        if (ctx.format == NULL) {
                i_fatal("formatted formatter cannot be used without a format.");
        }
+       const char *error;
        struct var_expand_table *entry = array_idx_modifiable(&ctx.headers, ctx.idx++);
        entry->value = value;
 
        if (ctx.idx >= array_count(&ctx.headers)) {
-               var_expand(ctx.buf, ctx.format, array_idx(&ctx.headers,0));
+               if (var_expand(ctx.buf, ctx.format, array_idx(&ctx.headers,0), &error) <= 0) {
+                       i_error("Failed to expand print format '%s': %s",
+                               ctx.format, error);
+               }
                doveadm_print_formatted_flush();
                ctx.idx = 0;
        }
index e177721ee81591eefb63ae92d16ee2fa6d1285a7..5461ddce0d8f546459b911b58e576427e9aa7356 100644 (file)
@@ -506,7 +506,7 @@ imap_client_create(int fd, const struct imap_client_state *state)
        struct imap_client *client;
        pool_t pool = pool_alloconly_create("imap client", 256);
        void *statebuf;
-       const char *ident;
+       const char *ident, *error;
 
        i_assert(state->username != NULL);
        i_assert(state->mail_log_prefix != NULL);
@@ -533,8 +533,12 @@ imap_client_create(int fd, const struct imap_client_state *state)
                string_t *str;
 
                str = t_str_new(256);
-               var_expand(str, state->mail_log_prefix,
-                          imap_client_get_var_expand_table(client));
+               if (var_expand(str, state->mail_log_prefix,
+                              imap_client_get_var_expand_table(client),
+                              &error) <= 0) {
+                       i_error("Failed to expand mail_log_prefix=%s: %s",
+                               state->mail_log_prefix, error);
+               }
                client->log_prefix = p_strdup(pool, str_c(str));
        } T_END;
 
index 6abb273d24a629eea96e10f38c184e58bc05f20e..ed1824f46a2940cc3d0f8a7353387f4b6fdd155d 100644 (file)
@@ -609,9 +609,15 @@ client_handle_user_command(struct client *client, const char *cmd,
        restrict_access_allow_coredumps(TRUE);
 
        set = mail_storage_service_user_get_set(user)[1];
-       settings_var_expand(&imap_urlauth_worker_setting_parser_info, set,
-                           mail_user->pool,
-                           mail_user_var_expand_table(mail_user));
+       if (settings_var_expand(&imap_urlauth_worker_setting_parser_info, set,
+                               mail_user->pool,
+                               mail_user_var_expand_table(mail_user),
+                               &error) <= 0) {
+               client_send_line(client, "NO");
+               client_abort(client, t_strdup_printf(
+                       "Session aborted: Failed to expand settings: %s", error));
+               return 0;
+       }
 
        if (set->verbose_proctitle) {
                verbose_proctitle = TRUE;
index c6000b3518fb687fabf236f830f72c6885b62ba2..e2bf126644fc18bf588289fb8d3ed8da53b83e52 100644 (file)
@@ -251,9 +251,13 @@ const char *client_stats(struct client *client)
                { '\0', NULL, NULL }
        };
        string_t *str;
+       const char *error;
 
        str = t_str_new(128);
-       var_expand(str, client->set->imap_logout_format, tab);
+       if (var_expand(str, client->set->imap_logout_format, tab, &error) <= 0) {
+               i_error("Failed to expand imap_logout_format=%s: %s",
+                       client->set->imap_logout_format, error);
+       }
        return str_c(str);
 }
 
index fe18e4a99cdaaaa650b782837bcaabfbfe3c6510..8384a419e6a6aa9587ca92b1a15f086d541aa219 100644 (file)
@@ -251,10 +251,17 @@ int client_create_from_input(const struct mail_storage_service_input *input,
                verbose_proctitle = TRUE;
        lda_set = mail_storage_service_user_get_set(user)[2];
 
-       settings_var_expand(&imap_setting_parser_info, imap_set,
-                           mail_user->pool, mail_user_var_expand_table(mail_user));
-       settings_var_expand(&lda_setting_parser_info, lda_set,
-                           mail_user->pool, mail_user_var_expand_table(mail_user));
+       if (settings_var_expand(&imap_setting_parser_info, imap_set,
+                               mail_user->pool, mail_user_var_expand_table(mail_user),
+                               &errstr) <= 0 ||
+           settings_var_expand(&lda_setting_parser_info, lda_set,
+                               mail_user->pool, mail_user_var_expand_table(mail_user),
+                               &errstr) <= 0) {
+               *error_r = t_strdup_printf("Failed to expand settings: %s", errstr);
+               mail_user_unref(&mail_user);
+               mail_storage_service_user_free(&user);
+               return -1;
+       }
 
        client = client_create(fd_in, fd_out, input->session_id,
                               mail_user, user, imap_set, lda_set);
index df6dddc6e2a2cf464d417aab42dbd2ee5fc8b94e..964850f82af4eb623c829fbd73d648e3e44fd777 100644 (file)
@@ -425,9 +425,11 @@ int main(int argc, char *argv[])
         lib_signals_ignore(SIGXFSZ, TRUE);
 #endif
        lda_set = mail_storage_service_user_get_set(service_user)[1];
-       settings_var_expand(&lda_setting_parser_info, lda_set,
-                           ctx.dest_user->pool,
-                           mail_user_var_expand_table(ctx.dest_user));
+       if (settings_var_expand(&lda_setting_parser_info, lda_set,
+                               ctx.dest_user->pool,
+                               mail_user_var_expand_table(ctx.dest_user),
+                               &errstr) <= 0)
+               i_fatal("Failed to expand settings: %s", errstr);
        ctx.set = lda_set;
 
        if (ctx.dest_user->mail_debug && *user_source != '\0') {
index 4f753de7dfe3f7667adc4d64855786d4863fd540..a57e21d4ca9eb506814459eba1381fc10cb65f91 100644 (file)
@@ -146,7 +146,7 @@ void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...)
 {
        va_list args;
        string_t *str;
-       const char *msg;
+       const char *msg, *error;
 
        if (*ctx->set->deliver_log_format == '\0')
                return;
@@ -161,7 +161,11 @@ void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...)
        /* update %$ */
        ctx->var_expand_table[0].value = msg;
        mail_deliver_log_var_expand_table_update_times(ctx, ctx->var_expand_table);
-       var_expand(str, ctx->set->deliver_log_format, ctx->var_expand_table);
+       if (var_expand(str, ctx->set->deliver_log_format,
+                      ctx->var_expand_table, &error) <= 0) {
+               i_error("Failed to expand deliver_log_format=%s: %s",
+                       ctx->set->deliver_log_format, error);
+       }
        ctx->var_expand_table[0].value = "";
        ctx->var_expand_table[VAR_EXPAND_DELIVERY_TIME_IDX].value = "";
 
index eb2b94720e48e5d9b3ca8ec5f11e4726796bb5da..405e64ff01ac9f8fe9d8443f294a78e92f7dff49 100644 (file)
@@ -98,8 +98,11 @@ int mail_send_rejection(struct mail_deliver_context *ctx, const char *recipient,
                ctx->dsn ? "delivery-status" : "disposition-notification",
                boundary);
     str_append(str, "Subject: ");
-    var_expand(str, ctx->set->rejection_subject,
-              get_var_expand_table(mail, reason, recipient));
+    if (var_expand(str, ctx->set->rejection_subject,
+                  get_var_expand_table(mail, reason, recipient), &error) <= 0) {
+           i_error("Failed to expand rejection_subject=%s: %s",
+                   ctx->set->rejection_subject, error);
+    }
     str_append(str, "\r\n");
 
     str_append(str, "Auto-Submitted: auto-replied (rejected)\r\n");
@@ -112,8 +115,11 @@ int mail_send_rejection(struct mail_deliver_context *ctx, const char *recipient,
     str_append(str, "Content-Disposition: inline\r\n");
     str_append(str, "Content-Transfer-Encoding: 8bit\r\n\r\n");
 
-    var_expand(str, ctx->set->rejection_reason,
-              get_var_expand_table(mail, reason, recipient));
+    if (var_expand(str, ctx->set->rejection_reason,
+                  get_var_expand_table(mail, reason, recipient), &error) <= 0) {
+           i_error("Failed to expand rejection_reason=%s: %s",
+                   ctx->set->rejection_reason, error);
+    }
     str_append(str, "\r\n");
 
     if (ctx->dsn) {
index 1c7bc850756d3841a3b3a830555ee3ff55fe17c8..05ffa0d7895560049237e05ce16deff69b510a0e 100644 (file)
@@ -6,10 +6,13 @@
 #include "var-expand.h"
 #include "mail-user-hash.h"
 
-unsigned int mail_user_hash(const char *username, const char *format)
+bool mail_user_hash(const char *username, const char *format,
+                   unsigned int *hash_r, const char **error_r)
 {
        unsigned char md5[MD5_RESULTLEN];
        unsigned int i, hash = 0;
+       char *error_dup = NULL;
+       int ret = 1;
 
        if (strcmp(format, "%u") == 0) {
                /* fast path */
@@ -28,12 +31,18 @@ unsigned int mail_user_hash(const char *username, const char *format)
                        { '\0', NULL, NULL }
                };
                string_t *str = t_str_new(128);
+               const char *error;
 
-               var_expand(str, format, tab);
+               ret = var_expand(str, format, tab, &error);
+               i_assert(ret >= 0);
+               if (ret == 0)
+                       error_dup = i_strdup(error);
                md5_get_digest(str_data(str), str_len(str), md5);
        } T_END;
        for (i = 0; i < sizeof(hash); i++)
                hash = (hash << CHAR_BIT) | md5[i];
-       return hash;
+       *hash_r = hash;
+       *error_r = t_strdup(error_dup);
+       i_free(error_dup);
+       return ret > 0;
 }
-
index 3287dfcd0523b027528fbf3332c99434200860fe..5362389a69acebb83ee112ac3a2a99d73a38f36c 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef MAIL_USER_HASH
 #define MAIL_USER_HASH
 
-/* Return a hash for username, based on given format. The format can use
-   %n, %d and %u variables. */
-unsigned int mail_user_hash(const char *username, const char *format);
+/* Get a hash for username, based on given format. The format can use
+   %n, %d and %u variables. Returns TRUE if ok, FALSE if format is invalid. */
+bool mail_user_hash(const char *username, const char *format,
+                   unsigned int *hash_r, const char **error_r);
 
 #endif
index cb3afd0211653a657d5b1f47563a2d2607f8439d..736d2f09ecd7f3ee73447ab45d76f0db97889b2b 100644 (file)
@@ -1269,16 +1269,19 @@ void settings_parse_set_keys_expandeded(struct setting_parser_context *ctx,
                settings_parse_set_key_expandeded(ctx, pool, *keys);
 }
 
-static void ATTR_NULL(3, 4, 5)
+static int ATTR_NULL(3, 4, 5)
 settings_var_expand_info(const struct setting_parser_info *info, void *set,
                         pool_t pool,
                         const struct var_expand_table *table,
                         const struct var_expand_func_table *func_table,
-                        void *func_context, string_t *str)
+                        void *func_context, string_t *str,
+                        const char **error_r)
 {
        const struct setting_define *def;
        void *value, *const *children;
+       const char *error;
        unsigned int i, count;
+       int ret, final_ret = 1;
 
        for (def = info->defines; def->key != NULL; def++) {
                value = PTR_OFFSET(set, def->offset);
@@ -1307,8 +1310,14 @@ settings_var_expand_info(const struct setting_parser_info *info, void *set,
                                *val += 1;
                        } else if (**val == SETTING_STRVAR_UNEXPANDED[0]) {
                                str_truncate(str, 0);
-                               var_expand_with_funcs(str, *val + 1, table,
-                                                     func_table, func_context);
+                               ret = var_expand_with_funcs(str, *val + 1, table,
+                                                           func_table, func_context,
+                                                           &error);
+                               if (final_ret > ret) {
+                                       final_ret = ret;
+                                       *error_r = t_strdup_printf(
+                                               "%s: %s", def->key, error);
+                               }
                                *val = p_strdup(pool, str_c(str));
                        } else {
                                i_assert(**val == SETTING_STRVAR_EXPANDED[0]);
@@ -1325,46 +1334,64 @@ settings_var_expand_info(const struct setting_parser_info *info, void *set,
 
                        children = array_get(val, &count);
                        for (i = 0; i < count; i++) {
-                               settings_var_expand_info(def->list_info,
+                               ret = settings_var_expand_info(def->list_info,
                                        children[i], pool, table, func_table,
-                                       func_context, str);
+                                       func_context, str, &error);
+                               if (final_ret > ret) {
+                                       final_ret = ret;
+                                       *error_r = error;
+                               }
                        }
                        break;
                }
                }
        }
+       return final_ret;
 }
 
-void settings_var_expand(const struct setting_parser_info *info,
-                        void *set, pool_t pool,
-                        const struct var_expand_table *table)
+int settings_var_expand(const struct setting_parser_info *info,
+                       void *set, pool_t pool,
+                       const struct var_expand_table *table,
+                       const char **error_r)
 {
-       settings_var_expand_with_funcs(info, set, pool, table, NULL, NULL);
+       return settings_var_expand_with_funcs(info, set, pool, table,
+                                             NULL, NULL, error_r);
 }
 
-void settings_var_expand_with_funcs(const struct setting_parser_info *info,
-                                   void *set, pool_t pool,
-                                   const struct var_expand_table *table,
-                                   const struct var_expand_func_table *func_table,
-                                   void *func_context)
+int settings_var_expand_with_funcs(const struct setting_parser_info *info,
+                                  void *set, pool_t pool,
+                                  const struct var_expand_table *table,
+                                  const struct var_expand_func_table *func_table,
+                                  void *func_context, const char **error_r)
 {
-       string_t *str;
+       char *error_dup = NULL;
+       int ret;
 
        T_BEGIN {
-               str = t_str_new(256);
-               settings_var_expand_info(info, set, pool, table,
-                                        func_table, func_context, str);
+               const char *error;
+               string_t *str = t_str_new(256);
+
+               ret = settings_var_expand_info(info, set, pool, table,
+                                              func_table, func_context, str,
+                                              &error);
+               if (ret <= 0)
+                       error_dup = i_strdup(error);
        } T_END;
+       *error_r = t_strdup(error_dup);
+       i_free(error_dup);
+       return ret;
 }
 
 void settings_parse_var_skip(struct setting_parser_context *ctx)
 {
        unsigned int i;
+       const char *error;
 
        for (i = 0; i < ctx->root_count; i++) {
-               settings_var_expand_info(ctx->roots[i].info,
-                                        ctx->roots[i].set_struct,
-                                        NULL, NULL, NULL, NULL, NULL);
+               (void)settings_var_expand_info(ctx->roots[i].info,
+                                              ctx->roots[i].set_struct,
+                                              NULL, NULL, NULL, NULL, NULL,
+                                              &error);
        }
 }
 
index 28b3fac78d5f4695a843dbc9a03e8fac0c5cdce0..ed0345e82124b549b4644149b0ce9ea9badc5568 100644 (file)
@@ -185,15 +185,17 @@ void settings_parse_set_keys_expandeded(struct setting_parser_context *ctx,
    actually knowing what the variables are. */
 void settings_parse_var_skip(struct setting_parser_context *ctx);
 /* Expand all unexpanded variables using the given table. Update the string
-   pointers so that they can be used without skipping over the '1'. */
-void settings_var_expand(const struct setting_parser_info *info,
-                        void *set, pool_t pool,
-                        const struct var_expand_table *table);
-void settings_var_expand_with_funcs(const struct setting_parser_info *info,
-                                   void *set, pool_t pool,
-                                   const struct var_expand_table *table,
-                                   const struct var_expand_func_table *func_table,
-                                   void *func_context);
+   pointers so that they can be used without skipping over the '1'.
+   Returns the same as var_expand(). */
+int settings_var_expand(const struct setting_parser_info *info,
+                       void *set, pool_t pool,
+                       const struct var_expand_table *table,
+                       const char **error_r);
+int settings_var_expand_with_funcs(const struct setting_parser_info *info,
+                                  void *set, pool_t pool,
+                                  const struct var_expand_table *table,
+                                  const struct var_expand_func_table *func_table,
+                                  void *func_context, const char **error_r);
 /* Go through all the settings and return the first one that has an unexpanded
    setting containing the given %key. */
 bool settings_vars_have_key(const struct setting_parser_info *info, void *set,
index c5361a913d2d260071e8af794e2596ed66ef8d16..9cbc4ed437fec9b759848b040cd050e63b408947 100644 (file)
@@ -529,9 +529,14 @@ static void driver_cassandra_metrics_write(struct cassandra_db *db)
        };
        string_t *path = t_str_new(64);
        string_t *data;
+       const char *error;
        int fd;
 
-       var_expand(path, db->metrics_path, tab);
+       if (var_expand(path, db->metrics_path, tab, &error) <= 0) {
+               i_error("cassandra: Failed to expand metrics_path=%s: %s",
+                       db->metrics_path, error);
+               return;
+       }
 
        fd = open(str_c(path), O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0600);
        if (fd == -1) {
index 06965538ad004a0340c23b25cdf9c0c844e8d0ef..b742c54bfbac224aabc8dcbbc4c3064498568a0b 100644 (file)
@@ -236,7 +236,12 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
 
        prefix = t_str_new(128);
        str_append(prefix, ns->prefix);
-       var_expand(prefix, storage->ns_prefix_pattern, tab);
+       if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
+               mailbox_list_set_critical(list,
+                       "Failed to expand namespace prefix '%s': %s",
+                       storage->ns_prefix_pattern, error);
+               return -1;
+       }
 
        *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
        if (*_ns != NULL) {
@@ -273,6 +278,15 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
                }
        }
 
+       location = t_str_new(256);
+       if (ret > 0 &&
+           var_expand(location, storage->location, tab, &error) <= 0) {
+               mailbox_list_set_critical(list,
+                       "Failed to expand namespace location '%s': %s",
+                       storage->location, error);
+               return -1;
+       }
+
        /* create the new namespace */
        new_ns = i_new(struct mail_namespace, 1);
        new_ns->refcount = 1;
@@ -286,10 +300,7 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
        new_ns->mail_set = _storage->set;
        i_array_init(&new_ns->all_storages, 2);
 
-       location = t_str_new(256);
-       if (ret > 0)
-               var_expand(location, storage->location, tab);
-       else {
+       if (ret <= 0) {
                get_nonexistent_user_location(storage, userdomain, location);
                new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
                if (ns->user->mail_debug) {
index 83dffe9fa00678639bec8eb0cdde53783279afec..74b89c3fc8362cafb5193a39bffddf81376c868a 100644 (file)
@@ -90,12 +90,13 @@ struct mail_storage_service_user {
 
 struct module *mail_storage_service_modules = NULL;
 
-static void
+static int
 mail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
                                string_t *str, const char *format,
                                struct mail_storage_service_user *user,
                                const struct mail_storage_service_input *input,
-                               const struct mail_storage_service_privileges *priv);
+                               const struct mail_storage_service_privileges *priv,
+                               const char **error_r);
 
 static bool
 mail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
@@ -447,22 +448,27 @@ mail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx,
        return get_var_expand_table(ctx->service, NULL, input, &priv);
 }
 
-static const char *
+static bool
 user_expand_varstr(struct mail_storage_service_ctx *ctx,
                   struct mail_storage_service_user *user,
                   struct mail_storage_service_privileges *priv,
-                  const char *str)
+                  const char *str, const char **value_r, const char **error_r)
 {
-       string_t *ret;
+       string_t *value;
+       int ret;
 
-       if (*str == SETTING_STRVAR_EXPANDED[0])
-               return str + 1;
+       if (*str == SETTING_STRVAR_EXPANDED[0]) {
+               *value_r = str + 1;
+               return 1;
+       }
 
        i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
 
-       ret = t_str_new(256);
-       mail_storage_service_var_expand(ctx, ret, str + 1, user, &user->input, priv);
-       return str_c(ret);
+       value = t_str_new(256);
+       ret = mail_storage_service_var_expand(ctx, value, str + 1, user,
+                                             &user->input, priv, error_r);
+       *value_r = str_c(value);
+       return ret > 0;
 }
 
 static int
@@ -474,6 +480,7 @@ service_parse_privileges(struct mail_storage_service_ctx *ctx,
        const struct mail_user_settings *set = user->user_set;
        uid_t uid = (uid_t)-1;
        gid_t gid = (gid_t)-1;
+       const char *error;
 
        memset(priv_r, 0, sizeof(*priv_r));
        if (*set->mail_uid != '\0') {
@@ -516,10 +523,20 @@ service_parse_privileges(struct mail_storage_service_ctx *ctx,
 
        /* variable strings are expanded in mail_user_init(),
           but we need the home and chroot sooner so do them separately here. */
-       priv_r->home = user_expand_varstr(ctx, user, priv_r,
-                                         user->user_set->mail_home);
-       priv_r->chroot = user_expand_varstr(ctx, user, priv_r,
-                                           user->user_set->mail_chroot);
+       if (!user_expand_varstr(ctx, user, priv_r, user->user_set->mail_home,
+                               &priv_r->home, &error) <= 0) {
+               *error_r = t_strdup_printf(
+                       "Failed to expand mail_home '%s': %s",
+                       user->user_set->mail_home, error);
+               return -1;
+       }
+       if (!user_expand_varstr(ctx, user, priv_r, user->user_set->mail_chroot,
+                               &priv_r->chroot, &error)) {
+               *error_r = t_strdup_printf(
+                       "Failed to expand mail_chroot '%s': %s",
+                       user->user_set->mail_chroot, error);
+               return -1;
+       }
        return 0;
 }
 
@@ -785,20 +802,21 @@ mail_storage_service_input_var_userdb(const char *data, void *context)
                        user == NULL ? NULL : user->input.userdb_fields);
 }
 
-static void
+static int
 mail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
                                string_t *str, const char *format,
                                struct mail_storage_service_user *user,
                                const struct mail_storage_service_input *input,
-                               const struct mail_storage_service_privileges *priv)
+                               const struct mail_storage_service_privileges *priv,
+                               const char **error_r)
 {
        static const struct var_expand_func_table func_table[] = {
                { "userdb", mail_storage_service_input_var_userdb },
                { NULL, NULL }
        };
-       var_expand_with_funcs(str, format,
+       return var_expand_with_funcs(str, format,
                   get_var_expand_table(ctx->service, user, input, priv),
-                  func_table, user);
+                  func_table, user, error_r);
 }
 
 static void
@@ -806,14 +824,16 @@ mail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
                              struct mail_storage_service_user *user,
                              struct mail_storage_service_privileges *priv)
 {
+       const char *error;
+
        ctx->log_initialized = TRUE;
        T_BEGIN {
                string_t *str;
 
                str = t_str_new(256);
-               mail_storage_service_var_expand(ctx, str,
+               (void)mail_storage_service_var_expand(ctx, str,
                        user->user_set->mail_log_prefix,
-                       user, &user->input, priv);
+                       user, &user->input, priv, &error);
                user->log_prefix = p_strdup(user->pool, str_c(str));
        } T_END;
 
@@ -1106,10 +1126,11 @@ mail_storage_service_set_log_prefix(struct mail_storage_service_ctx *ctx,
                                    const struct mail_storage_service_privileges *priv)
 {
        string_t *str;
+       const char *error;
 
        str = t_str_new(256);
-       mail_storage_service_var_expand(ctx, str, user_set->mail_log_prefix,
-                                       user, input, priv);
+       (void)mail_storage_service_var_expand(ctx, str, user_set->mail_log_prefix,
+                                             user, input, priv, &error);
        i_set_failure_prefix("%s", str_c(str));
 }
 
index 771078b17cdbe057a8377f19aeaf73d9864eea9b..5083b1bce202718a76a56e6e61c280c02046baad 100644 (file)
@@ -80,7 +80,7 @@ struct mail_user *mail_user_alloc(const char *username,
 static void
 mail_user_expand_plugins_envs(struct mail_user *user)
 {
-       const char **envs, *home;
+       const char **envs, *home, *error;
        string_t *str;
        unsigned int i, count;
 
@@ -101,9 +101,15 @@ mail_user_expand_plugins_envs(struct mail_user *user)
                        return;
                }
                str_truncate(str, 0);
-               var_expand_with_funcs(str, envs[i+1],
-                                     mail_user_var_expand_table(user),
-                                     mail_user_var_expand_func_table, user);
+               if (var_expand_with_funcs(str, envs[i+1],
+                                         mail_user_var_expand_table(user),
+                                         mail_user_var_expand_func_table, user,
+                                         &error) <= 0) {
+                       user->error = p_strdup_printf(user->pool,
+                               "Failed to expand plugin setting %s = '%s': %s",
+                               envs[i], envs[i+1], error);
+                       return;
+               }
                envs[i+1] = p_strdup(user->pool, str_c(str));
        }
 }
@@ -111,7 +117,7 @@ mail_user_expand_plugins_envs(struct mail_user *user)
 int mail_user_init(struct mail_user *user, const char **error_r)
 {
        const struct mail_storage_settings *mail_set;
-       const char *home, *key, *value;
+       const char *home, *key, *value, *error;
        bool need_home_dir;
 
        need_home_dir = user->_home == NULL &&
@@ -124,9 +130,13 @@ int mail_user_init(struct mail_user *user, const char **error_r)
        }
 
        /* expand settings after we can expand %h */
-       settings_var_expand_with_funcs(user->set_info, user->set,
-                                      user->pool, mail_user_var_expand_table(user),
-                                      mail_user_var_expand_func_table, user);
+       if (settings_var_expand_with_funcs(user->set_info, user->set,
+                                          user->pool, mail_user_var_expand_table(user),
+                                          mail_user_var_expand_func_table, user,
+                                          &error) <= 0) {
+               user->error = p_strdup_printf(user->pool,
+                       "Failed to expand settings: %s", error);
+       }
        user->settings_expanded = TRUE;
        mail_user_expand_plugins_envs(user);
 
@@ -352,26 +362,31 @@ static int mail_user_userdb_lookup_home(struct mail_user *user)
        return ret;
 }
 
-static void mail_user_get_mail_home(struct mail_user *user)
+static bool mail_user_get_mail_home(struct mail_user *user)
 {
-       const char *home = user->set->mail_home;
+       const char *error, *home = user->set->mail_home;
        string_t *str;
 
        if (user->settings_expanded) {
                user->_home = home[0] != '\0' ? home : NULL;
-               return;
+               return TRUE;
        }
        /* we're still initializing user. need to do the expansion ourself. */
        i_assert(home[0] == SETTING_STRVAR_UNEXPANDED[0]);
        home++;
        if (home[0] == '\0')
-               return;
+               return TRUE;
 
        str = t_str_new(128);
-       var_expand_with_funcs(str, home,
-                             mail_user_var_expand_table(user),
-                             mail_user_var_expand_func_table, user);
+       if (var_expand_with_funcs(str, home,
+                                 mail_user_var_expand_table(user),
+                                 mail_user_var_expand_func_table, user,
+                                 &error) <= 0) {
+               i_error("Failed to expand mail_home=%s: %s", home, error);
+               return FALSE;
+       }
        user->_home = p_strdup(user->pool, str_c(str));
+       return TRUE;
 }
 
 int mail_user_get_home(struct mail_user *user, const char **home_r)
@@ -385,7 +400,8 @@ int mail_user_get_home(struct mail_user *user, const char **home_r)
 
        if (mail_user_auth_master_conn == NULL) {
                /* no userdb connection. we can only use mail_home setting. */
-               mail_user_get_mail_home(user);
+               if (!mail_user_get_mail_home(user))
+                       return -1;
        } else if ((ret = mail_user_userdb_lookup_home(user)) < 0) {
                /* userdb lookup failed */
                return -1;
@@ -395,7 +411,8 @@ int mail_user_get_home(struct mail_user *user, const char **home_r)
        } else if (user->_home == NULL) {
                /* no home returned by userdb lookup, fallback to
                   mail_home setting. */
-               mail_user_get_mail_home(user);
+               if (!mail_user_get_mail_home(user))
+                       return -1;
        }
        user->home_looked_up = TRUE;
 
index 080a0739a4320ba381cf7374f54d167517bdb733..8b23f7ce3d2f00959e1a16d16ef5c71dc8c0000e 100644 (file)
@@ -9,6 +9,7 @@
 struct var_expand_test {
        const char *in;
        const char *out;
+       int ret;
 };
 
 struct var_get_key_range_test {
@@ -19,25 +20,26 @@ struct var_get_key_range_test {
 static void test_var_expand_ranges(void)
 {
        static struct var_expand_test tests[] = {
-               { "%v", "value1234" },
-               { "%3v", "val" },
-               { "%3.2v", "ue" },
-               { "%3.-2v", "ue12" },
-               { "%-3.2v", "23" },
-               { "%0.-1v", "value123" },
-               { "%-4.-1v", "123" }
+               { "%v", "value1234", 1 },
+               { "%3v", "val", 1 },
+               { "%3.2v", "ue", 1 },
+               { "%3.-2v", "ue12", 1 },
+               { "%-3.2v", "23", 1 },
+               { "%0.-1v", "value123", 1 },
+               { "%-4.-1v", "123", 1 }
        };
        static struct var_expand_table table[] = {
                { 'v', "value1234", NULL },
                { '\0', NULL, NULL }
        };
        string_t *str = t_str_new(128);
+       const char *error;
        unsigned int i;
 
        test_begin("var_expand - ranges");
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                str_truncate(str, 0);
-               var_expand(str, tests[i].in, table);
+               test_assert(var_expand(str, tests[i].in, table, &error) == tests[i].ret);
                test_assert(strcmp(tests[i].out, str_c(str)) == 0);
        }
        test_end();
@@ -46,16 +48,16 @@ static void test_var_expand_ranges(void)
 static void test_var_expand_builtin(void)
 {
        static struct var_expand_test tests[] = {
-               { "%{hostname}", NULL },
-               { "%{pid}", NULL },
-               { "a%{env:FOO}b", "abaRb" },
-               { "%50Hv", "1f" },
-               { "%50Hw", "2e" },
-               { "%50Nv", "25" },
-               { "%50Nw", "e" },
-
-               { "%{nonexistent}", "UNSUPPORTED_VARIABLE_nonexistent" },
-               { "%{nonexistent:default}", "UNSUPPORTED_VARIABLE_nonexistent" },
+               { "%{hostname}", NULL, 1 },
+               { "%{pid}", NULL, 1 },
+               { "a%{env:FOO}b", "abaRb", 1 },
+               { "%50Hv", "1f", 1 },
+               { "%50Hw", "2e", 1 },
+               { "%50Nv", "25", 1 },
+               { "%50Nw", "e", 1 },
+
+               { "%{nonexistent}", "UNSUPPORTED_VARIABLE_nonexistent", 0 },
+               { "%{nonexistent:default}", "UNSUPPORTED_VARIABLE_nonexistent", 0 },
        };
        static struct var_expand_table table[] = {
                { 'v', "value", NULL },
@@ -63,6 +65,7 @@ static void test_var_expand_builtin(void)
                { '\0', NULL, NULL }
        };
        string_t *str = t_str_new(128);
+       const char *error;
        unsigned int i;
 
        tests[0].out = my_hostname;
@@ -72,7 +75,7 @@ static void test_var_expand_builtin(void)
        test_begin("var_expand - builtin");
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                str_truncate(str, 0);
-               var_expand(str, tests[i].in, table);
+               test_assert_idx(var_expand(str, tests[i].in, table, &error) == tests[i].ret, i);
                test_assert_idx(strcmp(tests[i].out, str_c(str)) == 0, i);
        }
        test_end();
@@ -124,10 +127,10 @@ static const char *test_var_expand_func3(const char *data ATTR_UNUSED,
 static void test_var_expand_with_funcs(void)
 {
        static struct var_expand_test tests[] = {
-               { "%{func1}", "<>" },
-               { "%{func1:foo}", "<foo>" },
-               { "%{func2}", "" },
-               { "%{func3}", "" }
+               { "%{func1}", "<>", 1 },
+               { "%{func1:foo}", "<foo>", 1 },
+               { "%{func2}", "", 1 },
+               { "%{func3}", "", 1 }
        };
        static struct var_expand_table table[] = {
                { '\0', NULL, NULL }
@@ -139,13 +142,14 @@ static void test_var_expand_with_funcs(void)
                { NULL, NULL }
        };
        string_t *str = t_str_new(128);
+       const char *error;
        unsigned int i;
        int ctx = 0xabcdef;
 
        test_begin("var_expand_with_funcs");
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                str_truncate(str, 0);
-               var_expand_with_funcs(str, tests[i].in, table, func_table, &ctx);
+               test_assert_idx(var_expand_with_funcs(str, tests[i].in, table, func_table, &ctx, &error) == tests[i].ret, i);
                test_assert_idx(strcmp(tests[i].out, str_c(str)) == 0, i);
        }
        test_end();
index 5e61ace7a9ec03a7e46b7e466daa8111ce8f03ea..2483cbf047d6cf1f6ae25ba936ac1605b1a28692 100644 (file)
@@ -166,60 +166,75 @@ static const struct var_expand_modifier modifiers[] = {
        { '\0', NULL }
 };
 
-static const char *
-var_expand_short(const struct var_expand_table *table, char key)
+static int
+var_expand_short(const struct var_expand_table *table, char key,
+                const char **var_r, const char **error_r)
 {
         const struct var_expand_table *t;
 
        if (table != NULL) {
                for (t = table; !TABLE_LAST(t); t++) {
-                       if (t->key == key)
-                               return t->value != NULL ? t->value : "";
+                       if (t->key == key) {
+                               *var_r = t->value != NULL ? t->value : "";
+                               return 1;
+                       }
                }
        }
 
        /* not found */
-       if (key == '%')
-               return "%";
-       return NULL;
+       if (key == '%') {
+               *var_r = "%";
+               return 1;
+       }
+       if (*error_r == NULL)
+               *error_r = t_strdup_printf("Unknown variable '%%%c'", key);
+       return 0;
 }
 
-static const char *
+static int
 var_expand_func(const struct var_expand_func_table *func_table,
-               const char *key, const char *data, void *context)
+               const char *key, const char *data, void *context,
+               const char **var_r, const char **error_r)
 {
        const char *value;
 
        if (strcmp(key, "env") == 0) {
                value = getenv(data);
-               return value != NULL ? value : "";
+               *var_r = value != NULL ? value : "";
+               return 1;
        }
-       if (func_table == NULL)
-               return NULL;
-
-       for (; func_table->key != NULL; func_table++) {
-               if (strcmp(func_table->key, key) == 0) {
-                       value = func_table->func(data, context);
-                       return value != NULL ? value : "";
+       if (func_table != NULL) {
+               for (; func_table->key != NULL; func_table++) {
+                       if (strcmp(func_table->key, key) == 0) {
+                               value = func_table->func(data, context);
+                               *var_r = value != NULL ? value : "";
+                               return 1;
+                       }
                }
        }
-       return NULL;
+       if (*error_r == NULL)
+               *error_r = t_strdup_printf("Unknown variable '%%%s'", key);
+       *var_r = t_strdup_printf("UNSUPPORTED_VARIABLE_%s", key);
+       return 0;
 }
 
-static const char *
+static int
 var_expand_long(const struct var_expand_table *table,
                const struct var_expand_func_table *func_table,
-               const void *key_start, unsigned int key_len, void *context)
+               const void *key_start, unsigned int key_len, void *context,
+               const char **var_r, const char **error_r)
 {
         const struct var_expand_table *t;
        const char *key, *value = NULL;
+       int ret = 1;
 
        if (table != NULL) {
                for (t = table; !TABLE_LAST(t); t++) {
                        if (t->long_key != NULL &&
                            strncmp(t->long_key, key_start, key_len) == 0 &&
                            t->long_key[key_len] == '\0') {
-                               return t->value != NULL ? t->value : "";
+                               *var_r = t->value != NULL ? t->value : "";
+                               return 1;
                        }
                }
        }
@@ -248,17 +263,16 @@ var_expand_long(const struct var_expand_table *table,
                        key = t_strdup_until(key, data++);
                else
                        data = "";
-               value = var_expand_func(func_table, key, data, context);
+               ret = var_expand_func(func_table, key, data, context, &value, error_r);
        }
-       if (value == NULL)
-               return t_strdup_printf("UNSUPPORTED_VARIABLE_%s", key);
-       return value;
+       *var_r = value;
+       return ret;
 }
 
-void var_expand_with_funcs(string_t *dest, const char *str,
-                          const struct var_expand_table *table,
-                          const struct var_expand_func_table *func_table,
-                          void *context)
+int var_expand_with_funcs(string_t *dest, const char *str,
+                         const struct var_expand_table *table,
+                         const struct var_expand_func_table *func_table,
+                         void *context, const char **error_r)
 {
         const struct var_expand_modifier *m;
        const char *var;
@@ -267,6 +281,9 @@ void var_expand_with_funcs(string_t *dest, const char *str,
                (const char *, struct var_expand_context *);
        const char *end;
        unsigned int i, len, modifier_count;
+       int ret, final_ret = 1;
+
+       *error_r = NULL;
 
        memset(&ctx, 0, sizeof(ctx));
        for (; *str != '\0'; str++) {
@@ -342,13 +359,16 @@ void var_expand_with_funcs(string_t *dest, const char *str,
                        if (*str == '{' && (end = strchr(str, '}')) != NULL) {
                                /* %{long_key} */
                                len = end - (str + 1);
-                               var = var_expand_long(table, func_table,
-                                                     str+1, len, context);
+                               ret = var_expand_long(table, func_table,
+                                                     str+1, len, context,
+                                                     &var, error_r);
                                i_assert(var != NULL);
                                str = end;
                        } else {
-                               var = var_expand_short(table, *str);
+                               ret = var_expand_short(table, *str, &var, error_r);
                        }
+                       if (final_ret > ret)
+                               final_ret = ret;
 
                        if (var != NULL) {
                                for (i = 0; i < modifier_count; i++)
@@ -385,12 +405,13 @@ void var_expand_with_funcs(string_t *dest, const char *str,
                        }
                }
        }
+       return final_ret;
 }
 
-void var_expand(string_t *dest, const char *str,
-               const struct var_expand_table *table)
+int var_expand(string_t *dest, const char *str,
+              const struct var_expand_table *table, const char **error_r)
 {
-       var_expand_with_funcs(dest, str, table, NULL, NULL);
+       return var_expand_with_funcs(dest, str, table, NULL, NULL, error_r);
 }
 
 static bool
index aea8d77b33cc41c6f5b9415f2b3851693d8d8912..e93884fd80f78bbb54902f5e815691776e0d8cf6 100644 (file)
@@ -14,15 +14,18 @@ struct var_expand_func_table {
 };
 
 /* Expand % variables in src and append the string in dest.
-   table must end with key = 0. */
-void var_expand(string_t *dest, const char *str,
-               const struct var_expand_table *table);
+   table must end with key = 0. Returns 1 on success, 0 if the format string
+   contained invalid/unknown %variables. Even in case of errors the dest string
+   is still written as fully as possible. */
+int var_expand(string_t *dest, const char *str,
+              const struct var_expand_table *table,
+              const char **error_r);
 /* Like var_expand(), but support also callback functions for
    variable expansion. */
-void var_expand_with_funcs(string_t *dest, const char *str,
-                          const struct var_expand_table *table,
-                          const struct var_expand_func_table *func_table,
-                          void *func_context) ATTR_NULL(3, 4, 5);
+int var_expand_with_funcs(string_t *dest, const char *str,
+                         const struct var_expand_table *table,
+                         const struct var_expand_func_table *func_table,
+                         void *func_context, const char **error_r) ATTR_NULL(3, 4, 5);
 
 /* Returns the actual key character for given string, ie. skip any modifiers
    that are before it. The string should be the data after the '%' character.
index e922958be2d1e2d27fe6425878e4fbe2380f8a2e..6dbdad788570fa41f47f994fe3b834c7ccb89aa2 100644 (file)
@@ -192,8 +192,11 @@ static void client_read_settings(struct client *client)
                i_fatal("%s", error);
 
        lmtp_settings_dup(set_parser, client->pool, &lmtp_set, &lda_set);
-       settings_var_expand(&lmtp_setting_parser_info, lmtp_set, client->pool,
-               mail_storage_service_get_var_expand_table(storage_service, &input));
+       const struct var_expand_table *tab =
+               mail_storage_service_get_var_expand_table(storage_service, &input);
+       if (settings_var_expand(&lmtp_setting_parser_info, lmtp_set,
+                               client->pool, tab, &error) <= 0)
+               i_fatal("Failed to expand settings: %s", error);
        client->service_set = master_service_settings_get(master_service);
        client->lmtp_set = lmtp_set;
        client->unexpanded_lda_set = lda_set;
index 965390d167a33869fba54a97c4aee37cdc80afc6..fd1a3b509e83410d14d2f7e2861bca6039e3c8fb 100644 (file)
@@ -851,17 +851,29 @@ client_deliver(struct client *client, const struct mail_recipient *rcpt,
                                 rcpt->address);
                return -1;
        }
-       str = t_str_new(256);
-       var_expand_with_funcs(str, client->state.dest_user->set->mail_log_prefix,
-                             mail_user_var_expand_table(client->state.dest_user),
-                             mail_user_var_expand_func_table,
-                             client->state.dest_user);
-       i_set_failure_prefix("%s", str_c(str));
 
        sets = mail_storage_service_user_get_set(rcpt->service_user);
        lda_set = sets[1];
-       settings_var_expand(&lda_setting_parser_info, lda_set, client->pool,
-               mail_user_var_expand_table(client->state.dest_user));
+       if (settings_var_expand(&lda_setting_parser_info, lda_set, client->pool,
+                       mail_user_var_expand_table(client->state.dest_user), &error) <= 0) {
+               i_error("Failed to expand settings: %s", error);
+               client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
+                                rcpt->address);
+               return -1;
+       }
+
+       str = t_str_new(256);
+       if (var_expand_with_funcs(str, client->state.dest_user->set->mail_log_prefix,
+                                 mail_user_var_expand_table(client->state.dest_user),
+                                 mail_user_var_expand_func_table,
+                                 client->state.dest_user, &error) <= 0) {
+               i_error("Failed to expand mail_log_prefix=%s: %s",
+                       client->state.dest_user->set->mail_log_prefix, error);
+               client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
+                                rcpt->address);
+               return -1;
+       }
+       i_set_failure_prefix("%s", str_c(str));
 
        memset(&dctx, 0, sizeof(dctx));
        dctx.session = session;
index 0ad59f5676d68074a453b8a3f539a26700939a66..44377998ae0ebfc533d669d0c42b424172a563b8 100644 (file)
@@ -627,8 +627,10 @@ client_get_log_str(struct client *client, const char *msg)
                { "passdb", client_var_expand_func_passdb },
                { NULL, NULL }
        };
+       static bool expand_error_logged = FALSE;
        const struct var_expand_table *var_expand_table;
        char *const *e;
+       const char *error;
        string_t *str, *str2;
        unsigned int pos;
 
@@ -638,13 +640,22 @@ client_get_log_str(struct client *client, const char *msg)
        str2 = t_str_new(128);
        for (e = client->set->log_format_elements_split; *e != NULL; e++) {
                pos = str_len(str);
-               var_expand_with_funcs(str, *e, var_expand_table,
-                                     func_table, client);
+               if (var_expand_with_funcs(str, *e, var_expand_table,
+                                         func_table, client, &error) <= 0 &&
+                   !expand_error_logged) {
+                       i_error("Failed to expand log_format_elements=%s: %s",
+                               *e, error);
+                       expand_error_logged = TRUE;
+               }
                if (have_username_key(*e)) {
                        /* username is added even if it's empty */
                } else {
                        str_truncate(str2, 0);
-                       var_expand(str2, *e, login_var_expand_empty_tab);
+                       if (var_expand(str2, *e, login_var_expand_empty_tab,
+                                      &error) <= 0) {
+                               /* we just logged this error above. no need
+                                  to do it again. */
+                       }
                        if (strcmp(str_c(str)+pos, str_c(str2)) == 0) {
                                /* empty %variables, don't add */
                                str_truncate(str, pos);
@@ -666,7 +677,11 @@ client_get_log_str(struct client *client, const char *msg)
        };
 
        str_truncate(str, 0);
-       var_expand(str, client->set->login_log_format, tab);
+       if (var_expand(str, client->set->login_log_format, tab, &error) <= 0) {
+               i_error("Failed to expand login_log_format=%s: %s",
+                       client->set->login_log_format, error);
+               expand_error_logged = TRUE;
+       }
        return str_c(str);
 }
 
index 8cfa86a41433607133128afe8a70954aa89a070e..623ec0638803460f3905650bdbfd6f4eb8891f07 100644 (file)
@@ -920,10 +920,18 @@ login_proxy_cmd_kick_alt(struct ipc_cmd *cmd, const char *const *args)
        login_proxy_cmd_kick_full(cmd, args+1, want_kick_alt_username, i);
 }
 
-static unsigned int director_username_hash(struct client *client)
+static bool director_username_hash(struct client *client, unsigned int *hash_r)
 {
-       return mail_user_hash(client->virtual_user,
-                             client->set->director_username_hash);
+       const char *error;
+
+       if (!mail_user_hash(client->virtual_user,
+                           client->set->director_username_hash,
+                           hash_r, &error)) {
+               i_error("Failed to expand director_username_hash=%s: %s",
+                       client->set->director_username_hash, error);
+               return FALSE;
+       }
+       return TRUE;
 }
 
 static void
@@ -931,7 +939,7 @@ login_proxy_cmd_kick_director_hash(struct ipc_cmd *cmd, const char *const *args)
 {
        struct login_proxy *proxy, *next;
        struct ip_addr except_ip;
-       unsigned int hash, count = 0;
+       unsigned int hash, proxy_hash, count = 0;
 
        if (args[0] == NULL || str_to_uint(args[0], &hash) < 0) {
                ipc_cmd_fail(&cmd, "Invalid parameters");
@@ -949,7 +957,8 @@ login_proxy_cmd_kick_director_hash(struct ipc_cmd *cmd, const char *const *args)
        for (proxy = login_proxies; proxy != NULL; proxy = next) {
                next = proxy->next;
 
-               if (director_username_hash(proxy->client) == hash &&
+               if (director_username_hash(proxy->client, &proxy_hash) &&
+                   proxy_hash == hash &&
                    !net_ip_compare(&proxy->ip, &except_ip)) {
                        login_proxy_free_delayed(&proxy, KILLED_BY_DIRECTOR_REASON);
                        count++;
@@ -958,7 +967,8 @@ login_proxy_cmd_kick_director_hash(struct ipc_cmd *cmd, const char *const *args)
        for (proxy = login_proxies_pending; proxy != NULL; proxy = next) {
                next = proxy->next;
 
-               if (director_username_hash(proxy->client) == hash &&
+               if (director_username_hash(proxy->client, &proxy_hash) &&
+                   proxy_hash == hash &&
                    !net_ip_compare(&proxy->ip, &except_ip)) {
                        client_destroy(proxy->client, "Connection kicked");
                        count++;
index 089da722008f430dfbda8f70c0487fb1dfdaa281..e47fa19751ab8167ee53aa1f74bfb7b0fca1e0dd 100644 (file)
@@ -190,8 +190,9 @@ login_settings_read(pool_t pool,
        for (i = 0; i < count; i++)
                sets[i] = login_setting_dup(pool, input.roots[i], cache_sets[i]);
 
-       settings_var_expand(&login_setting_parser_info, sets[0], pool,
-                           login_set_var_expand_table(&input));
+       if (settings_var_expand(&login_setting_parser_info, sets[0], pool,
+                               login_set_var_expand_table(&input), &error) <= 0)
+               i_fatal("Failed to expand settings: %s", error);
 
        *ssl_set_r =
                login_setting_dup(pool, &master_service_ssl_setting_parser_info,
index 5790c204d12c34377282d735f644e2bafdbd6616..54c905a4e8d95f212bf21e686e361f555d2f2838 100644 (file)
@@ -38,7 +38,7 @@ acl_shared_namespace_add(struct mail_namespace *ns,
        struct mail_namespace *new_ns = ns;
        struct mailbox_list_iterate_context *iter;
        const struct mailbox_info *info;
-       const char *mailbox;
+       const char *mailbox, *error;
        string_t *str;
 
        if (strcmp(ns->user->username, userdomain) == 0) {
@@ -54,7 +54,11 @@ acl_shared_namespace_add(struct mail_namespace *ns,
        };
 
        str = t_str_new(128);
-       var_expand(str, sstorage->ns_prefix_pattern, tab);
+       if (var_expand(str, sstorage->ns_prefix_pattern, tab, &error) <= 0) {
+               i_error("Failed to expand namespace prefix %s: %s",
+                       sstorage->ns_prefix_pattern, error);
+               return;
+       }
        mailbox = str_c(str);
        if (shared_storage_get_namespace(&new_ns, &mailbox) < 0)
                return;
index 1ccd47316226096f9c962fad502ed945f15f1f46..699f444db807656770fdcb53c6f4370a87c7ea5e 100644 (file)
@@ -162,12 +162,12 @@ int dict_ldap_connect(struct ldap_dict *dict, const char **error_r)
        return ldap_client_init(&set, &dict->client, error_r);
 }
 
-static void
+static bool
 ldap_dict_build_query(struct ldap_dict *dict, const struct dict_ldap_map *map,
                       ARRAY_TYPE(const_string) *values, bool priv,
-                      string_t *query_r)
+                      string_t *query_r, const char **error_r)
 {
-       const char *template;
+       const char *template, *error;
        ARRAY(struct var_expand_table) exp;
        struct var_expand_table entry;
 
@@ -192,7 +192,11 @@ ldap_dict_build_query(struct ldap_dict *dict, const struct dict_ldap_map *map,
 
        array_append_zero(&exp);
 
-       var_expand(query_r, template, array_idx(&exp, 0));
+       if (var_expand(query_r, template, array_idx(&exp, 0), &error) <= 0) {
+               *error_r = t_strdup_printf("Failed to expand %s: %s", template, error);
+               return FALSE;
+       }
+       return TRUE;
 }
 
 static
@@ -376,6 +380,8 @@ void ldap_dict_lookup_async(struct dict *dict, const char *key,
        struct ldap_search_input input;
        struct ldap_dict *ctx = (struct ldap_dict*)dict;
        struct dict_ldap_op *op;
+       const char *error;
+
        pool_t oppool = pool_alloconly_create("ldap dict lookup", 64);
        string_t *query = str_new(oppool, 64);
        op = p_new(oppool, struct dict_ldap_op, 1);
@@ -398,7 +404,11 @@ void ldap_dict_lookup_async(struct dict *dict, const char *key,
                memset(&input, 0, sizeof(input));
                input.base_dn = map->base_dn;
                input.scope = map->scope_val;
-               ldap_dict_build_query(ctx, map, &values, strncmp(key, DICT_PATH_PRIVATE, strlen(DICT_PATH_PRIVATE))==0, query);
+               if (!ldap_dict_build_query(ctx, map, &values, strncmp(key, DICT_PATH_PRIVATE, strlen(DICT_PATH_PRIVATE))==0, query, &error)) {
+                       op->res.error = error;
+                       callback(&(op->res), context);
+                       pool_unref(&oppool);
+               }
                input.filter = str_c(query);
                input.attributes = attributes;
                input.timeout_secs = ctx->set->timeout;
index d8737fd25538f0ac84639417d62e8eb2ac4af5e9..949b973cc4df54e2659200d02e7dccdf5222cdf9 100644 (file)
@@ -553,9 +553,13 @@ static const char *client_stats(struct client *client)
                { '\0', NULL, NULL }
        };
        string_t *str;
+       const char *error;
 
        str = t_str_new(128);
-       var_expand(str, client->set->pop3_logout_format, tab);
+       if (var_expand(str, client->set->pop3_logout_format, tab, &error) <= 0) {
+               i_error("Failed to expand pop3_logout_format=%s: %s",
+                       client->set->pop3_logout_format, error);
+       }
        return str_c(str);
 }
 
index 65fb01eb3cfa9e3ecaa0c2de2f4fd9a647f8b2b1..e2149e7534663ed1f7d3531e42efa68cb27d4532 100644 (file)
@@ -639,7 +639,14 @@ pop3_get_uid(struct client *client, struct mail *mail, string_t *str,
                { 'g', guid, "guid" },
                { '\0', NULL, NULL }
        };
-       var_expand(str, client->mail_set->pop3_uidl_format, tab);
+       const char *error;
+
+       if (var_expand(str, client->mail_set->pop3_uidl_format,
+                      tab, &error) <= 0) {
+               i_error("UIDL: Failed to expand pop3_uidl_format=%s: %s",
+                       client->mail_set->pop3_uidl_format, error);
+               return -1;
+       }
        return 0;
 }