summaryrefslogtreecommitdiffstats
path: root/web/attachments/104059-check_smtp.c.patch
diff options
context:
space:
mode:
Diffstat (limited to 'web/attachments/104059-check_smtp.c.patch')
-rw-r--r--web/attachments/104059-check_smtp.c.patch491
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 }