1 /* $Id: imap.c,v 1.13 2006/05/09 03:26:41 jared Exp $ */
2 #include "config.h"
3
4 /* see RFC 2060 for protocol details
5 Excerpt included here:
6
7 6.2.2. LOGIN Command
8
9 Arguments: user name
10 password
11
12 Responses: no specific responses for this command
13
14 Result: OK - login completed, now in authenticated state
15 NO - login failure: user name or password rejected
16 BAD - command unknown or arguments invalid
17
18 The LOGIN command identifies the client to the server and carries
19 the plaintext password authenticating this user.
20
21 Example: C: a001 LOGIN SMITH SESAME
22 S: a001 OK LOGIN completed
23
24 6.1.3. LOGOUT Command
25
26 Arguments: none
27
28 Responses: REQUIRED untagged response: BYE
29
30 Result: OK - logout completed
31 BAD - command unknown or arguments invalid
32
33 The LOGOUT command informs the server that the client is done with
34 the connection. The server MUST send a BYE untagged response
35 before the (tagged) OK response, and then close the network
36 connection.
37
38 Example: C: A023 LOGOUT
39 S: * BYE IMAP4rev1 Server logging out
40 S: A023 OK LOGOUT completed
41 (Server and client then close the connection)
42
43 */
44
45 struct imapdata {
46 time_t start; /* test start time */
47 time_t lastact; /* last activity */
48 int state;
49 };
50
51 #define IMAP_CONNECT 1 /* doing a connect() */
52 #define IMAP_WAITBAN 2 /* Waiting for the banner */
53 #define IMAP_SENT_AUTH 3 /* sent our auth data */
54 #define IMAP_SENT_QUIT 4 /* sent logout */
55 #define IMAP_GOT_BYE 5 /* got a bye from the remote server */
56
start_test_imap(struct monitorent * here,time_t now_t)57 void start_test_imap(struct monitorent *here, time_t now_t)
58 {
59 struct imapdata *localstruct = NULL;
60 struct my_hostent *hp = NULL;
61 struct sockaddr_in name;
62 int serrno = -1, errcode = 0;
63
64 /* Allocate our memory */
65 here->monitordata = MALLOC(sizeof(struct imapdata), "imap localstruct");
66
67 localstruct = here->monitordata;
68
69 localstruct->start = now_t;
70
71 localstruct->lastact = localstruct->start;
72
73 here->filedes = open_sock();
74
75 if (here->filedes == -1)
76 {
77 here->retval = here->checkent->lastcheck;
78 FREE(here->monitordata);
79 here->monitordata = NULL;
80 return;
81 }
82
83
84 hp = my_gethostbyname(here->checkent->hostname, AF_INET);
85
86 if (hp == NULL)
87 {
88 here->retval = SYSM_NODNS;
89 FREE(here->monitordata);
90 here->monitordata = NULL;
91 return;
92 }
93
94 /* zero out the space */
95 memset ( &name, 0, sizeof ( name ) );
96
97 /* copy data */
98 memcpy((char*)&name.sin_addr, (char*)hp->my_h_addr_v4, hp->h_length_v4);
99
100 /* set family type */
101 name.sin_family = AF_INET;
102
103 /* set the port we're connecting to */
104 name.sin_port = htons(IMAP_PORTNUM);
105
106 if (debug)
107 {
108 print_err(0, "start_test_imap() doing connect() to %s:%d\n",
109 here->checkent->hostname, IMAP_PORTNUM);
110 }
111
112 errcode = connect(here->filedes, (struct sockaddr*)&name,
113 sizeof(struct sockaddr_in));
114 serrno = errno;
115 if (debug)
116 {
117 perror("connect() in start_imap");
118 }
119
120 if ((errcode < 0) && (serrno != EINPROGRESS))
121 {
122 close(here->filedes);
123
124 switch(serrno)
125 {
126 case ECONNREFUSED:
127 case EINTR:
128 here->retval = SYSM_CONNREF;
129 break;
130 case ENETUNREACH:
131 here->retval = SYSM_NETUNRCH;
132 break;
133 case EHOSTDOWN:
134 case EHOSTUNREACH:
135 here->retval = SYSM_HOSTDOWN;
136 break;
137 case ETIMEDOUT:
138 here->retval = SYSM_TIMEDOUT;
139 break;
140 }
141
142 /* Free memory we'd normally leak */
143 FREE(localstruct);
144 here->monitordata = NULL;
145
146 if (debug)
147 {
148 print_err(0, "imap.c: retval = %d\n", here->retval);
149 }
150 return;
151 }
152
153 /* doing a connect() */
154 localstruct->state = IMAP_CONNECT;
155
156 /* poll it again later */
157 return;
158 }
159
service_test_imap(struct monitorent * here,time_t now_t)160 void service_test_imap(struct monitorent *here, time_t now_t)
161 {
162 struct imapdata *localstruct = NULL;
163 char buffer[256], *retptr;
164 int isopenretval = -1;
165
166 /* do some variable shufflign */
167 localstruct = here->monitordata;
168
169 if (localstruct == NULL)
170 {
171 print_err(1, "bug - localstruct == NULL in imap.c:service_test_imap\n");
172 return;
173 }
174
175 if (debug)
176 {
177 print_err(0, "service_test_imap: state = %d\n", localstruct->state);
178 }
179 /* do different things based on the state */
180 switch (localstruct->state)
181 {
182 case IMAP_CONNECT:
183 {
184 isopenretval = is_open(here->filedes);
185 if (debug)
186 {
187 print_err(0, "is_open is returning %d\n", isopenretval);
188 }
189 if ((isopenretval != -1) &&
190 (isopenretval != SYSM_INPROG))
191 {
192 localstruct->lastact = now_t;
193 if (debug)
194 {
195 print_err(0, "is_open() in service_test_imap()\n");
196 }
197 if (isopenretval != SYSM_OK)
198 {
199 here->retval = isopenretval;
200 close(here->filedes);
201 FREE(localstruct);
202 here->monitordata = NULL;
203 if (debug)
204 {
205 print_err(0, "ending service_test_imap() with retval = %s\n", errtostr(here->retval));
206 }
207 return;
208 }
209 localstruct->state = IMAP_WAITBAN;
210 if (debug)
211 {
212 print_err(0, "connected() to the imap port of %s\n", here->checkent->hostname);
213 }
214 }
215 break;
216 }
217
218 case IMAP_WAITBAN:
219 {
220 if (data_waiting_read(here->filedes, 0))
221 {
222 memset(buffer, 0, 256);
223 read(here->filedes, buffer, 254);
224 if (debug)
225 {
226 print_err(0, "imap.c:Got :%s:\n", buffer);
227 }
228 if (strncmp(buffer, "* OK", 4) == 0)
229 {
230 /* prepare the buffer */
231 snprintf(buffer, 256, "A100 LOGIN %s %s",
232 here->checkent->username,
233 here->checkent->password);
234
235 /* send the buffer out the socket */
236 sendline(here->filedes, buffer);
237 localstruct->state = IMAP_SENT_AUTH;
238 } else {
239 here->retval = SYSM_BAD_RESP;
240 }
241 }
242 break;
243 }
244 case IMAP_SENT_AUTH:
245 {
246 if (data_waiting_read(here->filedes, 0))
247 {
248 memset(buffer, 0, 256);
249 read(here->filedes, buffer, 254);
250 if (debug)
251 {
252 print_err(0, "imap.c:Got :%s:\n", buffer);
253 }
254 /* ditch informational msg(s) */
255 doover: if (strncmp(buffer, "*", 1) == 0) {
256 if ((retptr = strchr(buffer, '\n')) != NULL) {
257 strncpy(buffer, retptr + 1, 250);
258 goto doover;
259 }
260 }
261 if (strncmp(buffer, "A100 OK", 7) == 0)
262 {
263 here->retval = SYSM_OK;
264 } else if (strncmp(buffer, "A100 NO", 7) == 0)
265 {
266 here->retval = SYSM_BAD_AUTH;
267 } else {
268 here->retval = SYSM_BAD_RESP;
269 }
270
271 sendline(here->filedes, "A102 LOGOUT");
272
273 /* send the buffer out the socket */
274 localstruct->state = IMAP_SENT_QUIT;
275 }
276 break;
277 }
278 case IMAP_SENT_QUIT:
279 {
280 if (data_waiting_read(here->filedes, 0))
281 {
282 memset(buffer, 0, 256);
283 read(here->filedes, buffer, 254);
284 if (debug)
285 {
286 print_err(0, "imap.c:Got :%s:\n", buffer);
287 }
288 if (strncmp(buffer, "A102 OK", 7) == 0)
289 {
290 here->retval = SYSM_OK;
291 localstruct->state = IMAP_GOT_BYE;
292 } else {
293 here->retval = SYSM_BAD_RESP;
294 }
295 }
296 break;
297 }
298
299
300 } /* end of switch */
301 if (here->retval != -1)
302 {
303 /* insert cleanup code here */
304 close (here->filedes);
305 FREE(localstruct);
306 here->monitordata = NULL;
307 }
308 return;
309
310 }
311
stop_test_imap(struct monitorent * here)312 void stop_test_imap(struct monitorent *here)
313 {
314 struct imapdata *localstruct = NULL;
315
316 localstruct = here->monitordata;
317 if (localstruct == NULL)
318 return;
319
320 close(here->filedes);
321 FREE(localstruct);
322 here->monitordata = NULL;
323 return;
324
325 }
326
327
328