#
# This script was written by George A. Theall, <theall@tifaware.com>.
#
# See the Nessus Scripts License for details.
#
if ( ! defined_func("localtime") ) exit(0);

# How far (in days) to warn of certificate expiry. [Hmmm, how often
# will scans be run and how quickly can people obtain new certs???]

lookahead = 60;

if (description) {
  script_id(15901);
  script_version ("$Revision: 1.2 $"); 

  name["english"] = "SSL Certificate Expiry";
  script_name(english:name["english"]);

  desc["english"] = "
This script checks expiry dates of certificates associated with
SSL-enabled services on the target and reports whether any have
already expired or will expire within " + lookahead + " days.

*****  Nessus relies on the clock setting on the Nessus server
*****  to determine if expiry dates are out of range. If that's
*****  inaccurate, the scan results may be as well.";
  script_description(english:desc["english"]);
 
  summary["english"] = "Checks SSL certificate expiry";
  script_summary(english:summary["english"]);
 
  script_category(ACT_GATHER_INFO);
  script_copyright(english:"This script is Copyright (C) 2004 George A. Theall");

  family["english"] = "General";
  script_family(english:family["english"]);

  script_dependencie("find_service.nes", "global_settings.nasl");

  exit(0);
}

include("global_settings.inc");
include("misc_func.inc");
include("ssl_funcs.inc");

host = get_host_name();
port = get_kb_item("Transport/SSL");
if (!port || !get_port_state(port)) exit(0);
if (debug_level) display("debug: checking SSL certificate on ", host, ":", port, ".\n");

if ( debug_level ) display("getting cert.\n");
cert = get_server_cert(port:port, encoding:"der");
if (!isnull(cert)) {

  # nb: maybe someday I'll actually *parse* ASN.1.
  v = stridx(cert, raw_string(0x30, 0x1e, 0x17, 0x0d));
  if (v >= 0) {
    v += 4;
    valid_start = substr(cert, v, v+11);
    v += 15;
    valid_end = substr(cert, v, v+11);

    if (valid_start =~ "^[0-9]{12}$" && valid_end =~ "^[0-9]{12}$") {
      # Get dates, expressed in UTC, for checking certs.
      # - right now.
      tm = localtime(unixtime(), utc:TRUE);
      now = substr(string(tm["year"]), 2);
      foreach field (make_list("mon", "mday", "hour", "min", "sec")) {
        if (tm[field] < 10) now += "0"; 
        now += tm[field];
      }
      # - 'lookahead' days in the future.
      tm = localtime(unixtime() + lookahead*24*60*60, utc:TRUE);
      future = substr(string(tm["year"]), 2);
      foreach field (make_list("mon", "mday", "hour", "min", "sec")) {
        if (tm[field] < 10) future += "0"; 
        future += tm[field];
      }
      if (debug_level) {
        display("debug: now:    ", now, ".\n");
        display("debug: future: ", future, ".\n");
      }

      if (debug_level) {
        display("debug: valid not before: ", valid_start, "Z.\n");
        display("debug: valid not after:  ", valid_end, "Z.\n");
      }
      if (log_verbosity > 1) display("The SSL certificate on ", host, ":", port, " is valid between ", valid_start, "Z and ", valid_end, "Z.\n");

      if (valid_start > now) {
        security_note(
          data:string("The SSL certificate of the remote service is not valid before ", valid_start, "Z!"),
          port:port
        );
      }
      else if (valid_end < now) {
        security_warning(
          data:string("The SSL certificate of the remote service expired ", valid_end, "Z!"),
          port:port
        );
      }
      else if (valid_end < future) {
        security_note(
          data:string("The SSL certificate of the remote service will expire within ", lookahead, " days, at ", valid_end, "Z."),
          port:port
        );
      }
    }
  }
}
