1 /******************************************************************************
6 * Created: Oct 09 2010 19:14:12
7 * Last modified: Oct 09 2010 19:14:12
9 * Author: Ladislav Láska
10 * e-mail: ladislav.laska@gmail.com
12 ******************************************************************************/
14 #define _XOPEN_SOURCE 500
16 #include <gnutls/gnutls.h>
17 #include <gnutls/x509.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
28 #define S_UNREACHABLE -1
35 int warning_after = 30;
40 #define die(msg) { fprintf(stderr, "Error: " msg "\n" ); exit(3); }
41 #define gnutls_die(code) { gnutls_perror(code); exit(3); }
47 int tcp_open( char *hostname, char *service ) {
48 struct addrinfo hints;
49 struct addrinfo *result, *result_ptr;
53 memset(&hints, 0, sizeof(struct addrinfo));
54 hints.ai_family = AF_UNSPEC;
55 hints.ai_socktype = SOCK_STREAM;
56 err = getaddrinfo(hostname, service, &hints, &result);
58 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
62 for (result_ptr = result; result_ptr != NULL; result_ptr = result_ptr->ai_next) {
63 sfd = socket(result_ptr->ai_family, result_ptr->ai_socktype,
64 result_ptr->ai_protocol);
65 if (sfd == -1) continue;
67 if (connect(sfd, result_ptr->ai_addr, result_ptr->ai_addrlen) != -1)
70 close(sfd); /* connect(2) failed. */
73 if (result_ptr == NULL) {
74 /* No address succeeded */
83 int check( char * hostname, char *service ) {
87 gnutls_session_t session;
88 gnutls_certificate_credentials_t xcred;
92 err = gnutls_certificate_allocate_credentials( &xcred );
93 if (err < 0) gnutls_die(err);
95 err = gnutls_init( &session, GNUTLS_CLIENT );
96 if (err < 0) gnutls_die(err);
99 err = gnutls_priority_set_direct(session, "EXPORT", NULL);
100 if (err < 0) gnutls_die(err);
102 err = gnutls_credentials_set( session, GNUTLS_CRD_CERTIFICATE, xcred );
103 if (err < 0) gnutls_die(err);
105 /* Connect to server */
107 int fd = tcp_open( hostname, service );
110 state= S_UNREACHABLE;
114 /* Socket opened, establish tls connection */
116 /* Associate socket with session */
117 gnutls_transport_set_ptr( session, (gnutls_transport_ptr_t) fd );
120 err = gnutls_handshake( session );
121 if (err < 0) gnutls_die(err);
123 /* Get server certificate. */
124 const gnutls_datum_t *cert_list;
125 unsigned int cert_list_size = 0;
126 time_t expiration_time, today;
127 gnutls_x509_crt_t cert;
129 if ( gnutls_certificate_type_get( session ) != GNUTLS_CRT_X509 ) {
134 cert_list = gnutls_certificate_get_peers( session, &cert_list_size );
138 for (int i = 0; i < cert_list_size; i++) {
139 gnutls_x509_crt_init( &cert );
140 gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER );
141 expiration_time = gnutls_x509_crt_get_expiration_time( cert );
142 int expires_in = (expiration_time - today) / 86400;
143 if ((state == S_OK) && (expires_in <= warning_after)) {
145 sprintf(errmsg, "Certificate will expire in %i days.", expires_in);
147 if ((state <= S_WARNING) && (expires_in <= error_after)) {
149 sprintf(errmsg, "Certificate will expire in %i days.", expires_in);
154 err = gnutls_bye( session, GNUTLS_SHUT_WR );
155 if (err < 0) gnutls_die(err);
158 gnutls_deinit( session );
159 gnutls_certificate_free_credentials( xcred );
164 void log_func( int level, char *msg ) {
165 fprintf(stderr, "[%2i] %s", level, msg);
169 * This signal handler is wrong, but it's just a failsafe.
171 void sig_handler(int k) {
172 fputs("Timeout.", stderr);
176 int main(int argc, char **argv) {
178 char *service = NULL;
182 while ((opt = getopt(argc, argv, "hvw:c:H:p:s:")) != -1) {
185 warning_after = atoi(optarg);
188 error_after = atoi(optarg);
191 hostname = strdup(optarg);
195 if (service != NULL) die("Only one service can be specified.");
196 service = strdup(optarg);
205 if (argc <= 1) die("No address to try.");
207 gnutls_global_set_log_function((gnutls_log_func) log_func);
208 gnutls_global_set_log_level(LOG_LEVEL);
211 /* Initialize gnutls */
213 if ((err = gnutls_global_init())) {
218 sprintf(errmsg, "OK");
224 /* TODO: doesn't work. */
225 signal(SIGALRM, sig_handler);
229 state = check(hostname, service);
231 printf("Internal error.");
233 gnutls_global_deinit();
238 printf("%s\n", errmsg);
239 return (state < 0) ? 127 : state;
243 printf("Help yourself.");