1 /*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * $Id: imapstorage.c,v 1.19 2008/02/17 13:13:26 hoa Exp $
34 */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include "imapstorage.h"
41
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "mail.h"
46 #include "imapdriver.h"
47 #include "imapdriver_cached.h"
48 #include "mailstorage_tools.h"
49 #include "maildriver.h"
50
51 /* imap storage */
52
53 #define IMAP_DEFAULT_PORT 143
54 #define IMAPS_DEFAULT_PORT 993
55
56 static int imap_mailstorage_connect(struct mailstorage * storage);
57 static int
58 imap_mailstorage_get_folder_session(struct mailstorage * storage,
59 char * pathname, mailsession ** result);
60 static void imap_mailstorage_uninitialize(struct mailstorage * storage);
61
62 static mailstorage_driver imap_mailstorage_driver = {
63 /* sto_name */ "imap",
64 /* sto_connect */ imap_mailstorage_connect,
65 /* sto_get_folder_session */ imap_mailstorage_get_folder_session,
66 /* sto_uninitialize */ imap_mailstorage_uninitialize
67 };
68
69 LIBETPAN_EXPORT
imap_mailstorage_init(struct mailstorage * storage,const char * imap_servername,uint16_t imap_port,const char * imap_command,int imap_connection_type,int imap_auth_type,const char * imap_login,const char * imap_password,int imap_cached,const char * imap_cache_directory)70 int imap_mailstorage_init(struct mailstorage * storage,
71 const char * imap_servername, uint16_t imap_port,
72 const char * imap_command,
73 int imap_connection_type, int imap_auth_type,
74 const char * imap_login, const char * imap_password,
75 int imap_cached, const char * imap_cache_directory)
76 {
77 return imap_mailstorage_init_sasl(storage,
78 imap_servername, imap_port,
79 imap_command,
80 imap_connection_type,
81 NULL,
82 NULL,
83 NULL, NULL,
84 imap_login, imap_login,
85 imap_password, NULL,
86 imap_cached, imap_cache_directory);
87 }
88
89 LIBETPAN_EXPORT
imap_mailstorage_init_sasl(struct mailstorage * storage,const char * imap_servername,uint16_t imap_port,const char * imap_command,int imap_connection_type,const char * auth_type,const char * server_fqdn,const char * local_ip_port,const char * remote_ip_port,const char * login,const char * auth_name,const char * password,const char * realm,int imap_cached,const char * imap_cache_directory)90 int imap_mailstorage_init_sasl(struct mailstorage * storage,
91 const char * imap_servername, uint16_t imap_port,
92 const char * imap_command,
93 int imap_connection_type,
94 const char * auth_type,
95 const char * server_fqdn,
96 const char * local_ip_port,
97 const char * remote_ip_port,
98 const char * login, const char * auth_name,
99 const char * password, const char * realm,
100 int imap_cached, const char * imap_cache_directory)
101 {
102 return imap_mailstorage_init_sasl_with_local_address(storage,
103 imap_servername, imap_port,
104 NULL, 0,
105 imap_command,
106 imap_connection_type,
107 auth_type,
108 server_fqdn,
109 local_ip_port,
110 remote_ip_port,
111 login, auth_name,
112 password, realm,
113 imap_cached, imap_cache_directory);
114 }
115
116 LIBETPAN_EXPORT
imap_mailstorage_init_sasl_with_local_address(struct mailstorage * storage,const char * imap_servername,uint16_t imap_port,const char * imap_local_address,uint16_t imap_local_port,const char * imap_command,int imap_connection_type,const char * auth_type,const char * server_fqdn,const char * local_ip_port,const char * remote_ip_port,const char * login,const char * auth_name,const char * password,const char * realm,int imap_cached,const char * imap_cache_directory)117 int imap_mailstorage_init_sasl_with_local_address(struct mailstorage * storage,
118 const char * imap_servername, uint16_t imap_port,
119 const char * imap_local_address, uint16_t imap_local_port,
120 const char * imap_command,
121 int imap_connection_type,
122 const char * auth_type,
123 const char * server_fqdn,
124 const char * local_ip_port,
125 const char * remote_ip_port,
126 const char * login, const char * auth_name,
127 const char * password, const char * realm,
128 int imap_cached, const char * imap_cache_directory)
129 {
130 struct imap_mailstorage * imap_storage;
131
132 imap_storage = malloc(sizeof(* imap_storage));
133 if (imap_storage == NULL)
134 goto err;
135
136 if (imap_servername != NULL) {
137 imap_storage->imap_servername = strdup(imap_servername);
138 if (imap_storage->imap_servername == NULL)
139 goto free;
140 }
141 else {
142 imap_storage->imap_servername = NULL;
143 }
144
145 if (imap_local_address != NULL) {
146 imap_storage->imap_local_address = strdup(imap_local_address);
147 if (imap_storage->imap_local_address == NULL)
148 goto free_servername;
149 }
150 else {
151 imap_storage->imap_local_address = NULL;
152 }
153
154 imap_storage->imap_local_port = imap_local_port;
155
156 imap_storage->imap_connection_type = imap_connection_type;
157
158 if (imap_port == 0) {
159 switch (imap_connection_type) {
160 case CONNECTION_TYPE_PLAIN:
161 case CONNECTION_TYPE_TRY_STARTTLS:
162 case CONNECTION_TYPE_STARTTLS:
163 case CONNECTION_TYPE_COMMAND:
164 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
165 case CONNECTION_TYPE_COMMAND_STARTTLS:
166 imap_port = IMAP_DEFAULT_PORT;
167 break;
168
169 case CONNECTION_TYPE_TLS:
170 case CONNECTION_TYPE_COMMAND_TLS:
171 imap_port = IMAPS_DEFAULT_PORT;
172 break;
173
174 default:
175 imap_port = IMAP_DEFAULT_PORT;
176 break;
177 }
178 }
179
180 imap_storage->imap_port = imap_port;
181
182 if (imap_command != NULL) {
183 imap_storage->imap_command = strdup(imap_command);
184 if (imap_storage->imap_command == NULL)
185 goto free_local_address;
186 }
187 else
188 imap_storage->imap_command = NULL;
189
190 imap_storage->imap_auth_type = IMAP_AUTH_TYPE_PLAIN;
191
192 imap_storage->imap_sasl.sasl_enabled = (auth_type != NULL);
193
194 if (auth_type != NULL) {
195 imap_storage->imap_sasl.sasl_auth_type = strdup(auth_type);
196 if (imap_storage->imap_sasl.sasl_auth_type == NULL)
197 goto free_command;
198 }
199 else
200 imap_storage->imap_sasl.sasl_auth_type = NULL;
201
202 if (server_fqdn != NULL) {
203 imap_storage->imap_sasl.sasl_server_fqdn = strdup(server_fqdn);
204 if (imap_storage->imap_sasl.sasl_server_fqdn == NULL)
205 goto free_auth_type;
206 }
207 else
208 imap_storage->imap_sasl.sasl_server_fqdn = NULL;
209
210 if (local_ip_port != NULL) {
211 imap_storage->imap_sasl.sasl_local_ip_port = strdup(local_ip_port);
212 if (imap_storage->imap_sasl.sasl_local_ip_port == NULL)
213 goto free_server_fqdn;
214 }
215 else
216 imap_storage->imap_sasl.sasl_local_ip_port = NULL;
217
218 if (remote_ip_port != NULL) {
219 imap_storage->imap_sasl.sasl_remote_ip_port = strdup(remote_ip_port);
220 if (imap_storage->imap_sasl.sasl_remote_ip_port == NULL)
221 goto free_local_ip_port;
222 }
223 else
224 imap_storage->imap_sasl.sasl_remote_ip_port = NULL;
225
226 if (login != NULL) {
227 imap_storage->imap_sasl.sasl_login = strdup(login);
228 if (imap_storage->imap_sasl.sasl_login == NULL)
229 goto free_remote_ip_port;
230 }
231 else
232 imap_storage->imap_sasl.sasl_login = NULL;
233
234 if (auth_name != NULL) {
235 imap_storage->imap_sasl.sasl_auth_name = strdup(auth_name);
236 if (imap_storage->imap_sasl.sasl_auth_name == NULL)
237 goto free_login;
238 }
239 else
240 imap_storage->imap_sasl.sasl_auth_name = NULL;
241
242 if (password != NULL) {
243 imap_storage->imap_sasl.sasl_password = strdup(password);
244 if (imap_storage->imap_sasl.sasl_password == NULL)
245 goto free_auth_name;
246 }
247 else
248 imap_storage->imap_sasl.sasl_password = NULL;
249
250 if (realm != NULL) {
251 imap_storage->imap_sasl.sasl_realm = strdup(realm);
252 if (imap_storage->imap_sasl.sasl_realm == NULL)
253 goto free_password;
254 }
255 else
256 imap_storage->imap_sasl.sasl_realm = NULL;
257
258 imap_storage->imap_cached = imap_cached;
259
260 if (imap_cached && (imap_cache_directory != NULL)) {
261 imap_storage->imap_cache_directory = strdup(imap_cache_directory);
262 if (imap_storage->imap_cache_directory == NULL)
263 goto free_realm;
264 }
265 else {
266 imap_storage->imap_cached = FALSE;
267 imap_storage->imap_cache_directory = NULL;
268 }
269
270 imap_storage->imap_auth_type = imap_storage->imap_auth_type;
271 if (imap_storage->imap_sasl.sasl_login != NULL) {
272 imap_storage->imap_login = strdup(imap_storage->imap_sasl.sasl_login);
273 if (imap_storage->imap_login == NULL)
274 goto free_cache_directory;
275 }
276 else {
277 imap_storage->imap_login = NULL;
278 }
279
280 if (imap_storage->imap_sasl.sasl_password != NULL) {
281 imap_storage->imap_password = strdup(imap_storage->imap_sasl.sasl_password);
282 if (imap_storage->imap_password == NULL)
283 goto free_copy_login;
284 }
285 else {
286 imap_storage->imap_password = NULL;
287 }
288
289 storage->sto_data = imap_storage;
290 storage->sto_driver = &imap_mailstorage_driver;
291
292 return MAIL_NO_ERROR;
293
294 free_copy_login:
295 free(imap_storage->imap_login);
296 free_cache_directory:
297 free(imap_storage->imap_cache_directory);
298 free_realm:
299 free(imap_storage->imap_sasl.sasl_realm);
300 free_password:
301 free(imap_storage->imap_sasl.sasl_password);
302 free_auth_name:
303 free(imap_storage->imap_sasl.sasl_auth_name);
304 free_login:
305 free(imap_storage->imap_sasl.sasl_login);
306 free_remote_ip_port:
307 free(imap_storage->imap_sasl.sasl_remote_ip_port);
308 free_local_ip_port:
309 free(imap_storage->imap_sasl.sasl_local_ip_port);
310 free_server_fqdn:
311 free(imap_storage->imap_sasl.sasl_server_fqdn);
312 free_auth_type:
313 free(imap_storage->imap_sasl.sasl_auth_type);
314 free_command:
315 free(imap_storage->imap_command);
316 free_local_address:
317 free(imap_storage->imap_local_address);
318 free_servername:
319 free(imap_storage->imap_servername);
320 free:
321 free(imap_storage);
322 err:
323 return MAIL_ERROR_MEMORY;
324 }
325
imap_mailstorage_uninitialize(struct mailstorage * storage)326 static void imap_mailstorage_uninitialize(struct mailstorage * storage)
327 {
328 struct imap_mailstorage * imap_storage;
329
330 imap_storage = storage->sto_data;
331
332 free(imap_storage->imap_password);
333 free(imap_storage->imap_login);
334
335 free(imap_storage->imap_cache_directory);
336
337 free(imap_storage->imap_sasl.sasl_realm);
338 free(imap_storage->imap_sasl.sasl_password);
339 free(imap_storage->imap_sasl.sasl_auth_name);
340 free(imap_storage->imap_sasl.sasl_login);
341 free(imap_storage->imap_sasl.sasl_remote_ip_port);
342 free(imap_storage->imap_sasl.sasl_local_ip_port);
343 free(imap_storage->imap_sasl.sasl_server_fqdn);
344 free(imap_storage->imap_sasl.sasl_auth_type);
345
346 free(imap_storage->imap_command);
347 free(imap_storage->imap_local_address);
348 free(imap_storage->imap_servername);
349 free(imap_storage);
350
351 storage->sto_data = NULL;
352 }
353
imap_connect(struct mailstorage * storage,mailsession ** result)354 static int imap_connect(struct mailstorage * storage,
355 mailsession ** result)
356 {
357 struct imap_mailstorage * imap_storage;
358 mailsession_driver * driver;
359 int r;
360 int res;
361 mailsession * session;
362
363 imap_storage = storage->sto_data;
364
365 if (imap_storage->imap_cached)
366 driver = imap_cached_session_driver;
367 else
368 driver = imap_session_driver;
369
370 r = mailstorage_generic_connect_with_local_address(driver,
371 imap_storage->imap_servername,
372 imap_storage->imap_port,
373 imap_storage->imap_local_address,
374 imap_storage->imap_local_port,
375 imap_storage->imap_command,
376 imap_storage->imap_connection_type,
377 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY,
378 imap_storage->imap_cache_directory,
379 0, NULL,
380 &session);
381 switch (r) {
382 case MAIL_NO_ERROR_NON_AUTHENTICATED:
383 case MAIL_NO_ERROR_AUTHENTICATED:
384 case MAIL_NO_ERROR:
385 break;
386 default:
387 res = r;
388 goto err;
389 }
390
391 r = mailstorage_generic_auth_sasl(session, r,
392 imap_storage->imap_sasl.sasl_auth_type,
393 imap_storage->imap_sasl.sasl_server_fqdn,
394 imap_storage->imap_sasl.sasl_local_ip_port,
395 imap_storage->imap_sasl.sasl_remote_ip_port,
396 imap_storage->imap_sasl.sasl_login,
397 imap_storage->imap_sasl.sasl_auth_name,
398 imap_storage->imap_sasl.sasl_password,
399 imap_storage->imap_sasl.sasl_realm);
400 if (r != MAIL_NO_ERROR) {
401 res = r;
402 goto free;
403 }
404
405 * result = session;
406
407 return MAIL_NO_ERROR;
408
409 free:
410 mailsession_free(session);
411 err:
412 return res;
413 }
414
imap_mailstorage_connect(struct mailstorage * storage)415 static int imap_mailstorage_connect(struct mailstorage * storage)
416 {
417 mailsession * session;
418 int r;
419 int res;
420
421 r = imap_connect(storage, &session);
422 if (r != MAIL_NO_ERROR) {
423 res = r;
424 goto err;
425 }
426
427 r = mailsession_select_folder(session, "INBOX");
428 if (r != MAIL_NO_ERROR) {
429 mailsession_logout(session);
430 res = r;
431 goto err;
432 }
433
434 storage->sto_session = session;
435 storage->sto_driver = &imap_mailstorage_driver;
436
437 return MAIL_NO_ERROR;
438
439 err:
440 return res;
441 }
442
443 static int
imap_mailstorage_get_folder_session(struct mailstorage * storage,char * pathname,mailsession ** result)444 imap_mailstorage_get_folder_session(struct mailstorage * storage,
445 char * pathname, mailsession ** result)
446 {
447 mailsession * session;
448 int r;
449 int res;
450
451 if (strcasecmp(pathname, "INBOX") == 0) {
452 session = storage->sto_session;
453 }
454 else {
455 r = imap_connect(storage, &session);
456 if (r != MAIL_NO_ERROR) {
457 res = r;
458 goto err;
459 }
460
461 r = mailsession_select_folder(session, pathname);
462 if (r != MAIL_NO_ERROR) {
463 mailsession_logout(session);
464 res = r;
465 goto free;
466 }
467 }
468
469 * result = session;
470
471 return MAIL_NO_ERROR;
472
473 free:
474 mailsession_free(session);
475 err:
476 return res;
477 }
478