1 /*
2 * odmr.c -- ODMR protocol methods (see RFC 2645)
3 *
4 * For license terms, see the file COPYING in this directory.
5 */
6
7 #include "config.h"
8 #ifdef ODMR_ENABLE
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <assert.h>
12 #ifdef HAVE_STRING_H /* strcat() */
13 #include <string.h>
14 #endif
15 #ifdef HAVE_NET_SOCKET_H /* BeOS needs this */
16 #include <net/socket.h>
17 #endif
18 #include <sys/types.h>
19 #ifdef HAVE_NET_SELECT_H /* AIX needs this */
20 #include <net/select.h>
21 #endif
22 #ifdef HAVE_SYS_SELECT_H /* AIX 4.1, at least, needs this */
23 #include <sys/select.h>
24 #endif
25 #include <netdb.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include "i18n.h"
29 #include "fetchmail.h"
30 #include "sdump.h"
31 #include "smtp.h"
32 #include "socket.h"
33
odmr_ok(int sock,char * argbuf)34 static int odmr_ok (int sock, char *argbuf)
35 /* parse command response */
36 {
37 int ok;
38
39 (void)argbuf;
40 ok = SMTP_ok(sock, SMTP_MODE, TIMEOUT_DEFAULT);
41 if (ok == SM_UNRECOVERABLE)
42 return(PS_PROTOCOL);
43 else
44 return(ok);
45 }
46
odmr_getrange(int sock,struct query * ctl,const char * id,int * countp,int * newp,unsigned long long * bytes)47 static int odmr_getrange(int sock, struct query *ctl, const char *id,
48 int *countp, int *newp, unsigned long long *bytes)
49 /* send ODMR and then run a reverse SMTP session */
50 {
51 int ok, opts, smtp_sock;
52 int doing_smtp_data = 0; /* Are we in SMTP DATA state? */
53 char buf [MSGBUFSIZE+1];
54 struct idlist *qnp; /* pointer to Q names */
55
56 (void)id;
57 if ((ok = SMTP_ehlo(sock, SMTP_MODE, fetchmailhost,
58 ctl->server.esmtp_name, ctl->server.esmtp_password,
59 &opts)))
60 {
61 report(stderr, GT_("%s's SMTP listener does not support ESMTP\n"),
62 ctl->server.pollname);
63 return(ok);
64 }
65 else if (!(opts & ESMTP_ATRN))
66 {
67 report(stderr, GT_("%s's SMTP listener does not support ATRN\n"),
68 ctl->server.pollname);
69 return(PS_PROTOCOL);
70 }
71
72 /* make sure we don't enter the fetch loop */
73 *bytes = *countp = *newp = -1;
74
75 /* authenticate via CRAM-MD5 */
76 ok = do_cram_md5(sock, "AUTH", ctl, "334 ");
77 if (ok)
78 return(ok);
79
80 /*
81 * By default, the hostlist has a single entry, the fetchmail host's
82 * canonical DNS name.
83 */
84 buf[0] = '\0';
85 for (qnp = ctl->domainlist; qnp; qnp = qnp->next)
86 if (strlen(buf) + strlen(qnp->id) + 1 >= sizeof(buf))
87 break;
88 else
89 {
90 strcat(buf, qnp->id);
91 strcat(buf, ",");
92 }
93 buf[strlen(buf) - 1] = '\0'; /* nuke final comma */
94
95 /* ship the domain list and get turnaround */
96 gen_send(sock, "ATRN %s", buf);
97 if ((ok = gen_recv(sock, buf, sizeof(buf))))
98 return(ok);
99
100 /* this switch includes all response codes described in RFC2645 */
101 switch(atoi(buf))
102 {
103 case 250: /* OK, turnaround is about to happe */
104 if (outlevel > O_SILENT)
105 report(stdout, GT_("Turnaround now...\n"));
106 break;
107
108 case 450: /* ATRN request refused */
109 if (outlevel > O_SILENT)
110 report(stdout, GT_("ATRN request refused.\n"));
111 return(PS_PROTOCOL);
112
113 case 451: /* Unable to process ATRN request now */
114 report(stderr, GT_("Unable to process ATRN request now\n"));
115 return(PS_EXCLUDE);
116
117 case 453: /* You have no mail */
118 if (outlevel > O_SILENT)
119 report(stderr, GT_("You have no mail.\n"));
120 return(PS_NOMAIL);
121
122 case 502: /* Command not implemented */
123 report(stderr, GT_("Command not implemented\n"));
124 return(PS_PROTOCOL);
125
126 case 530: /* Authentication required */
127 report(stderr, GT_("Authentication required.\n"));
128 return(PS_AUTHFAIL);
129
130 default: {
131 char *t = sdump(buf, strlen(buf));
132 report(stderr, GT_("Unknown ODMR error \"%s\"\n"), t);
133 xfree(t);
134 return(PS_PROTOCOL);
135 }
136 }
137
138 /*
139 * OK, if we got here it's time to become a pipe between the ODMR
140 * remote server (sending) and the SMTP listener we've designated
141 * (receiving). We're not going to try to be a protocol machine;
142 * instead, we'll use select(2) to watch the read sides of both
143 * sockets and just throw their data at each other.
144 */
145 if ((smtp_sock = smtp_setup(ctl)) == -1)
146 return(PS_SOCKET);
147 else
148 {
149 int maxfd = (sock > smtp_sock) ? sock : smtp_sock;
150
151 for (;;)
152 {
153 fd_set readfds;
154 struct timeval timeout;
155
156 FD_ZERO(&readfds);
157 FD_SET(sock, &readfds);
158 FD_SET(smtp_sock, &readfds);
159
160 timeout.tv_sec = ctl->server.timeout;
161 timeout.tv_usec = 0;
162
163 if (select(maxfd+1, &readfds, NULL, NULL, &timeout) == -1)
164 return(PS_PROTOCOL); /* timeout */
165
166 if (FD_ISSET(sock, &readfds))
167 {
168 int n = SockRead(sock, buf, sizeof(buf));
169 if (n <= 0)
170 break;
171
172 SockWrite(smtp_sock, buf, n);
173 if (outlevel >= O_MONITOR && !doing_smtp_data)
174 report(stdout, "ODMR< %s", buf);
175 }
176 if (FD_ISSET(smtp_sock, &readfds))
177 {
178 int n = SockRead(smtp_sock, buf, sizeof(buf));
179 if (n <= 0)
180 break;
181
182 SockWrite(sock, buf, n);
183 if (outlevel >= O_MONITOR)
184 report(stdout, "ODMR> %s", buf);
185
186 /* We are about to receive message data if the local MTA
187 * sends 354 (after receiving DATA) */
188 if (!doing_smtp_data && !strncmp(buf, "354", 3))
189 {
190 doing_smtp_data = 1;
191 if (outlevel > O_SILENT)
192 report(stdout, GT_("receiving message data\n"));
193 }
194 else if (doing_smtp_data)
195 doing_smtp_data = 0;
196 }
197 }
198 SockClose(smtp_sock);
199 }
200
201 return(0);
202 }
203
odmr_logout(int sock,struct query * ctl)204 static int odmr_logout(int sock, struct query *ctl)
205 /* send logout command */
206 {
207 /* if we have a smtp_socket, then we've turned around and the
208 local smtp server is in control of the connection (so we don't
209 send QUIT) */
210 if (ctl->smtp_socket == -1)
211 return(gen_transact(sock, "QUIT"));
212 else
213 return(PS_SUCCESS);
214 }
215
216 static const struct method odmr =
217 {
218 "ODMR", /* ODMR protocol */
219 "odmr", /* standard ODMR port */
220 "odmrs", /* ssl ODMR port */
221 FALSE, /* this is not a tagged protocol */
222 FALSE, /* this does not use a message delimiter */
223 odmr_ok, /* parse command response */
224 NULL, /* no need to get authentication */
225 odmr_getrange, /* initialize message sending */
226 NULL, /* we cannot get a list of sizes */
227 NULL, /* we cannot get a list of sizes of subsets */
228 NULL, /* how do we tell a message is old? */
229 NULL, /* no way to fetch headers */
230 NULL, /* no way to fetch body */
231 NULL, /* no message trailer */
232 NULL, /* how to delete a message */
233 NULL, /* how to mark a message as seen */
234 NULL, /* no mailbox support */
235 odmr_logout, /* log out, we're done */
236 FALSE, /* no, we can't re-poll */
237 NULL, /* no constructor */
238 NULL /* no destructor */
239 };
240
doODMR(struct query * ctl)241 int doODMR (struct query *ctl)
242 /* retrieve messages using ODMR */
243 {
244 int status;
245
246 if (ctl->keep) {
247 fprintf(stderr, GT_("Option --keep is not supported with ODMR\n"));
248 return(PS_SYNTAX);
249 }
250 if (ctl->flush) {
251 fprintf(stderr, GT_("Option --flush is not supported with ODMR\n"));
252 return(PS_SYNTAX);
253 }
254 if (ctl->mailboxes->id) {
255 fprintf(stderr, GT_("Option --folder is not supported with ODMR\n"));
256 return(PS_SYNTAX);
257 }
258 if (check_only) {
259 fprintf(stderr, GT_("Option --check is not supported with ODMR\n"));
260 return(PS_SYNTAX);
261 }
262 peek_capable = FALSE;
263
264 status = do_protocol(ctl, &odmr);
265 if (status == PS_NOMAIL)
266 status = PS_SUCCESS;
267 return(status);
268 }
269 #endif /* ODMR_ENABLE */
270
271 /* odmr.c ends here */
272