summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-10 01:31:52 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-10 01:31:52 +0100
commit883fcb607f9b3e810e22b2e21da7441a073b6e32 (patch)
tree89297b6448f6e56f402dbc5baff082e495fdf17a /plugins
parent0867319268898bc63f483e6257c65123e10603ba (diff)
downloadmonitoring-plugins-883fcb607f9b3e810e22b2e21da7441a073b6e32.tar.gz
Refactor check_smtp
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am3
-rw-r--r--plugins/check_smtp.c518
-rw-r--r--plugins/check_smtp.d/config.h92
3 files changed, 343 insertions, 270 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6ee93c18..5e8f0650 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -52,7 +52,8 @@ EXTRA_DIST = t \
52 check_swap.d \ 52 check_swap.d \
53 check_dbi.d \ 53 check_dbi.d \
54 check_ssh.d \ 54 check_ssh.d \
55 check_dns.d 55 check_dns.d \
56 check_smtp.d
56 57
57PLUGINHDRS = common.h 58PLUGINHDRS = common.h
58 59
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index bb45e01b..0be02937 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -28,6 +28,7 @@
28 * 28 *
29 *****************************************************************************/ 29 *****************************************************************************/
30 30
31#include "states.h"
31const char *progname = "check_smtp"; 32const char *progname = "check_smtp";
32const char *copyright = "2000-2024"; 33const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
@@ -36,21 +37,12 @@ const char *email = "devel@monitoring-plugins.org";
36#include "netutils.h" 37#include "netutils.h"
37#include "utils.h" 38#include "utils.h"
38#include "base64.h" 39#include "base64.h"
40#include "regex.h"
39 41
40#include <ctype.h> 42#include <ctype.h>
41 43#include "check_smtp.d/config.h"
42#ifdef HAVE_SSL
43static bool check_cert = false;
44static int days_till_exp_warn, days_till_exp_crit;
45# define my_recv(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
46# define my_send(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
47#else /* ifndef HAVE_SSL */
48# define my_recv(buf, len) read(sd, buf, len)
49# define my_send(buf, len) send(sd, buf, len, 0)
50#endif
51 44
52#define PROXY_PREFIX "PROXY TCP4 0.0.0.0 0.0.0.0 25 25\r\n" 45#define PROXY_PREFIX "PROXY TCP4 0.0.0.0 0.0.0.0 25 25\r\n"
53#define SMTP_EXPECT "220"
54#define SMTP_HELO "HELO " 46#define SMTP_HELO "HELO "
55#define SMTP_EHLO "EHLO " 47#define SMTP_EHLO "EHLO "
56#define SMTP_LHLO "LHLO " 48#define SMTP_LHLO "LHLO "
@@ -60,71 +52,51 @@ static int days_till_exp_warn, days_till_exp_crit;
60 52
61#define EHLO_SUPPORTS_STARTTLS 1 53#define EHLO_SUPPORTS_STARTTLS 1
62 54
63static int process_arguments (int, char **); 55typedef struct {
64static int validate_arguments (void); 56 int errorcode;
65static void print_help (void); 57 check_smtp_config config;
66void print_usage (void); 58} check_smtp_config_wrapper;
67static void smtp_quit(void); 59static check_smtp_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
68static int recvline(char *, size_t); 60
69static int recvlines(char *, size_t); 61int my_recv(check_smtp_config config, void *buf, int num, int socket_descriptor, bool ssl_established) {
70static int my_close(void); 62#ifdef HAVE_SSL
63 if ((config.use_starttls || config.use_ssl) && ssl_established) {
64 return np_net_ssl_read(buf, num);
65 }
66 return (int)read(socket_descriptor, buf, (size_t)num);
67#else /* ifndef HAVE_SSL */
68 return read(socket_descriptor, buf, len)
69#endif
70}
71
72int my_send(check_smtp_config config, void *buf, int num, int socket_descriptor, bool ssl_established) {
73#ifdef HAVE_SSL
74 if ((config.use_starttls || config.use_ssl) && ssl_established) {
75
76 return np_net_ssl_write(buf, num);
77 }
78 return (int)send(socket_descriptor, buf, (size_t)num, 0);
79#else /* ifndef HAVE_SSL */
80 return send(socket_descriptor, buf, len, 0);
81#endif
82}
83
84static void print_help(void);
85void print_usage(void);
86static char *smtp_quit(check_smtp_config /*config*/, char /*buffer*/[MAX_INPUT_BUFFER], int /*socket_descriptor*/,
87 bool /*ssl_established*/);
88static int recvline(char * /*buf*/, size_t /*bufsize*/, check_smtp_config /*config*/, int /*socket_descriptor*/, bool /*ssl_established*/);
89static int recvlines(check_smtp_config /*config*/, char * /*buf*/, size_t /*bufsize*/, int /*socket_descriptor*/, bool /*ssl_established*/);
90static int my_close(int /*socket_descriptor*/);
71 91
72#include "regex.h"
73static regex_t preg;
74static regmatch_t pmatch[10];
75static char errbuf[MAX_INPUT_BUFFER];
76static int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
77static int eflags = 0;
78static int errcode, excode;
79
80static int server_port_option = 0;
81static char *server_address = NULL;
82static char *server_expect = NULL;
83static char *mail_command = NULL;
84static char *from_arg = NULL;
85static int send_mail_from = 0;
86static int ncommands = 0;
87static int command_size = 0;
88static int nresponses = 0;
89static int response_size = 0;
90static char **commands = NULL;
91static char **responses = NULL;
92static char *authtype = NULL;
93static char *authuser = NULL;
94static char *authpass = NULL;
95static double warning_time = 0;
96static bool check_warning_time = false;
97static double critical_time = 0;
98static bool check_critical_time = false;
99static int verbose = 0; 92static int verbose = 0;
100static bool use_ssl = false; 93
101static bool use_starttls = false;
102static bool use_sni = false;
103static bool use_proxy_prefix = false;
104static bool use_ehlo = false;
105static bool use_lhlo = false;
106static bool ssl_established = false;
107static char *localhostname = NULL;
108static int sd;
109static char buffer[MAX_INPUT_BUFFER];
110enum { 94enum {
111 TCP_PROTOCOL = 1, 95 TCP_PROTOCOL = 1,
112 UDP_PROTOCOL = 2, 96 UDP_PROTOCOL = 2,
113}; 97};
114static bool ignore_send_quit_failure = false;
115 98
116int main(int argc, char **argv) { 99int main(int argc, char **argv) {
117 bool supports_tls = false;
118 int n = 0;
119 double elapsed_time;
120 long microsec;
121 int result = STATE_UNKNOWN;
122 char *cmd_str = NULL;
123 char *helocmd = NULL;
124 char *error_msg = "";
125 char *server_response = NULL;
126 struct timeval tv;
127
128 /* Catch pipe errors in read/write - sometimes occurs when writing QUIT */ 100 /* Catch pipe errors in read/write - sometimes occurs when writing QUIT */
129 (void)signal(SIGPIPE, SIG_IGN); 101 (void)signal(SIGPIPE, SIG_IGN);
130 102
@@ -135,25 +107,31 @@ int main(int argc, char **argv) {
135 /* Parse extra opts if any */ 107 /* Parse extra opts if any */
136 argv = np_extra_opts(&argc, argv, progname); 108 argv = np_extra_opts(&argc, argv, progname);
137 109
138 if (process_arguments(argc, argv) == ERROR) { 110 check_smtp_config_wrapper tmp_config = process_arguments(argc, argv);
111
112 if (tmp_config.errorcode == ERROR) {
139 usage4(_("Could not parse arguments")); 113 usage4(_("Could not parse arguments"));
140 } 114 }
141 115
116 const check_smtp_config config = tmp_config.config;
117
142 /* If localhostname not set on command line, use gethostname to set */ 118 /* If localhostname not set on command line, use gethostname to set */
119 char *localhostname = config.localhostname;
143 if (!localhostname) { 120 if (!localhostname) {
144 localhostname = malloc(HOST_MAX_BYTES); 121 localhostname = malloc(HOST_MAX_BYTES);
145 if (!localhostname) { 122 if (!localhostname) {
146 printf(_("malloc() failed!\n")); 123 printf(_("malloc() failed!\n"));
147 return STATE_CRITICAL; 124 exit(STATE_CRITICAL);
148 } 125 }
149 if (gethostname(localhostname, HOST_MAX_BYTES)) { 126 if (gethostname(localhostname, HOST_MAX_BYTES)) {
150 printf(_("gethostname() failed!\n")); 127 printf(_("gethostname() failed!\n"));
151 return STATE_CRITICAL; 128 exit(STATE_CRITICAL);
152 } 129 }
153 } 130 }
154 if (use_lhlo) { 131 char *helocmd = NULL;
132 if (config.use_lhlo) {
155 xasprintf(&helocmd, "%s%s%s", SMTP_LHLO, localhostname, "\r\n"); 133 xasprintf(&helocmd, "%s%s%s", SMTP_LHLO, localhostname, "\r\n");
156 } else if (use_ehlo) { 134 } else if (config.use_ehlo) {
157 xasprintf(&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n"); 135 xasprintf(&helocmd, "%s%s%s", SMTP_EHLO, localhostname, "\r\n");
158 } else { 136 } else {
159 xasprintf(&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n"); 137 xasprintf(&helocmd, "%s%s%s", SMTP_HELO, localhostname, "\r\n");
@@ -163,10 +141,13 @@ int main(int argc, char **argv) {
163 printf("HELOCMD: %s", helocmd); 141 printf("HELOCMD: %s", helocmd);
164 } 142 }
165 143
144 char *mail_command = strdup("MAIL ");
145
146 char *cmd_str = NULL;
166 /* initialize the MAIL command with optional FROM command */ 147 /* initialize the MAIL command with optional FROM command */
167 xasprintf(&cmd_str, "%sFROM:<%s>%s", mail_command, from_arg, "\r\n"); 148 xasprintf(&cmd_str, "%sFROM:<%s>%s", mail_command, config.from_arg, "\r\n");
168 149
169 if (verbose && send_mail_from) { 150 if (verbose && config.send_mail_from) {
170 printf("FROM CMD: %s", cmd_str); 151 printf("FROM CMD: %s", cmd_str);
171 } 152 }
172 153
@@ -176,84 +157,90 @@ int main(int argc, char **argv) {
176 /* set socket timeout */ 157 /* set socket timeout */
177 (void)alarm(socket_timeout); 158 (void)alarm(socket_timeout);
178 159
160 struct timeval start_time;
179 /* start timer */ 161 /* start timer */
180 gettimeofday(&tv, NULL); 162 gettimeofday(&start_time, NULL);
181 163
164 int socket_descriptor = 0;
182 /* try to connect to the host at the given port number */ 165 /* try to connect to the host at the given port number */
183 result = my_tcp_connect(server_address, server_port, &sd); 166 mp_state_enum result = my_tcp_connect(config.server_address, config.server_port, &socket_descriptor);
184 167
168 char *error_msg = "";
169 char buffer[MAX_INPUT_BUFFER];
170 bool ssl_established = false;
185 if (result == STATE_OK) { /* we connected */ 171 if (result == STATE_OK) { /* we connected */
186 /* If requested, send PROXY header */ 172 /* If requested, send PROXY header */
187 if (use_proxy_prefix) { 173 if (config.use_proxy_prefix) {
188 if (verbose) { 174 if (verbose) {
189 printf("Sending header %s\n", PROXY_PREFIX); 175 printf("Sending header %s\n", PROXY_PREFIX);
190 } 176 }
191 my_send(PROXY_PREFIX, strlen(PROXY_PREFIX)); 177 my_send(config, PROXY_PREFIX, strlen(PROXY_PREFIX), socket_descriptor, ssl_established);
192 } 178 }
193 179
194#ifdef HAVE_SSL 180#ifdef HAVE_SSL
195 if (use_ssl) { 181 if (config.use_ssl) {
196 result = np_net_ssl_init_with_hostname(sd, (use_sni ? server_address : NULL)); 182 result = np_net_ssl_init_with_hostname(socket_descriptor, (config.use_sni ? config.server_address : NULL));
197 if (result != STATE_OK) { 183 if (result != STATE_OK) {
198 printf(_("CRITICAL - Cannot create SSL context.\n")); 184 printf(_("CRITICAL - Cannot create SSL context.\n"));
199 close(sd); 185 close(socket_descriptor);
200 np_net_ssl_cleanup(); 186 np_net_ssl_cleanup();
201 return STATE_CRITICAL; 187 exit(STATE_CRITICAL);
202 } else {
203 ssl_established = 1;
204 } 188 }
189 ssl_established = true;
205 } 190 }
206#endif 191#endif
207 192
208 /* watch for the SMTP connection string and */ 193 /* watch for the SMTP connection string and */
209 /* return a WARNING status if we couldn't read any data */ 194 /* return a WARNING status if we couldn't read any data */
210 if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) { 195 if (recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established) <= 0) {
211 printf(_("recv() failed\n")); 196 printf(_("recv() failed\n"));
212 return STATE_WARNING; 197 exit(STATE_WARNING);
213 } 198 }
214 199
200 char *server_response = NULL;
215 /* save connect return (220 hostname ..) for later use */ 201 /* save connect return (220 hostname ..) for later use */
216 xasprintf(&server_response, "%s", buffer); 202 xasprintf(&server_response, "%s", buffer);
217 203
218 /* send the HELO/EHLO command */ 204 /* send the HELO/EHLO command */
219 my_send(helocmd, strlen(helocmd)); 205 my_send(config, helocmd, (int)strlen(helocmd), socket_descriptor, ssl_established);
220 206
221 /* allow for response to helo command to reach us */ 207 /* allow for response to helo command to reach us */
222 if (recvlines(buffer, MAX_INPUT_BUFFER) <= 0) { 208 if (recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established) <= 0) {
223 printf(_("recv() failed\n")); 209 printf(_("recv() failed\n"));
224 return STATE_WARNING; 210 exit(STATE_WARNING);
225 } else if (use_ehlo || use_lhlo) { 211 }
212 bool supports_tls = false;
213 if (config.use_ehlo || config.use_lhlo) {
226 if (strstr(buffer, "250 STARTTLS") != NULL || strstr(buffer, "250-STARTTLS") != NULL) { 214 if (strstr(buffer, "250 STARTTLS") != NULL || strstr(buffer, "250-STARTTLS") != NULL) {
227 supports_tls = true; 215 supports_tls = true;
228 } 216 }
229 } 217 }
230 218
231 if (use_starttls && !supports_tls) { 219 if (config.use_starttls && !supports_tls) {
232 printf(_("WARNING - TLS not supported by server\n")); 220 printf(_("WARNING - TLS not supported by server\n"));
233 smtp_quit(); 221 smtp_quit(config, buffer, socket_descriptor, ssl_established);
234 return STATE_WARNING; 222 exit(STATE_WARNING);
235 } 223 }
236 224
237#ifdef HAVE_SSL 225#ifdef HAVE_SSL
238 if (use_starttls) { 226 if (config.use_starttls) {
239 /* send the STARTTLS command */ 227 /* send the STARTTLS command */
240 send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0); 228 send(socket_descriptor, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0);
241 229
242 recvlines(buffer, MAX_INPUT_BUFFER); /* wait for it */ 230 recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established); /* wait for it */
243 if (!strstr(buffer, SMTP_EXPECT)) { 231 if (!strstr(buffer, SMTP_EXPECT)) {
244 printf(_("Server does not support STARTTLS\n")); 232 printf(_("Server does not support STARTTLS\n"));
245 smtp_quit(); 233 smtp_quit(config, buffer, socket_descriptor, ssl_established);
246 return STATE_UNKNOWN; 234 exit(STATE_UNKNOWN);
247 } 235 }
248 result = np_net_ssl_init_with_hostname(sd, (use_sni ? server_address : NULL)); 236 result = np_net_ssl_init_with_hostname(socket_descriptor, (config.use_sni ? config.server_address : NULL));
249 if (result != STATE_OK) { 237 if (result != STATE_OK) {
250 printf(_("CRITICAL - Cannot create SSL context.\n")); 238 printf(_("CRITICAL - Cannot create SSL context.\n"));
251 close(sd); 239 close(socket_descriptor);
252 np_net_ssl_cleanup(); 240 np_net_ssl_cleanup();
253 return STATE_CRITICAL; 241 exit(STATE_CRITICAL);
254 } else {
255 ssl_established = 1;
256 } 242 }
243 ssl_established = true;
257 244
258 /* 245 /*
259 * Resend the EHLO command. 246 * Resend the EHLO command.
@@ -266,29 +253,32 @@ int main(int argc, char **argv) {
266 * reason, some MTAs will not allow an AUTH LOGIN command before 253 * reason, some MTAs will not allow an AUTH LOGIN command before
267 * we resent EHLO via TLS. 254 * we resent EHLO via TLS.
268 */ 255 */
269 if (my_send(helocmd, strlen(helocmd)) <= 0) { 256 if (my_send(config, helocmd, strlen(helocmd), socket_descriptor, ssl_established) <= 0) {
270 printf("%s\n", _("SMTP UNKNOWN - Cannot send EHLO command via TLS.")); 257 printf("%s\n", _("SMTP UNKNOWN - Cannot send EHLO command via TLS."));
271 my_close(); 258 my_close(socket_descriptor);
272 return STATE_UNKNOWN; 259 exit(STATE_UNKNOWN);
273 } 260 }
261
274 if (verbose) { 262 if (verbose) {
275 printf(_("sent %s"), helocmd); 263 printf(_("sent %s"), helocmd);
276 } 264 }
277 if ((n = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 265
266 if (recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established) <= 0) {
278 printf("%s\n", _("SMTP UNKNOWN - Cannot read EHLO response via TLS.")); 267 printf("%s\n", _("SMTP UNKNOWN - Cannot read EHLO response via TLS."));
279 my_close(); 268 my_close(socket_descriptor);
280 return STATE_UNKNOWN; 269 exit(STATE_UNKNOWN);
281 } 270 }
271
282 if (verbose) { 272 if (verbose) {
283 printf("%s", buffer); 273 printf("%s", buffer);
284 } 274 }
285 275
286# ifdef USE_OPENSSL 276# ifdef USE_OPENSSL
287 if (check_cert) { 277 if (config.check_cert) {
288 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 278 result = np_net_ssl_check_cert(config.days_till_exp_warn, config.days_till_exp_crit);
289 smtp_quit(); 279 smtp_quit(config, buffer, socket_descriptor, ssl_established);
290 my_close(); 280 my_close(socket_descriptor);
291 return result; 281 exit(result);
292 } 282 }
293# endif /* USE_OPENSSL */ 283# endif /* USE_OPENSSL */
294 } 284 }
@@ -304,76 +294,81 @@ int main(int argc, char **argv) {
304 strip(server_response); 294 strip(server_response);
305 295
306 /* make sure we find the droids we are looking for */ 296 /* make sure we find the droids we are looking for */
307 if (!strstr(server_response, server_expect)) { 297 if (!strstr(server_response, config.server_expect)) {
308 if (server_port == SMTP_PORT) { 298 if (config.server_port == SMTP_PORT) {
309 printf(_("Invalid SMTP response received from host: %s\n"), server_response); 299 printf(_("Invalid SMTP response received from host: %s\n"), server_response);
310 } else { 300 } else {
311 printf(_("Invalid SMTP response received from host on port %d: %s\n"), server_port, server_response); 301 printf(_("Invalid SMTP response received from host on port %d: %s\n"), config.server_port, server_response);
312 } 302 }
313 return STATE_WARNING; 303 exit(STATE_WARNING);
314 } 304 }
315 305
316 if (send_mail_from) { 306 if (config.send_mail_from) {
317 my_send(cmd_str, strlen(cmd_str)); 307 my_send(config, cmd_str, (int)strlen(cmd_str), socket_descriptor, ssl_established);
318 if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose) { 308 if (recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established) >= 1 && verbose) {
319 printf("%s", buffer); 309 printf("%s", buffer);
320 } 310 }
321 } 311 }
322 312
323 n = 0; 313 int counter = 0;
324 while (n < ncommands) { 314 while (counter < config.ncommands) {
325 xasprintf(&cmd_str, "%s%s", commands[n], "\r\n"); 315 xasprintf(&cmd_str, "%s%s", config.commands[counter], "\r\n");
326 my_send(cmd_str, strlen(cmd_str)); 316 my_send(config, cmd_str, (int)strlen(cmd_str), socket_descriptor, ssl_established);
327 if (recvlines(buffer, MAX_INPUT_BUFFER) >= 1 && verbose) { 317 if (recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established) >= 1 && verbose) {
328 printf("%s", buffer); 318 printf("%s", buffer);
329 } 319 }
330 strip(buffer); 320 strip(buffer);
331 if (n < nresponses) { 321 if (counter < config.nresponses) {
332 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 322 int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
333 errcode = regcomp(&preg, responses[n], cflags); 323 regex_t preg;
324 int errcode = regcomp(&preg, config.responses[counter], cflags);
325 char errbuf[MAX_INPUT_BUFFER];
334 if (errcode != 0) { 326 if (errcode != 0) {
335 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER); 327 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
336 printf(_("Could Not Compile Regular Expression")); 328 printf(_("Could Not Compile Regular Expression"));
337 return ERROR; 329 exit(STATE_UNKNOWN);
338 } 330 }
339 excode = regexec(&preg, buffer, 10, pmatch, eflags); 331
332 regmatch_t pmatch[10];
333 int eflags = 0;
334 int excode = regexec(&preg, buffer, 10, pmatch, eflags);
340 if (excode == 0) { 335 if (excode == 0) {
341 result = STATE_OK; 336 result = STATE_OK;
342 } else if (excode == REG_NOMATCH) { 337 } else if (excode == REG_NOMATCH) {
343 result = STATE_WARNING; 338 result = STATE_WARNING;
344 printf(_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text(result), buffer, commands[n]); 339 printf(_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text(result), buffer, config.commands[counter]);
345 } else { 340 } else {
346 regerror(excode, &preg, errbuf, MAX_INPUT_BUFFER); 341 regerror(excode, &preg, errbuf, MAX_INPUT_BUFFER);
347 printf(_("Execute Error: %s\n"), errbuf); 342 printf(_("Execute Error: %s\n"), errbuf);
348 result = STATE_UNKNOWN; 343 result = STATE_UNKNOWN;
349 } 344 }
350 } 345 }
351 n++; 346 counter++;
352 } 347 }
353 348
354 if (authtype != NULL) { 349 if (config.authtype != NULL) {
355 if (strcmp(authtype, "LOGIN") == 0) { 350 if (strcmp(config.authtype, "LOGIN") == 0) {
356 char *abuf; 351 char *abuf;
357 int ret; 352 int ret;
358 do { 353 do {
359 if (authuser == NULL) { 354 if (config.authuser == NULL) {
360 result = STATE_CRITICAL; 355 result = STATE_CRITICAL;
361 xasprintf(&error_msg, _("no authuser specified, ")); 356 xasprintf(&error_msg, _("no authuser specified, "));
362 break; 357 break;
363 } 358 }
364 if (authpass == NULL) { 359 if (config.authpass == NULL) {
365 result = STATE_CRITICAL; 360 result = STATE_CRITICAL;
366 xasprintf(&error_msg, _("no authpass specified, ")); 361 xasprintf(&error_msg, _("no authpass specified, "));
367 break; 362 break;
368 } 363 }
369 364
370 /* send AUTH LOGIN */ 365 /* send AUTH LOGIN */
371 my_send(SMTP_AUTH_LOGIN, strlen(SMTP_AUTH_LOGIN)); 366 my_send(config, SMTP_AUTH_LOGIN, strlen(SMTP_AUTH_LOGIN), socket_descriptor, ssl_established);
372 if (verbose) { 367 if (verbose) {
373 printf(_("sent %s\n"), "AUTH LOGIN"); 368 printf(_("sent %s\n"), "AUTH LOGIN");
374 } 369 }
375 370
376 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 371 if ((ret = recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established)) <= 0) {
377 xasprintf(&error_msg, _("recv() failed after AUTH LOGIN, ")); 372 xasprintf(&error_msg, _("recv() failed after AUTH LOGIN, "));
378 result = STATE_WARNING; 373 result = STATE_WARNING;
379 break; 374 break;
@@ -389,14 +384,14 @@ int main(int argc, char **argv) {
389 } 384 }
390 385
391 /* encode authuser with base64 */ 386 /* encode authuser with base64 */
392 base64_encode_alloc(authuser, strlen(authuser), &abuf); 387 base64_encode_alloc(config.authuser, strlen(config.authuser), &abuf);
393 xasprintf(&abuf, "%s\r\n", abuf); 388 xasprintf(&abuf, "%s\r\n", abuf);
394 my_send(abuf, strlen(abuf)); 389 my_send(config, abuf, (int)strlen(abuf), socket_descriptor, ssl_established);
395 if (verbose) { 390 if (verbose) {
396 printf(_("sent %s\n"), abuf); 391 printf(_("sent %s\n"), abuf);
397 } 392 }
398 393
399 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 394 if ((ret = recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established)) <= 0) {
400 result = STATE_CRITICAL; 395 result = STATE_CRITICAL;
401 xasprintf(&error_msg, _("recv() failed after sending authuser, ")); 396 xasprintf(&error_msg, _("recv() failed after sending authuser, "));
402 break; 397 break;
@@ -410,13 +405,13 @@ int main(int argc, char **argv) {
410 break; 405 break;
411 } 406 }
412 /* encode authpass with base64 */ 407 /* encode authpass with base64 */
413 base64_encode_alloc(authpass, strlen(authpass), &abuf); 408 base64_encode_alloc(config.authpass, strlen(config.authpass), &abuf);
414 xasprintf(&abuf, "%s\r\n", abuf); 409 xasprintf(&abuf, "%s\r\n", abuf);
415 my_send(abuf, strlen(abuf)); 410 my_send(config, abuf, (int)strlen(abuf), socket_descriptor, ssl_established);
416 if (verbose) { 411 if (verbose) {
417 printf(_("sent %s\n"), abuf); 412 printf(_("sent %s\n"), abuf);
418 } 413 }
419 if ((ret = recvlines(buffer, MAX_INPUT_BUFFER)) <= 0) { 414 if ((ret = recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established)) <= 0) {
420 result = STATE_CRITICAL; 415 result = STATE_CRITICAL;
421 xasprintf(&error_msg, _("recv() failed after sending authpass, ")); 416 xasprintf(&error_msg, _("recv() failed after sending authpass, "));
422 break; 417 break;
@@ -438,41 +433,36 @@ int main(int argc, char **argv) {
438 } 433 }
439 434
440 /* tell the server we're done */ 435 /* tell the server we're done */
441 smtp_quit(); 436 smtp_quit(config, buffer, socket_descriptor, ssl_established);
442 437
443 /* finally close the connection */ 438 /* finally close the connection */
444 close(sd); 439 close(socket_descriptor);
445 } 440 }
446 441
447 /* reset the alarm */ 442 /* reset the alarm */
448 alarm(0); 443 alarm(0);
449 444
450 microsec = deltime(tv); 445 long microsec = deltime(start_time);
451 elapsed_time = (double)microsec / 1.0e6; 446 double elapsed_time = (double)microsec / 1.0e6;
452 447
453 if (result == STATE_OK) { 448 if (result == STATE_OK) {
454 if (check_critical_time && elapsed_time > critical_time) { 449 if (config.check_critical_time && elapsed_time > config.critical_time) {
455 result = STATE_CRITICAL; 450 result = STATE_CRITICAL;
456 } else if (check_warning_time && elapsed_time > warning_time) { 451 } else if (config.check_warning_time && elapsed_time > config.warning_time) {
457 result = STATE_WARNING; 452 result = STATE_WARNING;
458 } 453 }
459 } 454 }
460 455
461 printf(_("SMTP %s - %s%.3f sec. response time%s%s|%s\n"), state_text(result), error_msg, elapsed_time, verbose ? ", " : "", 456 printf(_("SMTP %s - %s%.3f sec. response time%s%s|%s\n"), state_text(result), error_msg, elapsed_time, verbose ? ", " : "",
462 verbose ? buffer : "", 457 verbose ? buffer : "",
463 fperfdata("time", elapsed_time, "s", (int)check_warning_time, warning_time, (int)check_critical_time, critical_time, true, 0, 458 fperfdata("time", elapsed_time, "s", config.check_warning_time, config.warning_time, config.check_critical_time,
464 false, 0)); 459 config.critical_time, true, 0, false, 0));
465 460
466 return result; 461 exit(result);
467} 462}
468 463
469/* process command-line arguments */ 464/* process command-line arguments */
470int process_arguments(int argc, char **argv) { 465check_smtp_config_wrapper process_arguments(int argc, char **argv) {
471 int c;
472 char *temp;
473
474 bool implicit_tls = false;
475
476 enum { 466 enum {
477 SNI_OPTION 467 SNI_OPTION
478 }; 468 };
@@ -506,109 +496,118 @@ int process_arguments(int argc, char **argv) {
506 {"proxy", no_argument, 0, 'r'}, 496 {"proxy", no_argument, 0, 'r'},
507 {0, 0, 0, 0}}; 497 {0, 0, 0, 0}};
508 498
499 check_smtp_config_wrapper result = {
500 .config = check_smtp_config_init(),
501 .errorcode = OK,
502 };
503
509 if (argc < 2) { 504 if (argc < 2) {
510 return ERROR; 505 result.errorcode = ERROR;
506 return result;
511 } 507 }
512 508
513 for (c = 1; c < argc; c++) { 509 for (int index = 1; index < argc; index++) {
514 if (strcmp("-to", argv[c]) == 0) { 510 if (strcmp("-to", argv[index]) == 0) {
515 strcpy(argv[c], "-t"); 511 strcpy(argv[index], "-t");
516 } else if (strcmp("-wt", argv[c]) == 0) { 512 } else if (strcmp("-wt", argv[index]) == 0) {
517 strcpy(argv[c], "-w"); 513 strcpy(argv[index], "-w");
518 } else if (strcmp("-ct", argv[c]) == 0) { 514 } else if (strcmp("-ct", argv[index]) == 0) {
519 strcpy(argv[c], "-c"); 515 strcpy(argv[index], "-c");
520 } 516 }
521 } 517 }
522 518
523 while (1) { 519 int command_size = 0;
524 c = getopt_long(argc, argv, "+hVv46Lrt:p:f:e:c:w:H:C:R:sSD:F:A:U:P:q", longopts, &option); 520 int response_size = 0;
521 bool implicit_tls = false;
522 while (true) {
523 int opt_index = getopt_long(argc, argv, "+hVv46Lrt:p:f:e:c:w:H:C:R:sSD:F:A:U:P:q", longopts, &option);
525 524
526 if (c == -1 || c == EOF) { 525 if (opt_index == -1 || opt_index == EOF) {
527 break; 526 break;
528 } 527 }
529 528
530 switch (c) { 529 switch (opt_index) {
531 case 'H': /* hostname */ 530 case 'H': /* hostname */
532 if (is_host(optarg)) { 531 if (is_host(optarg)) {
533 server_address = optarg; 532 result.config.server_address = optarg;
534 } else { 533 } else {
535 usage2(_("Invalid hostname/address"), optarg); 534 usage2(_("Invalid hostname/address"), optarg);
536 } 535 }
537 break; 536 break;
538 case 'p': /* port */ 537 case 'p': /* port */
539 if (is_intpos(optarg)) { 538 if (is_intpos(optarg)) {
540 server_port_option = atoi(optarg); 539 result.config.server_port = atoi(optarg);
541 } else { 540 } else {
542 usage4(_("Port must be a positive integer")); 541 usage4(_("Port must be a positive integer"));
543 } 542 }
544 break; 543 break;
545 case 'F': 544 case 'F':
546 /* localhostname */ 545 /* localhostname */
547 localhostname = strdup(optarg); 546 result.config.localhostname = strdup(optarg);
548 break; 547 break;
549 case 'f': /* from argument */ 548 case 'f': /* from argument */
550 from_arg = optarg + strspn(optarg, "<"); 549 result.config.from_arg = optarg + strspn(optarg, "<");
551 from_arg = strndup(from_arg, strcspn(from_arg, ">")); 550 result.config.from_arg = strndup(result.config.from_arg, strcspn(result.config.from_arg, ">"));
552 send_mail_from = 1; 551 result.config.send_mail_from = true;
553 break; 552 break;
554 case 'A': 553 case 'A':
555 authtype = optarg; 554 result.config.authtype = optarg;
556 use_ehlo = true; 555 result.config.use_ehlo = true;
557 break; 556 break;
558 case 'U': 557 case 'U':
559 authuser = optarg; 558 result.config.authuser = optarg;
560 break; 559 break;
561 case 'P': 560 case 'P':
562 authpass = optarg; 561 result.config.authpass = optarg;
563 break; 562 break;
564 case 'e': /* server expect string on 220 */ 563 case 'e': /* server expect string on 220 */
565 server_expect = optarg; 564 result.config.server_expect = optarg;
566 break; 565 break;
567 case 'C': /* commands */ 566 case 'C': /* commands */
568 if (ncommands >= command_size) { 567 if (result.config.ncommands >= command_size) {
569 command_size += 8; 568 command_size += 8;
570 commands = realloc(commands, sizeof(char *) * command_size); 569 result.config.commands = realloc(result.config.commands, sizeof(char *) * command_size);
571 if (commands == NULL) { 570 if (result.config.commands == NULL) {
572 die(STATE_UNKNOWN, _("Could not realloc() units [%d]\n"), ncommands); 571 die(STATE_UNKNOWN, _("Could not realloc() units [%d]\n"), result.config.ncommands);
573 } 572 }
574 } 573 }
575 commands[ncommands] = (char *)malloc(sizeof(char) * 255); 574 result.config.commands[result.config.ncommands] = (char *)malloc(sizeof(char) * 255);
576 strncpy(commands[ncommands], optarg, 255); 575 strncpy(result.config.commands[result.config.ncommands], optarg, 255);
577 ncommands++; 576 result.config.ncommands++;
578 break; 577 break;
579 case 'R': /* server responses */ 578 case 'R': /* server responses */
580 if (nresponses >= response_size) { 579 if (result.config.nresponses >= response_size) {
581 response_size += 8; 580 response_size += 8;
582 responses = realloc(responses, sizeof(char *) * response_size); 581 result.config.responses = realloc(result.config.responses, sizeof(char *) * response_size);
583 if (responses == NULL) { 582 if (result.config.responses == NULL) {
584 die(STATE_UNKNOWN, _("Could not realloc() units [%d]\n"), nresponses); 583 die(STATE_UNKNOWN, _("Could not realloc() units [%d]\n"), result.config.nresponses);
585 } 584 }
586 } 585 }
587 responses[nresponses] = (char *)malloc(sizeof(char) * 255); 586 result.config.responses[result.config.nresponses] = (char *)malloc(sizeof(char) * 255);
588 strncpy(responses[nresponses], optarg, 255); 587 strncpy(result.config.responses[result.config.nresponses], optarg, 255);
589 nresponses++; 588 result.config.nresponses++;
590 break; 589 break;
591 case 'c': /* critical time threshold */ 590 case 'c': /* critical time threshold */
592 if (!is_nonnegative(optarg)) { 591 if (!is_nonnegative(optarg)) {
593 usage4(_("Critical time must be a positive")); 592 usage4(_("Critical time must be a positive"));
594 } else { 593 } else {
595 critical_time = strtod(optarg, NULL); 594 result.config.critical_time = strtod(optarg, NULL);
596 check_critical_time = true; 595 result.config.check_critical_time = true;
597 } 596 }
598 break; 597 break;
599 case 'w': /* warning time threshold */ 598 case 'w': /* warning time threshold */
600 if (!is_nonnegative(optarg)) { 599 if (!is_nonnegative(optarg)) {
601 usage4(_("Warning time must be a positive")); 600 usage4(_("Warning time must be a positive"));
602 } else { 601 } else {
603 warning_time = strtod(optarg, NULL); 602 result.config.warning_time = strtod(optarg, NULL);
604 check_warning_time = true; 603 result.config.check_warning_time = true;
605 } 604 }
606 break; 605 break;
607 case 'v': /* verbose */ 606 case 'v': /* verbose */
608 verbose++; 607 verbose++;
609 break; 608 break;
610 case 'q': 609 case 'q':
611 ignore_send_quit_failure = true; /* ignore problem sending QUIT */ 610 result.config.ignore_send_quit_failure = true; /* ignore problem sending QUIT */
612 break; 611 break;
613 case 't': /* timeout */ 612 case 't': /* timeout */
614 if (is_intnonneg(optarg)) { 613 if (is_intnonneg(optarg)) {
@@ -617,30 +616,31 @@ int process_arguments(int argc, char **argv) {
617 usage4(_("Timeout interval must be a positive integer")); 616 usage4(_("Timeout interval must be a positive integer"));
618 } 617 }
619 break; 618 break;
620 case 'D': 619 case 'D': {
621 /* Check SSL cert validity */ 620 /* Check SSL cert validity */
622#ifdef USE_OPENSSL 621#ifdef USE_OPENSSL
622 char *temp;
623 if ((temp = strchr(optarg, ',')) != NULL) { 623 if ((temp = strchr(optarg, ',')) != NULL) {
624 *temp = '\0'; 624 *temp = '\0';
625 if (!is_intnonneg(optarg)) { 625 if (!is_intnonneg(optarg)) {
626 usage2("Invalid certificate expiration period", optarg); 626 usage2("Invalid certificate expiration period", optarg);
627 } 627 }
628 days_till_exp_warn = atoi(optarg); 628 result.config.days_till_exp_warn = atoi(optarg);
629 *temp = ','; 629 *temp = ',';
630 temp++; 630 temp++;
631 if (!is_intnonneg(temp)) { 631 if (!is_intnonneg(temp)) {
632 usage2(_("Invalid certificate expiration period"), temp); 632 usage2(_("Invalid certificate expiration period"), temp);
633 } 633 }
634 days_till_exp_crit = atoi(temp); 634 result.config.days_till_exp_crit = atoi(temp);
635 } else { 635 } else {
636 days_till_exp_crit = 0; 636 result.config.days_till_exp_crit = 0;
637 if (!is_intnonneg(optarg)) { 637 if (!is_intnonneg(optarg)) {
638 usage2("Invalid certificate expiration period", optarg); 638 usage2("Invalid certificate expiration period", optarg);
639 } 639 }
640 days_till_exp_warn = atoi(optarg); 640 result.config.days_till_exp_warn = atoi(optarg);
641 } 641 }
642 check_cert = true; 642 result.config.check_cert = true;
643 ignore_send_quit_failure = true; 643 result.config.ignore_send_quit_failure = true;
644#else 644#else
645 usage(_("SSL support not available - install OpenSSL and recompile")); 645 usage(_("SSL support not available - install OpenSSL and recompile"));
646#endif 646#endif
@@ -648,26 +648,27 @@ int process_arguments(int argc, char **argv) {
648 // fallthrough 648 // fallthrough
649 case 's': 649 case 's':
650 /* ssl */ 650 /* ssl */
651 use_ssl = true; 651 result.config.use_ssl = true;
652 server_port = SMTPS_PORT; 652 result.config.server_port = SMTPS_PORT;
653 break; 653 break;
654 case 'S': 654 case 'S':
655 /* starttls */ 655 /* starttls */
656 use_starttls = true; 656 result.config.use_starttls = true;
657 use_ehlo = true; 657 result.config.use_ehlo = true;
658 break; 658 break;
659 }
659 case SNI_OPTION: 660 case SNI_OPTION:
660#ifdef HAVE_SSL 661#ifdef HAVE_SSL
661 use_sni = true; 662 result.config.use_sni = true;
662#else 663#else
663 usage(_("SSL support not available - install OpenSSL and recompile")); 664 usage(_("SSL support not available - install OpenSSL and recompile"));
664#endif 665#endif
665 break; 666 break;
666 case 'r': 667 case 'r':
667 use_proxy_prefix = true; 668 result.config.use_proxy_prefix = true;
668 break; 669 break;
669 case 'L': 670 case 'L':
670 use_lhlo = true; 671 result.config.use_lhlo = true;
671 break; 672 break;
672 case '4': 673 case '4':
673 address_family = AF_INET; 674 address_family = AF_INET;
@@ -690,60 +691,36 @@ int process_arguments(int argc, char **argv) {
690 } 691 }
691 } 692 }
692 693
693 c = optind; 694 int c = optind;
694 if (server_address == NULL) { 695 if (result.config.server_address == NULL) {
695 if (argv[c]) { 696 if (argv[c]) {
696 if (is_host(argv[c])) { 697 if (is_host(argv[c])) {
697 server_address = argv[c]; 698 result.config.server_address = argv[c];
698 } else { 699 } else {
699 usage2(_("Invalid hostname/address"), argv[c]); 700 usage2(_("Invalid hostname/address"), argv[c]);
700 } 701 }
701 } else {
702 xasprintf(&server_address, "127.0.0.1");
703 } 702 }
704 } 703 }
705 704
706 if (server_expect == NULL) { 705 if (result.config.use_starttls && result.config.use_ssl) {
707 server_expect = strdup(SMTP_EXPECT);
708 }
709
710 if (mail_command == NULL) {
711 mail_command = strdup("MAIL ");
712 }
713
714 if (from_arg == NULL) {
715 from_arg = strdup(" ");
716 }
717
718 if (use_starttls && use_ssl) {
719 if (implicit_tls) { 706 if (implicit_tls) {
720 use_ssl = false; 707 result.config.use_ssl = false;
721 server_port = SMTP_PORT;
722 } else { 708 } else {
723 usage4(_("Set either -s/--ssl/--tls or -S/--starttls")); 709 usage4(_("Set either -s/--ssl/--tls or -S/--starttls"));
724 } 710 }
725 } 711 }
726 712
727 if (server_port_option != 0) { 713 return result;
728 server_port = server_port_option;
729 }
730
731 return validate_arguments();
732} 714}
733 715
734int validate_arguments(void) { return OK; } 716char *smtp_quit(check_smtp_config config, char buffer[MAX_INPUT_BUFFER], int socket_descriptor, bool ssl_established) {
735 717 int sent_bytes = my_send(config, SMTP_QUIT, strlen(SMTP_QUIT), socket_descriptor, ssl_established);
736void smtp_quit(void) { 718 if (sent_bytes < 0) {
737 int bytes; 719 if (config.ignore_send_quit_failure) {
738 int n;
739
740 n = my_send(SMTP_QUIT, strlen(SMTP_QUIT));
741 if (n < 0) {
742 if (ignore_send_quit_failure) {
743 if (verbose) { 720 if (verbose) {
744 printf(_("Connection closed by server before sending QUIT command\n")); 721 printf(_("Connection closed by server before sending QUIT command\n"));
745 } 722 }
746 return; 723 return buffer;
747 } 724 }
748 die(STATE_UNKNOWN, _("Connection closed by server before sending QUIT command\n")); 725 die(STATE_UNKNOWN, _("Connection closed by server before sending QUIT command\n"));
749 } 726 }
@@ -753,7 +730,7 @@ void smtp_quit(void) {
753 } 730 }
754 731
755 /* read the response but don't care about problems */ 732 /* read the response but don't care about problems */
756 bytes = recvlines(buffer, MAX_INPUT_BUFFER); 733 int bytes = recvlines(config, buffer, MAX_INPUT_BUFFER, socket_descriptor, ssl_established);
757 if (verbose) { 734 if (verbose) {
758 if (bytes < 0) { 735 if (bytes < 0) {
759 printf(_("recv() failed after QUIT.")); 736 printf(_("recv() failed after QUIT."));
@@ -764,6 +741,8 @@ void smtp_quit(void) {
764 printf(_("received %s\n"), buffer); 741 printf(_("received %s\n"), buffer);
765 } 742 }
766 } 743 }
744
745 return buffer;
767} 746}
768 747
769/* 748/*
@@ -775,20 +754,20 @@ void smtp_quit(void) {
775 * function which buffers the data, move that to netutils.c and change 754 * function which buffers the data, move that to netutils.c and change
776 * check_smtp and other plugins to use that. Also, remove (\r)\n. 755 * check_smtp and other plugins to use that. Also, remove (\r)\n.
777 */ 756 */
778int recvline(char *buf, size_t bufsize) { 757int recvline(char *buf, size_t bufsize, check_smtp_config config, int socket_descriptor, bool ssl_established) {
779 int result; 758 int result;
780 unsigned i; 759 int counter;
781 760
782 for (i = result = 0; i < bufsize - 1; i++) { 761 for (counter = result = 0; counter < bufsize - 1; counter++) {
783 if ((result = my_recv(&buf[i], 1)) != 1) { 762 if ((result = my_recv(config, &buf[counter], 1, socket_descriptor, ssl_established)) != 1) {
784 break; 763 break;
785 } 764 }
786 if (buf[i] == '\n') { 765 if (buf[counter] == '\n') {
787 buf[++i] = '\0'; 766 buf[++counter] = '\0';
788 return i; 767 return counter;
789 } 768 }
790 } 769 }
791 return (result == 1 || i == 0) ? -2 : result; /* -2 if out of space */ 770 return (result == 1 || counter == 0) ? -2 : result; /* -2 if out of space */
792} 771}
793 772
794/* 773/*
@@ -805,22 +784,23 @@ int recvline(char *buf, size_t bufsize) {
805 * 784 *
806 * TODO: Move this to netutils.c. Also, remove \r and possibly the final \n. 785 * TODO: Move this to netutils.c. Also, remove \r and possibly the final \n.
807 */ 786 */
808int recvlines(char *buf, size_t bufsize) { 787int recvlines(check_smtp_config config, char *buf, size_t bufsize, int socket_descriptor, bool ssl_established) {
809 int result, i; 788 int result;
789 int counter;
810 790
811 for (i = 0; /* forever */; i += result) { 791 for (counter = 0; /* forever */; counter += result) {
812 if (!((result = recvline(buf + i, bufsize - i)) > 3 && isdigit((int)buf[i]) && isdigit((int)buf[i + 1]) && 792 if (!((result = recvline(buf + counter, bufsize - counter, config, socket_descriptor, ssl_established)) > 3 &&
813 isdigit((int)buf[i + 2]) && buf[i + 3] == '-')) { 793 isdigit((int)buf[counter]) && isdigit((int)buf[counter + 1]) && isdigit((int)buf[counter + 2]) && buf[counter + 3] == '-')) {
814 break; 794 break;
815 } 795 }
816 } 796 }
817 797
818 return (result <= 0) ? result : result + i; 798 return (result <= 0) ? result : result + counter;
819} 799}
820 800
821int my_close(void) { 801int my_close(int socket_descriptor) {
822 int result; 802 int result;
823 result = close(sd); 803 result = close(socket_descriptor);
824#ifdef HAVE_SSL 804#ifdef HAVE_SSL
825 np_net_ssl_cleanup(); 805 np_net_ssl_cleanup();
826#endif 806#endif
diff --git a/plugins/check_smtp.d/config.h b/plugins/check_smtp.d/config.h
new file mode 100644
index 00000000..c8660445
--- /dev/null
+++ b/plugins/check_smtp.d/config.h
@@ -0,0 +1,92 @@
1#pragma once
2
3#include "../../config.h"
4#include <stddef.h>
5#include <string.h>
6
7enum {
8 SMTP_PORT = 25,
9 SMTPS_PORT = 465
10};
11
12#define SMTP_EXPECT "220"
13
14typedef struct {
15 int server_port;
16 char *server_address;
17 char *localhostname;
18 char *server_expect;
19 bool ignore_send_quit_failure;
20
21 double warning_time;
22 bool check_warning_time;
23 double critical_time;
24 bool check_critical_time;
25 bool use_ehlo;
26 bool use_lhlo;
27
28 char *from_arg;
29 bool send_mail_from;
30
31 int ncommands;
32 char **commands;
33
34 int nresponses;
35 char **responses;
36
37 char *authtype;
38 char *authuser;
39 char *authpass;
40
41 bool use_proxy_prefix;
42#ifdef HAVE_SSL
43 bool check_cert;
44 int days_till_exp_warn;
45 int days_till_exp_crit;
46 bool use_ssl;
47 bool use_starttls;
48 bool use_sni;
49#endif
50} check_smtp_config;
51
52check_smtp_config check_smtp_config_init() {
53 check_smtp_config tmp = {
54 .server_port = SMTP_PORT,
55 .server_address = strdup("localhost"),
56 .localhostname = NULL,
57
58 .server_expect = SMTP_EXPECT,
59 .ignore_send_quit_failure = false,
60
61 .warning_time = 0,
62 .check_warning_time = false,
63 .critical_time = 0,
64 .check_critical_time = false,
65 .use_ehlo = false,
66 .use_lhlo = false,
67
68 .from_arg = strdup(" "),
69 .send_mail_from = false,
70
71 .ncommands = 0,
72 .commands = NULL,
73
74 .nresponses = 0,
75 .responses = NULL,
76
77 .authtype = NULL,
78 .authuser = NULL,
79 .authpass = NULL,
80
81 .use_proxy_prefix = false,
82#ifdef HAVE_SSL
83 .check_cert = false,
84 .days_till_exp_warn = 0,
85 .days_till_exp_crit = 0,
86 .use_ssl = false,
87 .use_starttls = false,
88 .use_sni = false,
89#endif
90 };
91 return tmp;
92}