1 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "auth-common.h"
4 
5 #include "array.h"
6 #include "istream.h"
7 #include "str.h"
8 #include "json-parser.h"
9 #include "settings.h"
10 #include "dict.h"
11 #include "auth-request.h"
12 #include "auth-worker-client.h"
13 #include "db-dict.h"
14 
15 #include <stddef.h>
16 
17 enum dict_settings_section {
18 	DICT_SETTINGS_SECTION_ROOT = 0,
19 	DICT_SETTINGS_SECTION_KEY,
20 	DICT_SETTINGS_SECTION_PASSDB,
21 	DICT_SETTINGS_SECTION_USERDB
22 };
23 
24 struct dict_settings_parser_ctx {
25 	struct dict_connection *conn;
26 	enum dict_settings_section section;
27 	struct db_dict_key *cur_key;
28 };
29 
30 struct db_dict_iter_key {
31 	const struct db_dict_key *key;
32 	bool used;
33 	const char *value;
34 };
35 
36 struct db_dict_value_iter {
37 	pool_t pool;
38 	struct auth_request *auth_request;
39 	struct dict_connection *conn;
40 	const struct var_expand_table *var_expand_table;
41 	ARRAY(struct db_dict_iter_key) keys;
42 
43 	const ARRAY_TYPE(db_dict_field) *fields;
44 	const ARRAY_TYPE(db_dict_key_p) *objects;
45 	unsigned int field_idx;
46 	unsigned int object_idx;
47 
48 	struct json_parser *json_parser;
49 	string_t *tmpstr;
50 	const char *error;
51 };
52 
53 #define DEF_STR(name) DEF_STRUCT_STR(name, db_dict_settings)
54 #define DEF_BOOL(name) DEF_STRUCT_BOOL(name, db_dict_settings)
55 static struct setting_def setting_defs[] = {
56 	DEF_STR(uri),
57 	DEF_STR(default_pass_scheme),
58  	DEF_STR(iterate_prefix),
59  	DEF_BOOL(iterate_disable),
60 
61  	DEF_STR(passdb_objects),
62  	DEF_STR(userdb_objects),
63 	{ 0, NULL, 0 }
64 };
65 
66 static struct db_dict_settings default_dict_settings = {
67 	.uri = NULL,
68 	.default_pass_scheme = "MD5",
69 	.iterate_prefix = "",
70 	.iterate_disable = FALSE,
71 	.passdb_objects = "",
72 	.userdb_objects = ""
73 };
74 
75 #undef DEF_STR
76 #define DEF_STR(name) DEF_STRUCT_STR(name, db_dict_key)
77 static struct setting_def key_setting_defs[] = {
78 	DEF_STR(name),
79 	DEF_STR(key),
80 	DEF_STR(format),
81  	DEF_STR(default_value),
82 
83 	{ 0, NULL, 0 }
84 };
85 
86 static struct db_dict_key default_key_settings = {
87 	.name = NULL,
88 	.key = "",
89 	.format = "value",
90 	.default_value = NULL
91 };
92 
93 static struct dict_connection *connections = NULL;
94 
dict_conn_find(const char * config_path)95 static struct dict_connection *dict_conn_find(const char *config_path)
96 {
97 	struct dict_connection *conn;
98 
99 	for (conn = connections; conn != NULL; conn = conn->next) {
100 		if (strcmp(conn->config_path, config_path) == 0)
101 			return conn;
102 	}
103 
104 	return NULL;
105 }
106 
107 static bool
parse_obsolete_setting(const char * key,const char * value,struct dict_settings_parser_ctx * ctx,const char ** error_r)108 parse_obsolete_setting(const char *key, const char *value,
109 		       struct dict_settings_parser_ctx *ctx,
110 		       const char **error_r)
111 {
112 	const struct db_dict_key *dbkey;
113 
114 	if (strcmp(key, "password_key") == 0) {
115 		/* key passdb { key=<value> format=json }
116 		   passdb_objects = passdb */
117 		ctx->cur_key = array_append_space(&ctx->conn->set.keys);
118 		*ctx->cur_key = default_key_settings;
119 		ctx->cur_key->name = "passdb";
120 		ctx->cur_key->format = "json";
121 		ctx->cur_key->parsed_format = DB_DICT_VALUE_FORMAT_JSON;
122 		ctx->cur_key->key = p_strdup(ctx->conn->pool, value);
123 
124 		dbkey = ctx->cur_key;
125 		array_push_back(&ctx->conn->set.parsed_passdb_objects, &dbkey);
126 		return TRUE;
127 	}
128 	if (strcmp(key, "user_key") == 0) {
129 		/* key userdb { key=<value> format=json }
130 		   userdb_objects = userdb */
131 		ctx->cur_key = array_append_space(&ctx->conn->set.keys);
132 		*ctx->cur_key = default_key_settings;
133 		ctx->cur_key->name = "userdb";
134 		ctx->cur_key->format = "json";
135 		ctx->cur_key->parsed_format = DB_DICT_VALUE_FORMAT_JSON;
136 		ctx->cur_key->key = p_strdup(ctx->conn->pool, value);
137 
138 		dbkey = ctx->cur_key;
139 		array_push_back(&ctx->conn->set.parsed_userdb_objects, &dbkey);
140 		return TRUE;
141 	}
142 	if (strcmp(key, "value_format") == 0) {
143 		if (strcmp(value, "json") == 0)
144 			return TRUE;
145 		*error_r = "Deprecated value_format must be 'json'";
146 		return FALSE;
147 	}
148 	return FALSE;
149 }
150 
parse_setting(const char * key,const char * value,struct dict_settings_parser_ctx * ctx)151 static const char *parse_setting(const char *key, const char *value,
152 				 struct dict_settings_parser_ctx *ctx)
153 {
154 	struct db_dict_field *field;
155 	const char *error = NULL;
156 
157 	switch (ctx->section) {
158 	case DICT_SETTINGS_SECTION_ROOT:
159 		if (parse_obsolete_setting(key, value, ctx, &error))
160 			return NULL;
161 		if (error != NULL)
162 			return error;
163 		return parse_setting_from_defs(ctx->conn->pool, setting_defs,
164 					       &ctx->conn->set, key, value);
165 	case DICT_SETTINGS_SECTION_KEY:
166 		return parse_setting_from_defs(ctx->conn->pool, key_setting_defs,
167 					       ctx->cur_key, key, value);
168 	case DICT_SETTINGS_SECTION_PASSDB:
169 		field = array_append_space(&ctx->conn->set.passdb_fields);
170 		field->name = p_strdup(ctx->conn->pool, key);
171 		field->value = p_strdup(ctx->conn->pool, value);
172 		return NULL;
173 	case DICT_SETTINGS_SECTION_USERDB:
174 		field = array_append_space(&ctx->conn->set.userdb_fields);
175 		field->name = p_strdup(ctx->conn->pool, key);
176 		field->value = p_strdup(ctx->conn->pool, value);
177 		return NULL;
178 	}
179 	i_unreached();
180 }
181 
parse_section(const char * type,const char * name,struct dict_settings_parser_ctx * ctx,const char ** errormsg)182 static bool parse_section(const char *type, const char *name,
183 			  struct dict_settings_parser_ctx *ctx,
184 			  const char **errormsg)
185 {
186 	if (type == NULL) {
187 		ctx->section = DICT_SETTINGS_SECTION_ROOT;
188 		if (ctx->cur_key != NULL) {
189 			if (strcmp(ctx->cur_key->format, "value") == 0) {
190 				ctx->cur_key->parsed_format =
191 					DB_DICT_VALUE_FORMAT_VALUE;
192 			} else if (strcmp(ctx->cur_key->format, "json") == 0) {
193 				ctx->cur_key->parsed_format =
194 					DB_DICT_VALUE_FORMAT_JSON;
195 			} else {
196 				*errormsg = t_strconcat("Unknown key format: ",
197 					ctx->cur_key->format, NULL);
198 				return FALSE;
199 			}
200 		}
201 		ctx->cur_key = NULL;
202 		return TRUE;
203 	}
204 	if (ctx->section != DICT_SETTINGS_SECTION_ROOT) {
205 		*errormsg = "Nested sections not supported";
206 		return FALSE;
207 	}
208 	if (strcmp(type, "key") == 0) {
209 		if (name == NULL) {
210 			*errormsg = "Key section is missing name";
211 			return FALSE;
212 		}
213 		if (strchr(name, '.') != NULL) {
214 			*errormsg = "Key section names must not contain '.'";
215 			return FALSE;
216 		}
217 		ctx->section = DICT_SETTINGS_SECTION_KEY;
218 		ctx->cur_key = array_append_space(&ctx->conn->set.keys);
219 		*ctx->cur_key = default_key_settings;
220 		ctx->cur_key->name = p_strdup(ctx->conn->pool, name);
221 		return TRUE;
222 	}
223 	if (strcmp(type, "passdb_fields") == 0) {
224 		ctx->section = DICT_SETTINGS_SECTION_PASSDB;
225 		return TRUE;
226 	}
227 	if (strcmp(type, "userdb_fields") == 0) {
228 		ctx->section = DICT_SETTINGS_SECTION_USERDB;
229 		return TRUE;
230 	}
231 	*errormsg = "Unknown section";
232 	return FALSE;
233 }
234 
235 static void
db_dict_settings_parse(struct db_dict_settings * set)236 db_dict_settings_parse(struct db_dict_settings *set)
237 {
238 	const struct db_dict_key *key;
239 	const char *const *tmp;
240 
241 	tmp = t_strsplit_spaces(set->passdb_objects, " ");
242 	for (; *tmp != NULL; tmp++) {
243 		key = db_dict_set_key_find(&set->keys, *tmp);
244 		if (key == NULL) {
245 			i_fatal("dict: passdb_objects refers to key %s, "
246 				"which doesn't exist", *tmp);
247 		}
248 		if (key->parsed_format == DB_DICT_VALUE_FORMAT_VALUE) {
249 			i_fatal("dict: passdb_objects refers to key %s, "
250 				"but it's in value-only format", *tmp);
251 		}
252 		array_push_back(&set->parsed_passdb_objects, &key);
253 	}
254 
255 	tmp = t_strsplit_spaces(set->userdb_objects, " ");
256 	for (; *tmp != NULL; tmp++) {
257 		key = db_dict_set_key_find(&set->keys, *tmp);
258 		if (key == NULL) {
259 			i_fatal("dict: userdb_objects refers to key %s, "
260 				"which doesn't exist", *tmp);
261 		}
262 		if (key->parsed_format == DB_DICT_VALUE_FORMAT_VALUE) {
263 			i_fatal("dict: userdb_objects refers to key %s, "
264 				"but it's in value-only format", *tmp);
265 		}
266 		array_push_back(&set->parsed_userdb_objects, &key);
267 	}
268 }
269 
db_dict_init(const char * config_path)270 struct dict_connection *db_dict_init(const char *config_path)
271 {
272 	struct dict_settings dict_set;
273 	struct dict_settings_parser_ctx ctx;
274 	struct dict_connection *conn;
275 	const char *error;
276 	pool_t pool;
277 
278 	conn = dict_conn_find(config_path);
279 	if (conn != NULL) {
280 		conn->refcount++;
281 		return conn;
282 	}
283 
284 	if (*config_path == '\0')
285 		i_fatal("dict: Configuration file path not given");
286 
287 	pool = pool_alloconly_create("dict_connection", 1024);
288 	conn = p_new(pool, struct dict_connection, 1);
289 	conn->pool = pool;
290 
291 	conn->refcount = 1;
292 
293 	conn->config_path = p_strdup(pool, config_path);
294 	conn->set = default_dict_settings;
295 	p_array_init(&conn->set.keys, pool, 8);
296 	p_array_init(&conn->set.passdb_fields, pool, 8);
297 	p_array_init(&conn->set.userdb_fields, pool, 8);
298 	p_array_init(&conn->set.parsed_passdb_objects, pool, 2);
299 	p_array_init(&conn->set.parsed_userdb_objects, pool, 2);
300 
301 	i_zero(&ctx);
302 	ctx.conn = conn;
303 	if (!settings_read(config_path, NULL, parse_setting,
304 			   parse_section, &ctx, &error))
305 		i_fatal("dict %s: %s", config_path, error);
306 	db_dict_settings_parse(&conn->set);
307 
308 	if (conn->set.uri == NULL)
309 		i_fatal("dict %s: Empty uri setting", config_path);
310 
311 	i_zero(&dict_set);
312 	dict_set.base_dir = global_auth_settings->base_dir;
313 	dict_set.event_parent = auth_event;
314 	if (dict_init(conn->set.uri, &dict_set, &conn->dict, &error) < 0)
315 		i_fatal("dict %s: Failed to init dict: %s", config_path, error);
316 
317 	conn->next = connections;
318 	connections = conn;
319 	return conn;
320 }
321 
db_dict_unref(struct dict_connection ** _conn)322 void db_dict_unref(struct dict_connection **_conn)
323 {
324 	struct dict_connection *conn = *_conn;
325 
326 	*_conn = NULL;
327 	if (--conn->refcount > 0)
328 		return;
329 
330 	dict_deinit(&conn->dict);
331 	pool_unref(&conn->pool);
332 }
333 
334 static struct db_dict_iter_key *
db_dict_iter_find_key(struct db_dict_value_iter * iter,const char * name)335 db_dict_iter_find_key(struct db_dict_value_iter *iter, const char *name)
336 {
337 	struct db_dict_iter_key *key;
338 
339 	array_foreach_modifiable(&iter->keys, key) {
340 		if (strcmp(key->key->name, name) == 0)
341 			return key;
342 	}
343 	return NULL;
344 }
345 
db_dict_iter_find_used_keys(struct db_dict_value_iter * iter)346 static void db_dict_iter_find_used_keys(struct db_dict_value_iter *iter)
347 {
348 	const struct db_dict_field *field;
349 	struct db_dict_iter_key *key;
350 	const char *p, *name;
351 	unsigned int idx, size;
352 
353 	array_foreach(iter->fields, field) {
354 		for (p = field->value; *p != '\0'; ) {
355 			if (*p != '%') {
356 				p++;
357 				continue;
358 			}
359 
360 			var_get_key_range(++p, &idx, &size);
361 			if (size == 0) {
362 				/* broken %variable ending too early */
363 				break;
364 			}
365 			p += idx;
366 			if (size > 5 && memcmp(p, "dict:", 5) == 0) {
367 				name = t_strcut(t_strndup(p+5, size-5), ':');
368 				key = db_dict_iter_find_key(iter, name);
369 				if (key != NULL)
370 					key->used = TRUE;
371 			}
372 			p += size;
373 		}
374 	}
375 }
376 
db_dict_iter_find_used_objects(struct db_dict_value_iter * iter)377 static void db_dict_iter_find_used_objects(struct db_dict_value_iter *iter)
378 {
379 	const struct db_dict_key *dict_key;
380 	struct db_dict_iter_key *key;
381 
382 	array_foreach_elem(iter->objects, dict_key) {
383 		key = db_dict_iter_find_key(iter, dict_key->name);
384 		i_assert(key != NULL); /* checked at init */
385 		i_assert(key->key->parsed_format != DB_DICT_VALUE_FORMAT_VALUE);
386 		key->used = TRUE;
387 	}
388 }
389 
390 static int
db_dict_iter_key_cmp(const struct db_dict_iter_key * k1,const struct db_dict_iter_key * k2)391 db_dict_iter_key_cmp(const struct db_dict_iter_key *k1,
392 		     const struct db_dict_iter_key *k2)
393 {
394 	return null_strcmp(k1->key->default_value, k2->key->default_value);
395 }
396 
db_dict_iter_lookup_key_values(struct db_dict_value_iter * iter)397 static int db_dict_iter_lookup_key_values(struct db_dict_value_iter *iter)
398 {
399 	struct db_dict_iter_key *key;
400 	string_t *path;
401 	const char *error;
402 	int ret;
403 
404 	/* sort the keys so that we'll first lookup the keys without
405 	   default value. if their lookup fails, the user doesn't exist. */
406 	array_sort(&iter->keys, db_dict_iter_key_cmp);
407 
408 	path = t_str_new(128);
409 	str_append(path, DICT_PATH_SHARED);
410 
411 	struct dict_op_settings set = {
412 		.username = iter->auth_request->fields.user,
413 	};
414 
415 	array_foreach_modifiable(&iter->keys, key) {
416 		if (!key->used)
417 			continue;
418 
419 		str_truncate(path, strlen(DICT_PATH_SHARED));
420 		str_append(path, key->key->key);
421 		ret = dict_lookup(iter->conn->dict, &set, iter->pool,
422 				  str_c(path), &key->value, &error);
423 		if (ret > 0) {
424 			e_debug(authdb_event(iter->auth_request),
425 				"Lookup: %s = %s", str_c(path),
426 				key->value);
427 		} else if (ret < 0) {
428 			e_error(authdb_event(iter->auth_request),
429 				"Failed to lookup key %s: %s", str_c(path), error);
430 			return -1;
431 		} else if (key->key->default_value != NULL) {
432 			e_debug(authdb_event(iter->auth_request),
433 				"Lookup: %s not found, using default value %s",
434 				str_c(path), key->key->default_value);
435 			key->value = key->key->default_value;
436 		} else {
437 			return 0;
438 		}
439 	}
440 	return 1;
441 }
442 
db_dict_value_iter_init(struct dict_connection * conn,struct auth_request * auth_request,const ARRAY_TYPE (db_dict_field)* fields,const ARRAY_TYPE (db_dict_key_p)* objects,struct db_dict_value_iter ** iter_r)443 int db_dict_value_iter_init(struct dict_connection *conn,
444 			    struct auth_request *auth_request,
445 			    const ARRAY_TYPE(db_dict_field) *fields,
446 			    const ARRAY_TYPE(db_dict_key_p) *objects,
447 			    struct db_dict_value_iter **iter_r)
448 {
449 	struct db_dict_value_iter *iter;
450 	struct db_dict_iter_key *iterkey;
451 	const struct db_dict_key *key;
452 	pool_t pool;
453 	int ret;
454 
455 	pool = pool_alloconly_create(MEMPOOL_GROWING"auth dict lookup", 1024);
456 	iter = p_new(pool, struct db_dict_value_iter, 1);
457 	iter->pool = pool;
458 	iter->conn = conn;
459 	iter->fields = fields;
460 	iter->objects = objects;
461 	iter->tmpstr = str_new(pool, 128);
462 	iter->auth_request = auth_request;
463 	iter->var_expand_table = auth_request_get_var_expand_table(auth_request, NULL);
464 
465 	/* figure out what keys we need to lookup, and lookup them */
466 	p_array_init(&iter->keys, pool, array_count(&conn->set.keys));
467 	array_foreach(&conn->set.keys, key) {
468 		iterkey = array_append_space(&iter->keys);
469 		struct db_dict_key *new_key = p_new(iter->pool, struct db_dict_key, 1);
470 		memcpy(new_key, key, sizeof(struct db_dict_key));
471 		string_t *expanded_key = str_new(iter->pool, strlen(key->key));
472 		const char *error;
473 		if (auth_request_var_expand_with_table(expanded_key, key->key, auth_request,
474 						       iter->var_expand_table,
475 						       NULL, &error) <= 0) {
476 			e_error(authdb_event(iter->auth_request),
477 				"Failed to expand key %s: %s", key->key, error);
478 			pool_unref(&pool);
479 			return -1;
480 		}
481 		new_key->key = str_c(expanded_key);
482 		iterkey->key = new_key;
483 	}
484 	T_BEGIN {
485 		db_dict_iter_find_used_keys(iter);
486 		db_dict_iter_find_used_objects(iter);
487 		ret = db_dict_iter_lookup_key_values(iter);
488 	} T_END;
489 	if (ret <= 0) {
490 		pool_unref(&pool);
491 		return ret;
492 	}
493 	*iter_r = iter;
494 	return 1;
495 }
496 
497 static bool
db_dict_value_iter_json_next(struct db_dict_value_iter * iter,string_t * tmpstr,const char ** key_r,const char ** value_r)498 db_dict_value_iter_json_next(struct db_dict_value_iter *iter,
499 			     string_t *tmpstr,
500 			     const char **key_r, const char **value_r)
501 {
502 	enum json_type type;
503 	const char *value;
504 
505 	if (json_parse_next(iter->json_parser, &type, &value) < 0)
506 		return FALSE;
507 	if (type != JSON_TYPE_OBJECT_KEY) {
508 		iter->error = "Object expected";
509 		return FALSE;
510 	}
511 	if (*value == '\0') {
512 		iter->error = "Empty object key";
513 		return FALSE;
514 	}
515 	str_truncate(tmpstr, 0);
516 	str_append(tmpstr, value);
517 
518 	if (json_parse_next(iter->json_parser, &type, &value) < 0) {
519 		iter->error = "Missing value";
520 		return FALSE;
521 	}
522 	if (type == JSON_TYPE_OBJECT) {
523 		iter->error = "Nested objects not supported";
524 		return FALSE;
525 	}
526 	*key_r = str_c(tmpstr);
527 	*value_r = value;
528 	return TRUE;
529 }
530 
531 static void
db_dict_value_iter_json_init(struct db_dict_value_iter * iter,const char * data)532 db_dict_value_iter_json_init(struct db_dict_value_iter *iter, const char *data)
533 {
534 	struct istream *input;
535 
536 	i_assert(iter->json_parser == NULL);
537 
538 	input = i_stream_create_from_data(data, strlen(data));
539 	iter->json_parser = json_parser_init(input);
540 	i_stream_unref(&input);
541 }
542 
543 static bool
db_dict_value_iter_object_next(struct db_dict_value_iter * iter,const char ** key_r,const char ** value_r)544 db_dict_value_iter_object_next(struct db_dict_value_iter *iter,
545 			       const char **key_r, const char **value_r)
546 {
547 	const struct db_dict_key *dict_key;
548 	struct db_dict_iter_key *key;
549 
550 	if (iter->json_parser != NULL)
551 		return db_dict_value_iter_json_next(iter, iter->tmpstr, key_r, value_r);
552 	if (iter->object_idx == array_count(iter->objects))
553 		return FALSE;
554 
555 	dict_key = array_idx_elem(iter->objects, iter->object_idx);
556 	key = db_dict_iter_find_key(iter, dict_key->name);
557 	i_assert(key != NULL); /* checked at init */
558 
559 	switch (key->key->parsed_format) {
560 	case DB_DICT_VALUE_FORMAT_VALUE:
561 		i_unreached();
562 	case DB_DICT_VALUE_FORMAT_JSON:
563 		db_dict_value_iter_json_init(iter, key->value);
564 		return db_dict_value_iter_json_next(iter, iter->tmpstr, key_r, value_r);
565 	}
566 	i_unreached();
567 }
568 
569 static int
db_dict_field_find(const char * data,void * context,const char ** value_r,const char ** error_r ATTR_UNUSED)570 db_dict_field_find(const char *data, void *context,
571 		   const char **value_r,
572 		   const char **error_r ATTR_UNUSED)
573 {
574 	struct db_dict_value_iter *iter = context;
575 	struct db_dict_iter_key *key;
576 	const char *name, *value, *dotname = strchr(data, '.');
577 	string_t *tmpstr;
578 
579 	*value_r = NULL;
580 
581 	if (dotname != NULL)
582 		data = t_strdup_until(data, dotname++);
583 	key = db_dict_iter_find_key(iter, data);
584 	if (key == NULL)
585 		return 1;
586 
587 	switch (key->key->parsed_format) {
588 	case DB_DICT_VALUE_FORMAT_VALUE:
589 		*value_r = dotname != NULL ? NULL :
590 			(key->value == NULL ? "" : key->value);
591 		return 1;
592 	case DB_DICT_VALUE_FORMAT_JSON:
593 		if (dotname == NULL)
594 			return 1;
595 		db_dict_value_iter_json_init(iter, key->value);
596 		*value_r = "";
597 		tmpstr = t_str_new(64);
598 		while (db_dict_value_iter_json_next(iter, tmpstr, &name, &value)) {
599 			if (strcmp(name, dotname) == 0) {
600 				*value_r = t_strdup(value);
601 				break;
602 			}
603 		}
604 		(void)json_parser_deinit(&iter->json_parser, &iter->error);
605 		return 1;
606 	}
607 	i_unreached();
608 }
609 
db_dict_value_iter_next(struct db_dict_value_iter * iter,const char ** key_r,const char ** value_r)610 bool db_dict_value_iter_next(struct db_dict_value_iter *iter,
611 			     const char **key_r, const char **value_r)
612 {
613 	static struct var_expand_func_table var_funcs_table[] = {
614 		{ "dict", db_dict_field_find },
615 		{ NULL, NULL }
616 	};
617 	const struct db_dict_field *field;
618 	const char *error;
619 
620 	if (iter->field_idx == array_count(iter->fields))
621 		return db_dict_value_iter_object_next(iter, key_r, value_r);
622 	field = array_idx(iter->fields, iter->field_idx++);
623 
624 	str_truncate(iter->tmpstr, 0);
625 	if (var_expand_with_funcs(iter->tmpstr, field->value,
626 				  iter->var_expand_table, var_funcs_table,
627 				  iter, &error) <= 0) {
628 		iter->error = p_strdup_printf(iter->pool,
629 			"Failed to expand %s=%s: %s",
630 			field->name, field->value, error);
631 		return FALSE;
632 	}
633 	*key_r = field->name;
634 	*value_r = str_c(iter->tmpstr);
635 	return TRUE;
636 }
637 
db_dict_value_iter_deinit(struct db_dict_value_iter ** _iter,const char ** error_r)638 int db_dict_value_iter_deinit(struct db_dict_value_iter **_iter,
639 			      const char **error_r)
640 {
641 	struct db_dict_value_iter *iter = *_iter;
642 
643 	*_iter = NULL;
644 
645 	*error_r = iter->error;
646 	if (iter->json_parser != NULL) {
647 		if (json_parser_deinit(&iter->json_parser, &iter->error) < 0 &&
648 		    *error_r == NULL)
649 			*error_r = iter->error;
650 	}
651 
652 	pool_unref(&iter->pool);
653 	return *error_r != NULL ? -1 : 0;
654 }
655