1 /* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "settings-parser.h"
5 #include "mail-storage-settings.h"
6 #include "imapc-settings.h"
7 
8 #include <stddef.h>
9 
10 #undef DEF
11 #define DEF(type, name) \
12 	SETTING_DEFINE_STRUCT_##type(#name, name, struct imapc_settings)
13 
14 static bool imapc_settings_check(void *_set, pool_t pool, const char **error_r);
15 
16 static const struct setting_define imapc_setting_defines[] = {
17 	DEF(STR, imapc_host),
18 	DEF(IN_PORT, imapc_port),
19 
20 	DEF(STR_VARS, imapc_user),
21 	DEF(STR_VARS, imapc_master_user),
22 	DEF(STR, imapc_password),
23 	DEF(STR, imapc_sasl_mechanisms),
24 
25 	DEF(ENUM, imapc_ssl),
26 	DEF(BOOL, imapc_ssl_verify),
27 
28 	DEF(STR, imapc_features),
29 	DEF(STR, imapc_rawlog_dir),
30 	DEF(STR, imapc_list_prefix),
31 	DEF(TIME, imapc_cmd_timeout),
32 	DEF(TIME, imapc_max_idle_time),
33 	DEF(UINT, imapc_connection_retry_count),
34 	DEF(TIME_MSECS, imapc_connection_retry_interval),
35 	DEF(SIZE, imapc_max_line_length),
36 
37 	DEF(STR, pop3_deleted_flag),
38 
39 	SETTING_DEFINE_LIST_END
40 };
41 
42 static const struct imapc_settings imapc_default_settings = {
43 	.imapc_host = "",
44 	.imapc_port = 143,
45 
46 	.imapc_user = "",
47 	.imapc_master_user = "",
48 	.imapc_password = "",
49 	.imapc_sasl_mechanisms = "",
50 
51 	.imapc_ssl = "no:imaps:starttls",
52 	.imapc_ssl_verify = TRUE,
53 
54 	.imapc_features = "",
55 	.imapc_rawlog_dir = "",
56 	.imapc_list_prefix = "",
57 	.imapc_cmd_timeout = 5*60,
58 	.imapc_max_idle_time = 60*29,
59 	.imapc_connection_retry_count = 1,
60 	.imapc_connection_retry_interval = 1000,
61 	.imapc_max_line_length = 0,
62 
63 	.pop3_deleted_flag = ""
64 };
65 
66 static const struct setting_parser_info imapc_setting_parser_info = {
67 	.module_name = "imapc",
68 	.defines = imapc_setting_defines,
69 	.defaults = &imapc_default_settings,
70 
71 	.type_offset = SIZE_MAX,
72 	.struct_size = sizeof(struct imapc_settings),
73 
74 	.parent_offset = SIZE_MAX,
75 	.parent = &mail_user_setting_parser_info,
76 
77 	.check_func = imapc_settings_check
78 };
79 
imapc_get_setting_parser_info(void)80 const struct setting_parser_info *imapc_get_setting_parser_info(void)
81 {
82 	return &imapc_setting_parser_info;
83 }
84 
85 /* <settings checks> */
86 struct imapc_feature_list {
87 	const char *name;
88 	enum imapc_features num;
89 };
90 
91 static const struct imapc_feature_list imapc_feature_list[] = {
92 	{ "rfc822.size", IMAPC_FEATURE_RFC822_SIZE },
93 	{ "guid-forced", IMAPC_FEATURE_GUID_FORCED },
94 	{ "fetch-headers", IMAPC_FEATURE_FETCH_HEADERS },
95 	{ "gmail-migration", IMAPC_FEATURE_GMAIL_MIGRATION },
96 	{ "search", IMAPC_FEATURE_SEARCH },
97 	{ "zimbra-workarounds", IMAPC_FEATURE_ZIMBRA_WORKAROUNDS },
98 	{ "no-examine", IMAPC_FEATURE_NO_EXAMINE },
99 	{ "proxyauth", IMAPC_FEATURE_PROXYAUTH },
100 	{ "fetch-msn-workarounds", IMAPC_FEATURE_FETCH_MSN_WORKAROUNDS },
101 	{ "fetch-fix-broken-mails", IMAPC_FEATURE_FETCH_FIX_BROKEN_MAILS },
102 	{ "modseq", IMAPC_FEATURE_MODSEQ },
103 	{ "delay-login", IMAPC_FEATURE_DELAY_LOGIN },
104 	{ "fetch-bodystructure", IMAPC_FEATURE_FETCH_BODYSTRUCTURE },
105 	{ "send-id", IMAPC_FEATURE_SEND_ID },
106 	{ "fetch-empty-is-expunged", IMAPC_FEATURE_FETCH_EMPTY_IS_EXPUNGED },
107 	{ "no-msn-updates", IMAPC_FEATURE_NO_MSN_UPDATES },
108 	{ "acl", IMAPC_FEATURE_ACL },
109 	{ NULL, 0 }
110 };
111 
112 static int
imapc_settings_parse_throttle(struct imapc_settings * set,const char * throttle_str,const char ** error_r)113 imapc_settings_parse_throttle(struct imapc_settings *set,
114 			      const char *throttle_str, const char **error_r)
115 {
116 	const char *const *tmp;
117 
118 	tmp = t_strsplit(throttle_str, ":");
119 	if (str_array_length(tmp) != 3 ||
120 	    str_to_uint(tmp[0], &set->throttle_init_msecs) < 0 ||
121 	    str_to_uint(tmp[1], &set->throttle_max_msecs) < 0 ||
122 	    str_to_uint(tmp[2], &set->throttle_shrink_min_msecs) < 0) {
123 		*error_r = "imapc_features: Invalid throttle settings";
124 		return -1;
125 	}
126 	return 0;
127 }
128 
129 static int
imapc_settings_parse_features(struct imapc_settings * set,const char ** error_r)130 imapc_settings_parse_features(struct imapc_settings *set,
131 			      const char **error_r)
132 {
133         enum imapc_features features = 0;
134         const struct imapc_feature_list *list;
135 	const char *const *str;
136 
137         str = t_strsplit_spaces(set->imapc_features, " ,");
138 	for (; *str != NULL; str++) {
139 		list = imapc_feature_list;
140 		for (; list->name != NULL; list++) {
141 			if (strcasecmp(*str, list->name) == 0) {
142 				features |= list->num;
143 				break;
144 			}
145 		}
146 		if (strncasecmp(*str, "throttle:", 9) == 0) {
147 			if (imapc_settings_parse_throttle(set, *str + 9, error_r) < 0)
148 				return -1;
149 			continue;
150 		}
151 		if (list->name == NULL) {
152 			*error_r = t_strdup_printf("imapc_features: "
153 				"Unknown feature: %s", *str);
154 			return -1;
155 		}
156 	}
157 	set->parsed_features = features;
158 	return 0;
159 }
160 
imapc_settings_check(void * _set,pool_t pool ATTR_UNUSED,const char ** error_r)161 static bool imapc_settings_check(void *_set, pool_t pool ATTR_UNUSED,
162 				 const char **error_r)
163 {
164 	struct imapc_settings *set = _set;
165 
166 	if (set->imapc_max_idle_time == 0) {
167 		*error_r = "imapc_max_idle_time must not be 0";
168 		return FALSE;
169 	}
170 	if (imapc_settings_parse_features(set, error_r) < 0)
171 		return FALSE;
172 	return TRUE;
173 }
174