diff options
Diffstat (limited to 'web/attachments/112577-check_smtp.c.patch.cvs.HEAD.20041215')
-rw-r--r-- | web/attachments/112577-check_smtp.c.patch.cvs.HEAD.20041215 | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/web/attachments/112577-check_smtp.c.patch.cvs.HEAD.20041215 b/web/attachments/112577-check_smtp.c.patch.cvs.HEAD.20041215 new file mode 100644 index 0000000..8dedb8c --- /dev/null +++ b/web/attachments/112577-check_smtp.c.patch.cvs.HEAD.20041215 | |||
@@ -0,0 +1,504 @@ | |||
1 | *** check_smtp.c.orig 2004-12-15 13:08:34.000000000 -0500 | ||
2 | --- check_smtp.c 2004-12-15 14:35:05.521604150 -0500 | ||
3 | *************** | ||
4 | *** 25,45 **** | ||
5 | --- 25,77 ---- | ||
6 | |||
7 | #include "common.h" | ||
8 | #include "netutils.h" | ||
9 | #include "utils.h" | ||
10 | |||
11 | + #ifdef HAVE_SSL_H | ||
12 | + # include <rsa.h> | ||
13 | + # include <crypto.h> | ||
14 | + # include <x509.h> | ||
15 | + # include <pem.h> | ||
16 | + # include <ssl.h> | ||
17 | + # include <err.h> | ||
18 | + #else | ||
19 | + # ifdef HAVE_OPENSSL_SSL_H | ||
20 | + # include <openssl/rsa.h> | ||
21 | + # include <openssl/crypto.h> | ||
22 | + # include <openssl/x509.h> | ||
23 | + # include <openssl/pem.h> | ||
24 | + # include <openssl/ssl.h> | ||
25 | + # include <openssl/err.h> | ||
26 | + # endif | ||
27 | + #endif | ||
28 | + | ||
29 | + #ifdef HAVE_SSL | ||
30 | + | ||
31 | + int check_cert = FALSE; | ||
32 | + int days_till_exp; | ||
33 | + SSL_CTX *ctx; | ||
34 | + SSL *ssl; | ||
35 | + X509 *server_cert; | ||
36 | + int connect_STARTTLS (void); | ||
37 | + int check_certificate (X509 **); | ||
38 | + #endif | ||
39 | + | ||
40 | enum { | ||
41 | SMTP_PORT = 25 | ||
42 | }; | ||
43 | const char *SMTP_EXPECT = "220"; | ||
44 | const char *SMTP_HELO = "HELO "; | ||
45 | const char *SMTP_QUIT = "QUIT\r\n"; | ||
46 | + const char *SMTP_STARTTLS = "STARTTLS\r\n"; | ||
47 | |||
48 | int process_arguments (int, char **); | ||
49 | int validate_arguments (void); | ||
50 | void print_help (void); | ||
51 | void print_usage (void); | ||
52 | + int myrecv(void); | ||
53 | + int my_close(void); | ||
54 | |||
55 | #ifdef HAVE_REGEX_H | ||
56 | #include <regex.h> | ||
57 | char regex_expect[MAX_INPUT_BUFFER] = ""; | ||
58 | regex_t preg; | ||
59 | *************** | ||
60 | *** 66,87 **** | ||
61 | int warning_time = 0; | ||
62 | int check_warning_time = FALSE; | ||
63 | int critical_time = 0; | ||
64 | int check_critical_time = FALSE; | ||
65 | int verbose = 0; | ||
66 | ! | ||
67 | ! | ||
68 | |||
69 | int | ||
70 | main (int argc, char **argv) | ||
71 | { | ||
72 | ! int sd; | ||
73 | int n = 0; | ||
74 | double elapsed_time; | ||
75 | long microsec; | ||
76 | int result = STATE_UNKNOWN; | ||
77 | - char buffer[MAX_INPUT_BUFFER]; | ||
78 | char *cmd_str = NULL; | ||
79 | char *helocmd = NULL; | ||
80 | struct timeval tv; | ||
81 | |||
82 | setlocale (LC_ALL, ""); | ||
83 | --- 98,124 ---- | ||
84 | int warning_time = 0; | ||
85 | int check_warning_time = FALSE; | ||
86 | int critical_time = 0; | ||
87 | int check_critical_time = FALSE; | ||
88 | int verbose = 0; | ||
89 | ! int use_ssl = FALSE; | ||
90 | ! int sd; | ||
91 | ! char buffer[MAX_INPUT_BUFFER]; | ||
92 | ! enum { | ||
93 | ! TCP_PROTOCOL = 1, | ||
94 | ! UDP_PROTOCOL = 2, | ||
95 | ! MAXBUF = 1024 | ||
96 | ! }; | ||
97 | |||
98 | int | ||
99 | main (int argc, char **argv) | ||
100 | { | ||
101 | ! | ||
102 | int n = 0; | ||
103 | double elapsed_time; | ||
104 | long microsec; | ||
105 | int result = STATE_UNKNOWN; | ||
106 | char *cmd_str = NULL; | ||
107 | char *helocmd = NULL; | ||
108 | struct timeval tv; | ||
109 | |||
110 | setlocale (LC_ALL, ""); | ||
111 | *************** | ||
112 | *** 138,153 **** | ||
113 | printf (_("Invalid SMTP response received from host on port %d\n"), | ||
114 | server_port); | ||
115 | result = STATE_WARNING; | ||
116 | } | ||
117 | } | ||
118 | ! | ||
119 | /* send the HELO command */ | ||
120 | send(sd, helocmd, strlen(helocmd), 0); | ||
121 | |||
122 | /* allow for response to helo command to reach us */ | ||
123 | ! recv(sd, buffer, MAX_INPUT_BUFFER-1, 0); | ||
124 | |||
125 | /* sendmail will syslog a "NOQUEUE" error if session does not attempt | ||
126 | * to do something useful. This can be prevented by giving a command | ||
127 | * even if syntax is illegal (MAIL requires a FROM:<...> argument) | ||
128 | * | ||
129 | --- 175,223 ---- | ||
130 | printf (_("Invalid SMTP response received from host on port %d\n"), | ||
131 | server_port); | ||
132 | result = STATE_WARNING; | ||
133 | } | ||
134 | } | ||
135 | ! #ifdef HAVE_SSL | ||
136 | ! if(use_ssl) { | ||
137 | ! /* send the STARTTLS command */ | ||
138 | ! send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0); | ||
139 | ! | ||
140 | ! recv(sd,buffer, MAX_INPUT_BUFFER-1, 0); // wait for it | ||
141 | ! if (!strstr (buffer, server_expect)) { | ||
142 | ! printf (_("Server does not support STARTTLS\n")); | ||
143 | ! return STATE_UNKNOWN; | ||
144 | ! } | ||
145 | ! if(connect_STARTTLS() != OK) { | ||
146 | ! printf (_("ERROR: Cannot create SSL context.\n")); | ||
147 | ! return STATE_CRITICAL; | ||
148 | ! } | ||
149 | ! if ( check_cert ) { | ||
150 | ! if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) { | ||
151 | ! result = check_certificate (&server_cert); | ||
152 | ! X509_free(server_cert); | ||
153 | ! } | ||
154 | ! else { | ||
155 | ! printf (_("ERROR: Cannot retrieve server certificate.\n")); | ||
156 | ! result = STATE_CRITICAL; | ||
157 | ! | ||
158 | ! } | ||
159 | ! my_close(); | ||
160 | ! return result; | ||
161 | ! } | ||
162 | ! } | ||
163 | ! #endif | ||
164 | /* send the HELO command */ | ||
165 | + #ifdef HAVE_SSL | ||
166 | + if (use_ssl) | ||
167 | + SSL_write(ssl, helocmd, strlen(helocmd)); | ||
168 | + else | ||
169 | + #endif | ||
170 | send(sd, helocmd, strlen(helocmd), 0); | ||
171 | |||
172 | /* allow for response to helo command to reach us */ | ||
173 | ! myrecv(); | ||
174 | |||
175 | /* sendmail will syslog a "NOQUEUE" error if session does not attempt | ||
176 | * to do something useful. This can be prevented by giving a command | ||
177 | * even if syntax is illegal (MAIL requires a FROM:<...> argument) | ||
178 | * | ||
179 | *************** | ||
180 | *** 156,175 **** | ||
181 | * | ||
182 | * You can disable sending mail_command with '--nocommand' | ||
183 | * Use the -f option to provide a FROM address | ||
184 | */ | ||
185 | if (smtp_use_dummycmd) { | ||
186 | ! send(sd, cmd_str, strlen(cmd_str), 0); | ||
187 | ! recv(sd, buffer, MAX_INPUT_BUFFER-1, 0); | ||
188 | ! if (verbose) | ||
189 | ! printf("%s", buffer); | ||
190 | } | ||
191 | |||
192 | while (n < ncommands) { | ||
193 | asprintf (&cmd_str, "%s%s", commands[n], "\r\n"); | ||
194 | send(sd, cmd_str, strlen(cmd_str), 0); | ||
195 | ! recv(sd, buffer, MAX_INPUT_BUFFER-1, 0); | ||
196 | if (verbose) | ||
197 | printf("%s", buffer); | ||
198 | strip (buffer); | ||
199 | if (n < nresponses) { | ||
200 | #ifdef HAVE_REGEX_H | ||
201 | --- 226,255 ---- | ||
202 | * | ||
203 | * You can disable sending mail_command with '--nocommand' | ||
204 | * Use the -f option to provide a FROM address | ||
205 | */ | ||
206 | if (smtp_use_dummycmd) { | ||
207 | ! #ifdef HAVE_SSL | ||
208 | ! if (use_ssl) | ||
209 | ! SSL_write(ssl, cmd_str, strlen(cmd_str)); | ||
210 | ! else | ||
211 | ! #endif | ||
212 | ! send(sd, cmd_str, strlen(cmd_str), 0); | ||
213 | ! myrecv(); | ||
214 | ! if (verbose) | ||
215 | ! printf("%s", buffer); | ||
216 | } | ||
217 | |||
218 | while (n < ncommands) { | ||
219 | asprintf (&cmd_str, "%s%s", commands[n], "\r\n"); | ||
220 | + #ifdef HAVE_SSL | ||
221 | + if (use_ssl) | ||
222 | + SSL_write(ssl,cmd_str, strlen(cmd_str)); | ||
223 | + else | ||
224 | + #endif | ||
225 | send(sd, cmd_str, strlen(cmd_str), 0); | ||
226 | ! myrecv(); | ||
227 | if (verbose) | ||
228 | printf("%s", buffer); | ||
229 | strip (buffer); | ||
230 | if (n < nresponses) { | ||
231 | #ifdef HAVE_REGEX_H | ||
232 | *************** | ||
233 | *** 204,213 **** | ||
234 | --- 284,298 ---- | ||
235 | } | ||
236 | n++; | ||
237 | } | ||
238 | |||
239 | /* tell the server we're done */ | ||
240 | + #ifdef HAVE_SSL | ||
241 | + if (use_ssl) | ||
242 | + SSL_write(ssl,SMTP_QUIT, strlen (SMTP_QUIT)); | ||
243 | + else | ||
244 | + #endif | ||
245 | send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0); | ||
246 | |||
247 | /* finally close the connection */ | ||
248 | close (sd); | ||
249 | } | ||
250 | *************** | ||
251 | *** 259,268 **** | ||
252 | --- 344,355 ---- | ||
253 | {"verbose", no_argument, 0, 'v'}, | ||
254 | {"version", no_argument, 0, 'V'}, | ||
255 | {"use-ipv4", no_argument, 0, '4'}, | ||
256 | {"use-ipv6", no_argument, 0, '6'}, | ||
257 | {"help", no_argument, 0, 'h'}, | ||
258 | + {"starttls",no_argument,0,'S'}, | ||
259 | + {"certificate",required_argument,0,'D'}, | ||
260 | {0, 0, 0, 0} | ||
261 | }; | ||
262 | |||
263 | if (argc < 2) | ||
264 | return ERROR; | ||
265 | *************** | ||
266 | *** 275,285 **** | ||
267 | else if (strcmp ("-ct", argv[c]) == 0) | ||
268 | strcpy (argv[c], "-c"); | ||
269 | } | ||
270 | |||
271 | while (1) { | ||
272 | ! c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:", | ||
273 | longopts, &option); | ||
274 | |||
275 | if (c == -1 || c == EOF) | ||
276 | break; | ||
277 | |||
278 | --- 362,372 ---- | ||
279 | else if (strcmp ("-ct", argv[c]) == 0) | ||
280 | strcpy (argv[c], "-c"); | ||
281 | } | ||
282 | |||
283 | while (1) { | ||
284 | ! c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:SD:", | ||
285 | longopts, &option); | ||
286 | |||
287 | if (c == -1 || c == EOF) | ||
288 | break; | ||
289 | |||
290 | *************** | ||
291 | *** 352,361 **** | ||
292 | --- 439,464 ---- | ||
293 | } | ||
294 | else { | ||
295 | usage4 (_("Time interval must be a positive integer")); | ||
296 | } | ||
297 | break; | ||
298 | + case 'S': | ||
299 | + /* starttls */ | ||
300 | + use_ssl = TRUE; | ||
301 | + break; | ||
302 | + case 'D': | ||
303 | + /* Check SSL cert validity */ | ||
304 | + #ifdef HAVE_SSL | ||
305 | + if (!is_intnonneg (optarg)) | ||
306 | + usage2 ("invalid certificate expiration period",optarg); | ||
307 | + days_till_exp = atoi (optarg); | ||
308 | + check_cert = TRUE; | ||
309 | + #else | ||
310 | + terminate (STATE_UNKNOWN, | ||
311 | + "SSL support not available. Install OpenSSL and recompile."); | ||
312 | + #endif | ||
313 | + break; | ||
314 | case '4': | ||
315 | address_family = AF_INET; | ||
316 | break; | ||
317 | case '6': | ||
318 | #ifdef USE_IPV6 | ||
319 | *************** | ||
320 | *** 443,452 **** | ||
321 | --- 546,562 ---- | ||
322 | -R, --command=STRING\n\ | ||
323 | Expected response to command (may be used repeatedly)\n\ | ||
324 | -f, --from=STRING\n\ | ||
325 | FROM-address to include in MAIL command, required by Exchange 2000\n"), | ||
326 | SMTP_EXPECT); | ||
327 | + #ifdef HAVE_SSL | ||
328 | + printf (_("\ | ||
329 | + -D, --certificate=INTEGER\n\ | ||
330 | + Minimum number of days a certificate has to be valid.\n\ | ||
331 | + -S, --starttls\n\ | ||
332 | + Use STARTTLS for the connection.\n")); | ||
333 | + #endif | ||
334 | |||
335 | printf (_(UT_WARN_CRIT)); | ||
336 | |||
337 | printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); | ||
338 | |||
339 | *************** | ||
340 | *** 466,472 **** | ||
341 | void | ||
342 | print_usage (void) | ||
343 | { | ||
344 | printf ("\ | ||
345 | Usage: %s -H host [-p port] [-e expect] [-C command] [-f from addr]\n\ | ||
346 | ! [-w warn] [-c crit] [-t timeout] [-n] [-v] [-4|-6]\n", progname); | ||
347 | } | ||
348 | --- 576,731 ---- | ||
349 | void | ||
350 | print_usage (void) | ||
351 | { | ||
352 | printf ("\ | ||
353 | Usage: %s -H host [-p port] [-e expect] [-C command] [-f from addr]\n\ | ||
354 | ! [-w warn] [-c crit] [-t timeout] [-S] [-D days] [-n] [-v] [-4|-6]\n", progname); | ||
355 | ! } | ||
356 | ! | ||
357 | ! #ifdef HAVE_SSL | ||
358 | ! int | ||
359 | ! connect_STARTTLS (void) | ||
360 | ! { | ||
361 | ! SSL_METHOD *meth; | ||
362 | ! | ||
363 | ! /* Initialize SSL context */ | ||
364 | ! SSLeay_add_ssl_algorithms (); | ||
365 | ! meth = SSLv2_client_method (); | ||
366 | ! SSL_load_error_strings (); | ||
367 | ! if ((ctx = SSL_CTX_new (meth)) == NULL) | ||
368 | ! { | ||
369 | ! printf(_("ERROR: Cannot create SSL context.\n")); | ||
370 | ! return STATE_CRITICAL; | ||
371 | ! } | ||
372 | ! /* do the SSL handshake */ | ||
373 | ! if ((ssl = SSL_new (ctx)) != NULL) | ||
374 | ! { | ||
375 | ! SSL_set_fd (ssl, sd); | ||
376 | ! /* original version checked for -1 | ||
377 | ! I look for success instead (1) */ | ||
378 | ! if (SSL_connect (ssl) == 1) | ||
379 | ! return OK; | ||
380 | ! ERR_print_errors_fp (stderr); | ||
381 | ! } | ||
382 | ! else | ||
383 | ! { | ||
384 | ! printf (_("ERROR: Cannot initiate SSL handshake.\n")); | ||
385 | ! } | ||
386 | ! /* this causes a seg faul | ||
387 | ! not sure why, being sloppy | ||
388 | ! and commenting it out */ | ||
389 | ! // SSL_free (ssl); | ||
390 | ! SSL_CTX_free(ctx); | ||
391 | ! my_close(); | ||
392 | ! | ||
393 | ! return STATE_CRITICAL; | ||
394 | ! } | ||
395 | ! | ||
396 | ! int | ||
397 | ! check_certificate (X509 ** certificate) | ||
398 | ! { | ||
399 | ! ASN1_STRING *tm; | ||
400 | ! int offset; | ||
401 | ! struct tm stamp; | ||
402 | ! int days_left; | ||
403 | ! | ||
404 | ! /* Retrieve timestamp of certificate */ | ||
405 | ! tm = X509_get_notAfter (*certificate); | ||
406 | ! | ||
407 | ! /* Generate tm structure to process timestamp */ | ||
408 | ! if (tm->type == V_ASN1_UTCTIME) { | ||
409 | ! if (tm->length < 10) { | ||
410 | ! printf (_("ERROR: Wrong time format in certificate.\n")); | ||
411 | ! return STATE_CRITICAL; | ||
412 | ! } | ||
413 | ! else { | ||
414 | ! stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0'); | ||
415 | ! if (stamp.tm_year < 50) | ||
416 | ! stamp.tm_year += 100; | ||
417 | ! offset = 0; | ||
418 | ! } | ||
419 | ! } | ||
420 | ! else { | ||
421 | ! if (tm->length < 12) { | ||
422 | ! printf (_("ERROR: Wrong time format in certificate.\n")); | ||
423 | ! return STATE_CRITICAL; | ||
424 | ! } | ||
425 | ! else { | ||
426 | ! stamp.tm_year = | ||
427 | ! (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 + | ||
428 | ! (tm->data[2] - '0') * 10 + (tm->data[3] - '0'); | ||
429 | ! stamp.tm_year -= 1900; | ||
430 | ! offset = 2; | ||
431 | ! } | ||
432 | ! } | ||
433 | ! stamp.tm_mon = | ||
434 | ! (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1; | ||
435 | ! stamp.tm_mday = | ||
436 | ! (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0'); | ||
437 | ! stamp.tm_hour = | ||
438 | ! (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0'); | ||
439 | ! stamp.tm_min = | ||
440 | ! (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0'); | ||
441 | ! stamp.tm_sec = 0; | ||
442 | ! stamp.tm_isdst = -1; | ||
443 | ! | ||
444 | ! days_left = (mktime (&stamp) - time (NULL)) / 86400; | ||
445 | ! snprintf | ||
446 | ! (timestamp, 16, "%02d/%02d/%04d %02d:%02d", | ||
447 | ! stamp.tm_mon + 1, | ||
448 | ! stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min); | ||
449 | ! | ||
450 | ! if (days_left > 0 && days_left <= days_till_exp) { | ||
451 | ! printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp); | ||
452 | ! return STATE_WARNING; | ||
453 | ! } | ||
454 | ! if (days_left < 0) { | ||
455 | ! printf ("Certificate expired on %s.\n", timestamp); | ||
456 | ! return STATE_CRITICAL; | ||
457 | ! } | ||
458 | ! | ||
459 | ! if (days_left == 0) { | ||
460 | ! printf ("Certificate expires today (%s).\n", timestamp); | ||
461 | ! return STATE_WARNING; | ||
462 | ! } | ||
463 | ! | ||
464 | ! printf ("Certificate will expire on %s.\n", timestamp); | ||
465 | ! | ||
466 | ! return STATE_OK; | ||
467 | ! } | ||
468 | ! #endif | ||
469 | ! | ||
470 | ! int | ||
471 | ! myrecv (void) | ||
472 | ! { | ||
473 | ! int i; | ||
474 | ! | ||
475 | ! #ifdef HAVE_SSL | ||
476 | ! if (use_ssl) { | ||
477 | ! i = SSL_read (ssl, buffer, MAXBUF - 1); | ||
478 | ! } | ||
479 | ! else { | ||
480 | ! #endif | ||
481 | ! i = read (sd, buffer, MAXBUF - 1); | ||
482 | ! #ifdef HAVE_SSL | ||
483 | ! } | ||
484 | ! #endif | ||
485 | ! return i; | ||
486 | ! } | ||
487 | ! | ||
488 | ! int | ||
489 | ! my_close (void) | ||
490 | ! { | ||
491 | ! #ifdef HAVE_SSL | ||
492 | ! if (use_ssl == TRUE) { | ||
493 | ! SSL_shutdown (ssl); | ||
494 | ! SSL_free (ssl); | ||
495 | ! SSL_CTX_free (ctx); | ||
496 | ! return 0; | ||
497 | ! } | ||
498 | ! else { | ||
499 | ! #endif | ||
500 | ! return close(sd); | ||
501 | ! #ifdef HAVE_SSL | ||
502 | ! } | ||
503 | ! #endif | ||
504 | } | ||