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