1 #include "io.h"
2 #include "managesieve.h"
3 #include "managesieve_in.h"
4 #include "managesieve_out.h"
5 #include "managesieve_write.h"
6 #include "protocol_t.h"
7 #include "options.h"
8 #include "unused.h"
9 #include "perdition_globals.h"
10 #include "greeting.h"
11 
12 /**********************************************************************
13  * managesieve_capability_msg
14  * String for imap greeting
15  * pre: tls_flags: the encryption flags that have been set
16  *      tls_state: the current state of encryption for the session
17  *      tail: string to append to the message
18  * return capability message, should be freed by caller
19  *        NULL on error
20  **********************************************************************/
21 
managesieve_capability_msg(flag_t tls_flags,flag_t tls_state,const char * tail)22 char *managesieve_capability_msg(flag_t tls_flags, flag_t tls_state,
23 				 const char *tail)
24 {
25 	char *capability = NULL;;
26 	char *message = NULL;
27 
28 	capability = managesieve_capability(tls_flags, tls_state);
29 	if (!capability) {
30 		VANESSA_LOGGER_DEBUG("managesieve_capability");
31 		goto err;
32 	}
33 
34 	message = malloc(strlen(capability) + 2 +
35 			 strlen(MANAGESIEVE_OK) + 2 +
36 			 strlen(tail) + 2);
37 	if (!message) {
38 		VANESSA_LOGGER_DEBUG_ERRNO("m alloc");
39 		goto err;
40 	}
41 
42 	strcpy(message, capability);
43 	strcat(message, "\r\n" MANAGESIEVE_OK " \"");
44 	strcat(message, tail);
45 	strcat(message, "\"");
46 
47 err:
48 	free(capability);
49 	return message;
50 }
51 
52 
53 /**********************************************************************
54  * managesieve_greeting_str
55  * String for imap greeting
56  * pre: flag: Flags as per greeting.h
57  *      tls_flags: the encryption flags that have been set
58  * return greeting string
59  *        NULL on error
60  **********************************************************************/
61 
managesieve_greeting_str(flag_t flag)62 char *managesieve_greeting_str(flag_t flag)
63 {
64 	char *tail = NULL;
65 	char *message = NULL;
66 
67 	tail = greeting_str(MANAGESIEVE_GREETING, flag);
68 	if (!tail) {
69 		VANESSA_LOGGER_DEBUG("greeting_str");
70 		goto err;
71 	}
72 
73 	/* The tls_state argument to managesieve_capability() can be
74 	 * SSL_MODE_EMPTY as the capability before any tls login has
75 	 * occured is desired. Its for the greeting, before anything has
76 	 * happend.
77 	 */
78 	message = managesieve_capability_msg(opt.ssl_mode, SSL_MODE_EMPTY,
79 					     tail);
80 	if (!message) {
81 		VANESSA_LOGGER_DEBUG("managesieve_capability_msg");
82 		goto err;
83 	}
84 
85 err:
86 	free(tail);
87 	return message;
88 }
89 
90 /**********************************************************************
91  * managesieve_greeting
92  * Send a greeting to the user
93  * pre: io_t: io_t to write to
94  *	flag: Flags as per greeting.h
95  *	tls_flags: the encryption flags that have been set
96  * post: greeting is written to io
97  * return 0 on success
98  *	  -1 on error
99  **********************************************************************/
100 
managesieve_greeting(io_t * io,flag_t flag)101 int managesieve_greeting(io_t *io, flag_t flag)
102 {
103 	char *message = NULL;
104 	int status = -1;
105 
106 	message = managesieve_greeting_str(flag);
107 	if (!message) {
108 		VANESSA_LOGGER_DEBUG("greeting_str");
109 		return -1;
110 	}
111 
112 	if (managesieve_write_raw(io, message) < 0) {
113 		VANESSA_LOGGER_DEBUG("managesieve_write_raw");
114 		goto err;
115 	}
116 
117 	status = 0;
118 err:
119 	free(message);
120 	return status;
121 }
122 
123 /**********************************************************************
124  * managesieve_destroy_protocol
125  * Destroy protocol specific elements of the protocol structure
126  **********************************************************************/
127 
managesieve_destroy_protocol(protocol_t * UNUSED (protocol))128 static void managesieve_destroy_protocol(protocol_t *UNUSED(protocol))
129 {
130 	;
131 }
132 
133 /**********************************************************************
134  * managesieve_port
135  * Return the port to be used
136  * pre: port: port that has been set
137  * post: MANAGESIEVE_DEFAULT_PORT if port is PERDITION_PROTOCOL_DEPENDANT
138  *	 port otherwise
139  **********************************************************************/
140 
managesieve_port(char * port)141 static char *managesieve_port(char *port)
142 {
143 	if (strcmp(PERDITION_PROTOCOL_DEPENDANT, port))
144 		return port;
145 	if (opt.no_lookup)
146 		return MANAGESIEVE_DEFAULT_PORT_NUMBER;
147 	return MANAGESIEVE_DEFAULT_PORT_NAME;
148 }
149 
150 /**********************************************************************
151  * managesieve_encryption
152  * Return the encryption states to be used.
153  * pre: ssl_flags: the encryption flags that have been set
154  * return: ssl_flags to be used
155  **********************************************************************/
156 
managesieve_encryption(flag_t ssl_flags)157 static flag_t managesieve_encryption(flag_t ssl_flags)
158 {
159 	return ssl_flags;
160 }
161 
162 /**********************************************************************
163  * managesieve_mangle_capability
164  * Modify a capability by exchanging delimiters
165  * pre: capability: capability string that has been set
166  * return: mangled_capability suitable for sending on the wire,
167  *         caller should free this memory
168  *         NULL on error
169  **********************************************************************/
170 
managesieve_mangle_capability(const char * capability)171 static char *managesieve_mangle_capability(const char *capability)
172 {
173 	const char *start;
174 	const char *end;
175 	char *mangled_capability;
176 	size_t n_len;
177 	int count;
178 
179 	const char *old_delimiter = MANAGESIEVE_CAPA_DELIMITER;
180 	const char *new_delimiter = "\r\n";
181 
182 	const size_t old_delimiter_len = strlen(old_delimiter);
183 	const size_t new_delimiter_len = strlen(new_delimiter);
184 
185 	n_len = 0;
186 	count = 0;
187 	start = capability;
188 	while ((start = strstr(start, old_delimiter))) {
189 		start += old_delimiter_len;
190 		count++;
191 	}
192 
193 	n_len = strlen(capability) - (count * old_delimiter_len) +
194 		(count * new_delimiter_len);
195 
196 	mangled_capability = (char *)malloc(n_len + 1);
197 	if (!mangled_capability) {
198 		VANESSA_LOGGER_DEBUG_ERRNO("malloc");
199 		return NULL;
200 	}
201 	memset(mangled_capability, 0, n_len + 1);
202 
203 	end = capability;
204 	while (1) {
205 		start = end;
206 		end = strstr(start, old_delimiter);
207 		if (!end)
208 			break;
209 		strncat(mangled_capability, start, end-start);
210 		strcat(mangled_capability, new_delimiter);
211 		end += old_delimiter_len;
212 	}
213 	strncat(mangled_capability, start, end-start);
214 
215 	return mangled_capability;
216 }
217 
218 
219 /**********************************************************************
220  * managesieve_capability
221  * Return the capability string to be used.
222  * pre: tls_flags: the encryption flags that have been set
223  *	tls_state: the current state of encryption for the session
224  * return: capability to use, as per protocol_capability with
225  *	   managesieve parameters
226  *	   NULL on error
227  **********************************************************************/
228 
managesieve_capability(flag_t tls_flags,flag_t tls_state)229 char *managesieve_capability(flag_t tls_flags, flag_t tls_state)
230 {
231 	flag_t mode;
232 	char *capability;
233 	char *old_capability;
234 
235 	if ((tls_flags & SSL_MODE_TLS_LISTEN) &&
236 	    !(tls_state & SSL_MODE_TLS_LISTEN))
237 		mode = PROTOCOL_C_ADD;
238 	else
239 		mode = PROTOCOL_C_DEL;
240 
241 	capability = protocol_capability(mode, opt.managesieve_capability,
242 					MANAGESIEVE_CAPA_STARTTLS,
243 					MANAGESIEVE_CAPA_DELIMITER);
244 	if (!capability) {
245 		VANESSA_LOGGER_DEBUG("protocol_capability");
246 		return NULL;
247 	}
248 
249 	old_capability = capability;
250 	capability = managesieve_mangle_capability(old_capability);
251 	free(old_capability);
252 	if (!capability) {
253 		VANESSA_LOGGER_DEBUG("managesieve_mangle_capability");
254 		return NULL;
255 	}
256 
257 	return capability;
258 }
259 
managesieve_protocol_bye(io_t * io,const char * msg)260 static int managesieve_protocol_bye(io_t *io, const char *msg)
261 {
262 	return managesieve_bye(io, NULL, msg);
263 }
264 
265 /**********************************************************************
266  * managesieve_initialise_protocol
267  * Initialise the protocol structure for the managesieve protocol
268  * pre: protocol: pointer to an allocated protocol structure
269  * return: seeded protocol structure
270  *	   NULL on error
271  **********************************************************************/
272 
273 static char *managesieve_type[] = { MANAGESIEVE_OK, MANAGESIEVE_NO,
274 				    MANAGESIEVE_BYE };
275 
managesieve_initialise_protocol(protocol_t * protocol)276 protocol_t *managesieve_initialise_protocol(protocol_t *protocol)
277 {
278 	protocol->type = managesieve_type;
279 	protocol->write_str = managesieve_write_str;
280 	protocol->greeting = managesieve_greeting;
281 	protocol->quit_string = MANAGESIEVE_QUIT;
282 	protocol->bye = managesieve_protocol_bye;
283 	protocol->in_get_auth = managesieve_in_get_auth;
284 #ifdef WITH_PAM_SUPPORT
285 	protocol->in_authenticate = managesieve_in_authenticate;
286 #else
287 	protocol->in_authenticate = NULL;
288 #endif
289 	protocol->out_setup = managesieve_out_setup;
290 	protocol->out_authenticate = managesieve_out_authenticate;
291 	protocol->out_response = managesieve_out_response;
292 	protocol->destroy = managesieve_destroy_protocol;
293 	protocol->port = managesieve_port;
294 	protocol->encryption = managesieve_encryption;
295 
296 	return protocol;
297 }
298