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