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