int warning_after = 30;
int error_after = 7;
int verbose = 0;
+int timeout = 9;
+int use_starttls = 0;
+
+#define BUFFER_SIZE 1024
#define LOG_LEVEL 0
#define die(msg) { fprintf(stderr, "Error: " msg "\n" ); exit(3); }
+#define dief(msg, ...) { fprintf(stderr, "Error: " msg "\n", __VA_ARGS__ ); exit(3); }
#define gnutls_die(code) { gnutls_perror(code); exit(3); }
char errmsg[256];
return sfd;
}
+/* Expects some data. This is just wrong and should be written correctly. */
+char *expect(int fd, char *str) {
+ char buffer[BUFFER_SIZE];
+ int len = strlen(str);
+ int bytes = read(fd, buffer, BUFFER_SIZE);
+ if (bytes < len) goto fail;
+ if (!strncmp(buffer,str,len)) {
+ while (bytes == BUFFER_SIZE)
+ bytes = read(fd, buffer, BUFFER_SIZE) > 0;
+ return NULL;
+ }
+
+ fail:;
+ char *ptr = strdup(buffer);
+ while (bytes == BUFFER_SIZE)
+ bytes = read(fd, buffer, BUFFER_SIZE) > 0;
+ return ptr;
+}
+
int check( char * hostname, char *service ) {
int state = S_OK;
int err;
/* Connect to server */
- int fd = tcp_open( hostname, service );
+ long fd = tcp_open( hostname, service );
if (fd == -1) {
state= S_UNREACHABLE;
goto cleanup;
}
+
+ /* StartTLS? */
+
+ if (use_starttls) {
+ expect(fd, "");
+ char buffer[] = "STARTTLS\n";
+ write(fd, buffer, sizeof(buffer));
+ char *b;
+ if ((b = expect(fd, "220 "))) {
+ dief("STARTTLS declined: %s.", b);
+ }
+ }
+
+
/* Socket opened, establish tls connection */
/* Associate socket with session */
* This signal handler is wrong, but it's just a failsafe.
*/
void sig_handler(int k) {
- fputs("Timeout.", stderr);
+ fputs("Timeout.\n", stderr);
exit(S_UNKNOWN);
}
int opt;
- while ((opt = getopt(argc, argv, "hvw:c:H:p:s:")) != -1) {
+ while ((opt = getopt(argc, argv, "hvSw:c:H:p:s:t:")) != -1) {
switch (opt) {
case 'w':
warning_after = atoi(optarg);
case 'H':
hostname = strdup(optarg);
break;
+ case 't':
+ timeout = atoi( optarg );
+ if (timeout < 0) die("Timeout must be >= 0");
+ break;
case 'p':
case 's':
if (service != NULL) die("Only one service can be specified.");
exit(0);
case 'v':
verbose++;
+ case 'S':
+ use_starttls = 1;
default: break;
}
}
/* Setup alarm */
/* TODO: doesn't work. */
signal(SIGALRM, sig_handler);
- alarm(9*60);
+ alarm( timeout );
/* Do checking */
state = check(hostname, service);
- if (state < 0)
- printf("Internal error.");
+ if (state < 0) {
+ sprintf(errmsg, "Internal error %i.", state);
+ state = S_UNKNOWN;
+ }
gnutls_global_deinit();
printf(
"Usage: cert-checker [options] -H hostname -p|s port|service\n"
" Where options could be: \n"
- " -h this help\n"
- " -w warning level (in days, default 30)\n"
- " -c critical level (in days, default 7)\n"
- " -v verbosity level\n"
+ " -h hostname this help\n"
+ " -w n warning level (in days, default 30)\n"
+ " -c n critical level (in days, default 7)\n"
+ " -v verbosity level\n"
+ " -t n timeout (in seconds, n=0 disables timeout\n"
+ " -S use SMTP/STARTLS\n"
);
}