summaryrefslogtreecommitdiffstats
path: root/web/attachments/112577-check_smtp.c.patch.cvs.HEAD.20041215
diff options
context:
space:
mode:
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.20041215504
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 }