summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/interface/mailstorage_tools.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/interface/mailstorage_tools.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/interface/mailstorage_tools.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/libetpan/src/driver/interface/mailstorage_tools.c b/libetpan/src/driver/interface/mailstorage_tools.c
new file mode 100644
index 0000000..9d39cab
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_tools.c
@@ -0,0 +1,372 @@
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$
34 */
35
36#include "mailstorage_tools.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#include <unistd.h>
45#include <stdlib.h>
46#include <sys/wait.h>
47#include <sys/ioctl.h>
48#include <fcntl.h>
49#include <string.h>
50
51#include "mail.h"
52#include "mailmessage.h"
53#include "maildriver.h"
54
55/* tools */
56
57/* connection to TCP/IP server */
58
59static int tcp_connect(char * server, uint16_t port)
60{
61 struct hostent * remotehost;
62 struct sockaddr_in sa;
63 int s;
64 int r;
65
66 s = socket(PF_INET, SOCK_STREAM, 0);
67 if (s == -1)
68 goto err;
69
70 remotehost = gethostbyname(server);
71 if (remotehost == NULL)
72 goto close_socket;
73
74 sa.sin_family = AF_INET;
75 sa.sin_port = htons(port);
76 memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length);
77
78 r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
79 if (r == -1)
80 goto close_socket;
81
82 return s;
83
84 close_socket:
85 close(s);
86 err:
87 return -1;
88}
89
90
91/* connection through a shell command */
92
93static void do_exec_command(int fd, const char *command,
94 char *servername, uint16_t port)
95{
96 int i, maxopen;
97
98 if (fork() > 0) {
99 /* Fork again to become a child of init rather than
100 the etpan client. */
101 exit(0);
102 }
103
104 if (servername)
105 setenv("ETPANSERVER", servername, 1);
106 else
107 unsetenv("ETPANSERVER");
108
109 if (port) {
110 char porttext[20];
111
112 snprintf(porttext, sizeof(porttext), "%d", port);
113 setenv("ETPANPORT", porttext, 1);
114 }
115 else {
116 unsetenv("ETPANPORT");
117 }
118
119 /* Not a lot we can do if there's an error other than bail. */
120 if (dup2(fd, 0) == -1)
121 exit(1);
122 if (dup2(fd, 1) == -1)
123 exit(1);
124
125 /* Should we close stderr and reopen /dev/null? */
126
127 maxopen = sysconf(_SC_OPEN_MAX);
128 for (i=3; i < maxopen; i++)
129 close(i);
130
131#ifdef TIOCNOTTY
132 /* Detach from the controlling tty if we have one. Otherwise,
133 SSH might do something stupid like trying to use it instead
134 of running $SSH_ASKPASS. Doh. */
135 fd = open("/dev/tty", O_RDONLY);
136 if (fd != -1) {
137 ioctl(fd, TIOCNOTTY, NULL);
138 close(fd);
139 }
140#endif /* TIOCNOTTY */
141
142 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
143
144 /* Eep. Shouldn't reach this */
145 exit(1);
146}
147
148static int subcommand_connect(char *command, char *servername, uint16_t port)
149{
150 int sockfds[2];
151 pid_t childpid;
152
153 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
154 return -1;
155
156 childpid = fork();
157 if (!childpid) {
158 do_exec_command(sockfds[1], command, servername, port);
159 }
160 else if (childpid == -1) {
161 close(sockfds[0]);
162 close(sockfds[1]);
163 return -1;
164 }
165
166 close(sockfds[1]);
167
168 /* Reap child, leaving grandchild process to run */
169 waitpid(childpid, NULL, 0);
170
171 return sockfds[0];
172}
173
174int mailstorage_generic_connect(mailsession_driver * driver,
175 char * servername,
176 uint16_t port,
177 char * command,
178 int connection_type,
179 int cache_function_id,
180 char * cache_directory,
181 int flags_function_id,
182 char * flags_directory,
183 mailsession ** result)
184{
185 int r;
186 int res;
187 mailstream * stream;
188 int fd;
189 mailsession * session;
190 int connect_result;
191
192 switch (connection_type) {
193 case CONNECTION_TYPE_PLAIN:
194 case CONNECTION_TYPE_TRY_STARTTLS:
195 case CONNECTION_TYPE_STARTTLS:
196 case CONNECTION_TYPE_TLS:
197 fd = tcp_connect(servername, port);
198 if (fd == -1) {
199 res = MAIL_ERROR_CONNECT;
200 goto err;
201 }
202 break;
203
204 case CONNECTION_TYPE_COMMAND:
205 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
206 case CONNECTION_TYPE_COMMAND_STARTTLS:
207 case CONNECTION_TYPE_COMMAND_TLS:
208 fd = subcommand_connect(command, servername, port);
209 break;
210
211 default:
212 fd = -1;
213 break;
214 }
215
216 if (fd == -1) {
217 res = MAIL_ERROR_INVAL;
218 goto err;
219 }
220
221 switch (connection_type) {
222 case CONNECTION_TYPE_PLAIN:
223 case CONNECTION_TYPE_TRY_STARTTLS:
224 case CONNECTION_TYPE_STARTTLS:
225 case CONNECTION_TYPE_COMMAND:
226 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
227 case CONNECTION_TYPE_COMMAND_STARTTLS:
228 stream = mailstream_socket_open(fd);
229 break;
230
231 case CONNECTION_TYPE_TLS:
232 case CONNECTION_TYPE_COMMAND_TLS:
233 stream = mailstream_ssl_open(fd);
234 break;
235
236 default:
237 stream = NULL;
238 break;
239 }
240
241 if (stream == NULL) {
242 res = MAIL_ERROR_STREAM;
243 close(fd);
244 goto err;
245 }
246
247 session = mailsession_new(driver);
248 if (session == NULL) {
249 res = MAIL_ERROR_MEMORY;
250 goto close_stream;
251 }
252
253 if (cache_directory != NULL) {
254 char cache_directory_server[PATH_MAX];
255
256 snprintf(cache_directory_server, PATH_MAX, "%s/%s",
257 cache_directory, servername);
258
259 r = mailsession_parameters(session,
260 cache_function_id,
261 cache_directory_server);
262 if (r != MAIL_NO_ERROR) {
263 res = r;
264 goto close_stream;
265 }
266 }
267
268 if (flags_directory != NULL) {
269 char flags_directory_server[PATH_MAX];
270
271 snprintf(flags_directory_server, PATH_MAX, "%s/%s",
272 flags_directory, servername);
273
274 r = mailsession_parameters(session,
275 flags_function_id,
276 flags_directory_server);
277 if (r != MAIL_NO_ERROR) {
278 res = r;
279 goto close_stream;
280 }
281 }
282
283 r = mailsession_connect_stream(session, stream);
284 switch (r) {
285 case MAIL_NO_ERROR_NON_AUTHENTICATED:
286 case MAIL_NO_ERROR_AUTHENTICATED:
287 case MAIL_NO_ERROR:
288 break;
289 default:
290 res = r;
291 goto free;
292 }
293
294 connect_result = r;
295
296 switch (connection_type) {
297 case CONNECTION_TYPE_TRY_STARTTLS:
298 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
299 r = mailsession_starttls(session);
300 if ((r != MAIL_NO_ERROR) && (r != MAIL_ERROR_NO_TLS)) {
301 res = r;
302 goto free;
303 }
304 break;
305
306 case CONNECTION_TYPE_STARTTLS:
307 case CONNECTION_TYPE_COMMAND_STARTTLS:
308 r = mailsession_starttls(session);
309 if (r != MAIL_NO_ERROR) {
310 res = r;
311 goto free;
312 }
313 }
314
315 * result = session;
316
317 return connect_result;
318
319 close_stream:
320 mailstream_close(stream);
321 free:
322 mailsession_free(session);
323 err:
324 return res;
325}
326
327
328
329
330
331int mailstorage_generic_auth(mailsession * session,
332 int connect_result,
333 int auth_type,
334 char * login,
335 char * password)
336{
337 int must_auth;
338 int r;
339 int res;
340
341 r = connect_result;
342
343 must_auth = FALSE;
344 switch (r) {
345 case MAIL_NO_ERROR_NON_AUTHENTICATED:
346 must_auth = TRUE;
347 break;
348 case MAIL_NO_ERROR_AUTHENTICATED:
349 case MAIL_NO_ERROR:
350 break;
351 default:
352 res = r;
353 goto err;
354 }
355
356 if ((login == NULL) || (password == NULL))
357 must_auth = FALSE;
358
359 if (must_auth) {
360 r = mailsession_login(session, login, password);
361 if (r != MAIL_NO_ERROR) {
362 mailsession_logout(session);
363 res = r;
364 goto err;
365 }
366 }
367
368 return MAIL_NO_ERROR;
369
370 err:
371 return res;
372}