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: pop3storage.c,v 1.22 2009/07/23 19:46:46 hoa Exp $
34 */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include "pop3storage.h"
41
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "mail.h"
46 #include "mailstorage_tools.h"
47 #include "maildriver.h"
48
49 /* pop3 storage */
50
51 #define POP3_DEFAULT_PORT 110
52 #define POP3S_DEFAULT_PORT 995
53
54 static int pop3_mailstorage_connect(struct mailstorage * storage);
55 static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
56 char * pathname, mailsession ** result);
57 static void pop3_mailstorage_uninitialize(struct mailstorage * storage);
58
59 static mailstorage_driver pop3_mailstorage_driver = {
60 /* sto_name */ "pop3",
61 /* sto_connect */ pop3_mailstorage_connect,
62 /* sto_get_folder_session */ pop3_mailstorage_get_folder_session,
63 /* sto_uninitialize */ pop3_mailstorage_uninitialize
64 };
65
66 LIBETPAN_EXPORT
pop3_mailstorage_init(struct mailstorage * storage,const char * pop3_servername,uint16_t pop3_port,const char * pop3_command,int pop3_connection_type,int pop3_auth_type,const char * pop3_login,const char * pop3_password,int pop3_cached,const char * pop3_cache_directory,const char * pop3_flags_directory)67 int pop3_mailstorage_init(struct mailstorage * storage,
68 const char * pop3_servername, uint16_t pop3_port,
69 const char * pop3_command,
70 int pop3_connection_type, int pop3_auth_type,
71 const char * pop3_login, const char * pop3_password,
72 int pop3_cached,
73 const char * pop3_cache_directory, const char * pop3_flags_directory)
74 {
75 char * sasl_auth_type;
76
77 sasl_auth_type = NULL;
78 switch (pop3_auth_type) {
79 case POP3_AUTH_TYPE_APOP:
80 sasl_auth_type = POP3_SASL_AUTH_TYPE_APOP;
81 break;
82 case POP3_AUTH_TYPE_TRY_APOP:
83 sasl_auth_type = POP3_SASL_AUTH_TYPE_TRY_APOP;
84 break;
85 }
86
87 return pop3_mailstorage_init_sasl(storage,
88 pop3_servername, pop3_port,
89 pop3_command,
90 pop3_connection_type,
91 sasl_auth_type,
92 NULL,
93 NULL, NULL,
94 pop3_login, pop3_login,
95 pop3_password, NULL,
96 pop3_cached, pop3_cache_directory,
97 pop3_flags_directory);
98 }
99
100 LIBETPAN_EXPORT
pop3_mailstorage_init_sasl(struct mailstorage * storage,const char * pop3_servername,uint16_t pop3_port,const char * pop3_command,int pop3_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 pop3_cached,const char * pop3_cache_directory,const char * pop3_flags_directory)101 int pop3_mailstorage_init_sasl(struct mailstorage * storage,
102 const char * pop3_servername, uint16_t pop3_port,
103 const char * pop3_command,
104 int pop3_connection_type,
105 const char * auth_type,
106 const char * server_fqdn,
107 const char * local_ip_port,
108 const char * remote_ip_port,
109 const char * login, const char * auth_name,
110 const char * password, const char * realm,
111 int pop3_cached, const char * pop3_cache_directory,
112 const char * pop3_flags_directory)
113 {
114 return pop3_mailstorage_init_sasl_with_local_address(storage,
115 pop3_servername, pop3_port,
116 NULL, 0,
117 pop3_command,
118 pop3_connection_type,
119 auth_type,
120 server_fqdn,
121 local_ip_port,
122 remote_ip_port,
123 login, auth_name,
124 password, realm,
125 pop3_cached, pop3_cache_directory,
126 pop3_flags_directory);
127 }
128
129 LIBETPAN_EXPORT
pop3_mailstorage_init_sasl_with_local_address(struct mailstorage * storage,const char * pop3_servername,uint16_t pop3_port,const char * pop3_local_address,uint16_t pop3_local_port,const char * pop3_command,int pop3_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 pop3_cached,const char * pop3_cache_directory,const char * pop3_flags_directory)130 int pop3_mailstorage_init_sasl_with_local_address(struct mailstorage * storage,
131 const char * pop3_servername, uint16_t pop3_port,
132 const char * pop3_local_address, uint16_t pop3_local_port,
133 const char * pop3_command,
134 int pop3_connection_type,
135 const char * auth_type,
136 const char * server_fqdn,
137 const char * local_ip_port,
138 const char * remote_ip_port,
139 const char * login, const char * auth_name,
140 const char * password, const char * realm,
141 int pop3_cached, const char * pop3_cache_directory,
142 const char * pop3_flags_directory)
143 {
144 struct pop3_mailstorage * pop3_storage;
145
146 pop3_storage = malloc(sizeof(* pop3_storage));
147 if (pop3_storage == NULL)
148 goto err;
149
150 if (pop3_servername != NULL) {
151 pop3_storage->pop3_servername = strdup(pop3_servername);
152 if (pop3_storage->pop3_servername == NULL)
153 goto free;
154 }
155 else {
156 pop3_storage->pop3_servername = NULL;
157 }
158
159 if (pop3_local_address != NULL) {
160 pop3_storage->pop3_local_address = strdup(pop3_local_address);
161 if (pop3_storage->pop3_local_address == NULL)
162 goto free_servername;
163 }
164 else {
165 pop3_storage->pop3_local_address = NULL;
166 }
167
168 pop3_storage->pop3_local_port = pop3_local_port;
169
170 pop3_storage->pop3_connection_type = pop3_connection_type;
171
172 if (pop3_port == 0) {
173 switch (pop3_connection_type) {
174 case CONNECTION_TYPE_PLAIN:
175 case CONNECTION_TYPE_TRY_STARTTLS:
176 case CONNECTION_TYPE_STARTTLS:
177 case CONNECTION_TYPE_COMMAND:
178 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
179 case CONNECTION_TYPE_COMMAND_STARTTLS:
180 pop3_port = POP3_DEFAULT_PORT;
181 break;
182
183 case CONNECTION_TYPE_TLS:
184 case CONNECTION_TYPE_COMMAND_TLS:
185 pop3_port = POP3S_DEFAULT_PORT;
186 break;
187
188 default:
189 pop3_port = POP3_DEFAULT_PORT;
190 break;
191 }
192 }
193
194 pop3_storage->pop3_port = pop3_port;
195
196 if (pop3_command != NULL) {
197 pop3_storage->pop3_command = strdup(pop3_command);
198 if (pop3_storage->pop3_command == NULL)
199 goto free_local_address;
200 }
201 else
202 pop3_storage->pop3_command = NULL;
203
204 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN;
205
206 pop3_storage->pop3_sasl.sasl_enabled = (auth_type != NULL);
207
208 if (auth_type != NULL) {
209 if (strcmp(auth_type, POP3_SASL_AUTH_TYPE_APOP) == 0) {
210 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_APOP;
211 auth_type = NULL;
212 }
213 else if (strcmp(auth_type, POP3_SASL_AUTH_TYPE_TRY_APOP) == 0) {
214 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP;
215 auth_type = NULL;
216 }
217 }
218
219 if (auth_type != NULL) {
220 pop3_storage->pop3_sasl.sasl_auth_type = strdup(auth_type);
221 if (pop3_storage->pop3_sasl.sasl_auth_type == NULL)
222 goto free_command;
223 }
224 else
225 pop3_storage->pop3_sasl.sasl_auth_type = NULL;
226
227 if (server_fqdn != NULL) {
228 pop3_storage->pop3_sasl.sasl_server_fqdn = strdup(server_fqdn);
229 if (pop3_storage->pop3_sasl.sasl_server_fqdn == NULL)
230 goto free_auth_type;
231 }
232 else
233 pop3_storage->pop3_sasl.sasl_server_fqdn = NULL;
234
235 if (local_ip_port != NULL) {
236 pop3_storage->pop3_sasl.sasl_local_ip_port = strdup(local_ip_port);
237 if (pop3_storage->pop3_sasl.sasl_local_ip_port == NULL)
238 goto free_server_fqdn;
239 }
240 else
241 pop3_storage->pop3_sasl.sasl_local_ip_port = NULL;
242
243 if (remote_ip_port != NULL) {
244 pop3_storage->pop3_sasl.sasl_remote_ip_port = strdup(remote_ip_port);
245 if (pop3_storage->pop3_sasl.sasl_remote_ip_port == NULL)
246 goto free_local_ip_port;
247 }
248 else
249 pop3_storage->pop3_sasl.sasl_remote_ip_port = NULL;
250
251 if (login != NULL) {
252 pop3_storage->pop3_sasl.sasl_login = strdup(login);
253 if (pop3_storage->pop3_sasl.sasl_login == NULL)
254 goto free_remote_ip_port;
255 }
256 else
257 pop3_storage->pop3_sasl.sasl_login = NULL;
258
259 if (auth_name != NULL) {
260 pop3_storage->pop3_sasl.sasl_auth_name = strdup(auth_name);
261 if (pop3_storage->pop3_sasl.sasl_auth_name == NULL)
262 goto free_login;
263 }
264 else
265 pop3_storage->pop3_sasl.sasl_auth_name = NULL;
266
267 if (password != NULL) {
268 pop3_storage->pop3_sasl.sasl_password = strdup(password);
269 if (pop3_storage->pop3_sasl.sasl_password == NULL)
270 goto free_auth_name;
271 }
272 else
273 pop3_storage->pop3_sasl.sasl_password = NULL;
274
275 if (realm != NULL) {
276 pop3_storage->pop3_sasl.sasl_realm = strdup(realm);
277 if (pop3_storage->pop3_sasl.sasl_realm == NULL)
278 goto free_password;
279 }
280 else
281 pop3_storage->pop3_sasl.sasl_realm = NULL;
282
283 pop3_storage->pop3_cached = pop3_cached;
284
285 if (pop3_cached && (pop3_cache_directory != NULL) &&
286 (pop3_flags_directory != NULL)) {
287 pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory);
288 if (pop3_storage->pop3_cache_directory == NULL)
289 goto free_realm;
290 pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory);
291 if (pop3_storage->pop3_flags_directory == NULL)
292 goto free_cache_directory;
293 }
294 else {
295 pop3_storage->pop3_cached = FALSE;
296 pop3_storage->pop3_cache_directory = NULL;
297 pop3_storage->pop3_flags_directory = NULL;
298 }
299
300 pop3_storage->pop3_auth_type = pop3_storage->pop3_auth_type;
301 if (pop3_storage->pop3_sasl.sasl_login != NULL) {
302 pop3_storage->pop3_login = strdup(pop3_storage->pop3_sasl.sasl_login);
303 if (pop3_storage->pop3_login == NULL)
304 goto free_cache_directory;
305 }
306 else {
307 pop3_storage->pop3_login = NULL;
308 }
309 if (pop3_storage->pop3_sasl.sasl_password != NULL) {
310 pop3_storage->pop3_password = strdup(pop3_storage->pop3_sasl.sasl_password);
311 if (pop3_storage->pop3_password == NULL)
312 goto free_copy_login;
313 }
314
315 storage->sto_data = pop3_storage;
316 storage->sto_driver = &pop3_mailstorage_driver;
317
318 return MAIL_NO_ERROR;
319
320 free_copy_login:
321 free(pop3_storage->pop3_login);
322 free_cache_directory:
323 free(pop3_storage->pop3_cache_directory);
324 free_realm:
325 free(pop3_storage->pop3_sasl.sasl_realm);
326 free_password:
327 free(pop3_storage->pop3_sasl.sasl_password);
328 free_auth_name:
329 free(pop3_storage->pop3_sasl.sasl_auth_name);
330 free_login:
331 free(pop3_storage->pop3_sasl.sasl_login);
332 free_remote_ip_port:
333 free(pop3_storage->pop3_sasl.sasl_remote_ip_port);
334 free_local_ip_port:
335 free(pop3_storage->pop3_sasl.sasl_local_ip_port);
336 free_server_fqdn:
337 free(pop3_storage->pop3_sasl.sasl_server_fqdn);
338 free_auth_type:
339 free(pop3_storage->pop3_sasl.sasl_auth_type);
340 free_command:
341 free(pop3_storage->pop3_command);
342 free_local_address:
343 free(pop3_storage->pop3_local_address);
344 free_servername:
345 free(pop3_storage->pop3_servername);
346 free:
347 free(pop3_storage);
348 err:
349 return MAIL_ERROR_MEMORY;
350 }
351
pop3_mailstorage_uninitialize(struct mailstorage * storage)352 static void pop3_mailstorage_uninitialize(struct mailstorage * storage)
353 {
354 struct pop3_mailstorage * pop3_storage;
355
356 pop3_storage = storage->sto_data;
357
358 free(pop3_storage->pop3_password);
359 free(pop3_storage->pop3_login);
360
361 free(pop3_storage->pop3_flags_directory);
362 free(pop3_storage->pop3_cache_directory);
363
364 free(pop3_storage->pop3_sasl.sasl_realm);
365 free(pop3_storage->pop3_sasl.sasl_password);
366 free(pop3_storage->pop3_sasl.sasl_auth_name);
367 free(pop3_storage->pop3_sasl.sasl_login);
368 free(pop3_storage->pop3_sasl.sasl_remote_ip_port);
369 free(pop3_storage->pop3_sasl.sasl_local_ip_port);
370 free(pop3_storage->pop3_sasl.sasl_server_fqdn);
371 free(pop3_storage->pop3_sasl.sasl_auth_type);
372
373 free(pop3_storage->pop3_command);
374 free(pop3_storage->pop3_local_address);
375 free(pop3_storage->pop3_servername);
376 free(pop3_storage);
377
378 storage->sto_data = NULL;
379 }
380
pop3_mailstorage_connect(struct mailstorage * storage)381 static int pop3_mailstorage_connect(struct mailstorage * storage)
382 {
383 struct pop3_mailstorage * pop3_storage;
384 mailsession_driver * driver;
385 int r;
386 int res;
387 mailsession * session;
388 int auth_type;
389
390 pop3_storage = storage->sto_data;
391
392 if (pop3_storage->pop3_cached)
393 driver = pop3_cached_session_driver;
394 else
395 driver = pop3_session_driver;
396
397 r = mailstorage_generic_connect_with_local_address(driver,
398 pop3_storage->pop3_servername,
399 pop3_storage->pop3_port,
400 pop3_storage->pop3_local_address,
401 pop3_storage->pop3_local_port,
402 pop3_storage->pop3_command,
403 pop3_storage->pop3_connection_type,
404 POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
405 pop3_storage->pop3_cache_directory,
406 POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
407 pop3_storage->pop3_flags_directory,
408 &session);
409 switch (r) {
410 case MAIL_NO_ERROR_NON_AUTHENTICATED:
411 case MAIL_NO_ERROR_AUTHENTICATED:
412 case MAIL_NO_ERROR:
413 break;
414 default:
415 res = r;
416 goto err;
417 }
418
419 auth_type = -1;
420 switch (pop3_storage->pop3_auth_type) {
421 case POP3_AUTH_TYPE_PLAIN:
422 auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
423 break;
424 case POP3_AUTH_TYPE_APOP:
425 auth_type = POP3DRIVER_AUTH_TYPE_APOP;
426 break;
427 case POP3_AUTH_TYPE_TRY_APOP:
428 auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP;
429 break;
430 }
431
432 if (auth_type != -1) {
433 mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type);
434 }
435
436 r = mailstorage_generic_auth_sasl(session, r,
437 pop3_storage->pop3_sasl.sasl_auth_type,
438 pop3_storage->pop3_sasl.sasl_server_fqdn,
439 pop3_storage->pop3_sasl.sasl_local_ip_port,
440 pop3_storage->pop3_sasl.sasl_remote_ip_port,
441 pop3_storage->pop3_sasl.sasl_login,
442 pop3_storage->pop3_sasl.sasl_auth_name,
443 pop3_storage->pop3_sasl.sasl_password,
444 pop3_storage->pop3_sasl.sasl_realm);
445 if (r != MAIL_NO_ERROR) {
446 if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) {
447 /* try in clear authentication */
448 mailsession_free(session);
449
450 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN;
451 r = mailstorage_connect(storage);
452 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP;
453 if (r != MAIL_NO_ERROR) {
454 res = r;
455 return res;
456 }
457
458 return MAIL_NO_ERROR;
459 }
460
461 res = r;
462 goto free;
463 }
464
465 storage->sto_session = session;
466
467 return MAIL_NO_ERROR;
468
469 free:
470 mailsession_free(session);
471 err:
472 return res;
473 }
474
pop3_mailstorage_get_folder_session(struct mailstorage * storage,char * pathname,mailsession ** result)475 static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
476 char * pathname, mailsession ** result)
477 {
478 * result = storage->sto_session;
479
480 return MAIL_NO_ERROR;
481 }
482
483