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