1 /* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
2 #include "lib.h"
3 #include "str.h"
4 #include "array.h"
5 #include "settings-parser.h"
6 #include "master-service.h"
7 #include "master-service-settings.h"
8 #include "mail-crypt-common.h"
9 #include "mail-crypt-key.h"
10 #include "fs-crypt-settings.h"
11 
12 static const struct fs_crypt_settings *
fs_crypt_load_settings(void)13 fs_crypt_load_settings(void)
14 {
15 	static const struct setting_parser_info *set_roots[] = {
16 		&fs_crypt_setting_parser_info,
17 		NULL
18 	};
19 	struct master_service_settings_input input;
20 	struct master_service_settings_output output;
21 	const char *error;
22 
23 	i_zero(&input);
24 	input.roots = set_roots;
25 	input.module = "fs-crypt";
26 	input.service = "fs-crypt";
27 	if (master_service_settings_read(master_service, &input,
28 					 &output, &error) < 0)
29 		i_fatal("Error reading configuration: %s", error);
30 
31 	return master_service_settings_get_others(master_service)[0];
32 }
33 
34 static
mail_crypt_plugin_getenv(const struct fs_crypt_settings * set,const char * name)35 const char *mail_crypt_plugin_getenv(const struct fs_crypt_settings *set,
36 				     const char *name)
37 {
38 	const char *const *envs;
39 	unsigned int i, count;
40 
41 	if (set == NULL)
42 		return NULL;
43 
44 	if (!array_is_created(&set->plugin_envs))
45 		return NULL;
46 
47 	envs = array_get(&set->plugin_envs, &count);
48 	for (i = 0; i < count; i += 2) {
49 		if (strcmp(envs[i], name) == 0)
50 			return envs[i+1];
51 	}
52 	return NULL;
53 }
54 
55 static int
mail_crypt_load_global_private_keys(const struct fs_crypt_settings * set,const char * set_prefix,struct mail_crypt_global_keys * global_keys,const char ** error_r)56 mail_crypt_load_global_private_keys(const struct fs_crypt_settings *set,
57 				    const char *set_prefix,
58 				    struct mail_crypt_global_keys *global_keys,
59 				    const char **error_r)
60 {
61 	string_t *set_key = t_str_new(64);
62 	str_append(set_key, set_prefix);
63 	str_append(set_key, "_private_key");
64 	size_t prefix_len = str_len(set_key);
65 
66 	unsigned int i = 1;
67 	const char *key_data;
68 	while ((key_data = mail_crypt_plugin_getenv(set, str_c(set_key))) != NULL) {
69 		const char *set_pw = t_strconcat(str_c(set_key), "_password", NULL);
70 		const char *password = mail_crypt_plugin_getenv(set, set_pw);
71 		if (mail_crypt_load_global_private_key(str_c(set_key), key_data,
72 							set_pw, password,
73 							global_keys, error_r) < 0)
74 			return -1;
75 		str_truncate(set_key, prefix_len);
76 		str_printfa(set_key, "%u", ++i);
77 	}
78 	return 0;
79 }
80 
mail_crypt_global_keys_load_pluginenv(const char * set_prefix,struct mail_crypt_global_keys * global_keys_r,const char ** error_r)81 int mail_crypt_global_keys_load_pluginenv(const char *set_prefix,
82 				struct mail_crypt_global_keys *global_keys_r,
83 				const char **error_r)
84 {
85 	const struct fs_crypt_settings *set = fs_crypt_load_settings();
86 
87 	const char *set_key = t_strconcat(set_prefix, "_public_key", NULL);
88 	const char *key_data = mail_crypt_plugin_getenv(set, set_key);
89 	int ret = 0;
90 
91 	mail_crypt_global_keys_init(global_keys_r);
92 	if (key_data != NULL) {
93 		if (mail_crypt_load_global_public_key(set_key, key_data,
94 						      global_keys_r, error_r) < 0)
95 			ret = -1;
96 	}
97 
98 	if (ret == 0 &&
99 	    mail_crypt_load_global_private_keys(set, set_prefix, global_keys_r,
100 						error_r) < 0)
101 		ret = -1;
102 
103 	if (ret != 0)
104 		mail_crypt_global_keys_free(global_keys_r);
105 	return ret;
106 }
107