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