void logerr(const char *ctl, ...) { int saved_errno; va_list va; saved_errno = errno; va_start(va, ctl); vlogline(0, 0, ctl, va); logerrstr(": %s", strerror(saved_errno)); va_end(va); }
void myprintf (const char *format, ...) { va_list args; char buf[4 * PBC_DES_KEY_BUF]; pool *p = NULL; assert (ssl != NULL); va_start (args, format); vsnprintf (buf, sizeof (buf), format, args); va_end (args); if (debug) { pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "Sending: \"%s\"", buf); } if (SSL_write (ssl, buf, strlen (buf)) < 0) { logerrstr ("SSL_write"); exit (1); } }
/* run as if invoked by inetd */ int main (int argc, char *argv[]) { int c; int filetype = SSL_FILETYPE_PEM; char *peer = NULL; char *ptr; char buf[4096]; enum optype op = NOOP; char *setkey = NULL; SSL_CTX *ctx; X509 *client_cert; int r; pool *p = NULL; security_context *context = NULL; int max_wait = 0; while ((c = getopt (argc, argv, "apc:k:C:D:f:")) != -1) { switch (c) { case 'a': filetype = SSL_FILETYPE_ASN1; break; case 'p': filetype = SSL_FILETYPE_PEM; break; case 'c': /* 'optarg' is the certificate file */ certfile = strdup (optarg); break; case 'k': /* 'optarg' is the key file */ keyfile = strdup (optarg); break; case 'C': /* 'optarg' is the CA we accept */ cafile = strdup (optarg); break; case 'D': /* 'optarg' is a directory of CAs */ cadir = strdup (optarg); break; case 'f': configfile = strdup (optarg); break; case '?': default: usage (); break; } } libpbc_config_init (p, configfile, "keyserver"); pbc_log_init_syslog (p, "keyserver"); libpbc_pubcookie_init (p, &context); debug = libpbc_config_getint (p, "logging_level", 0); if (!keyfile) keyfile = libpbc_config_getstring (p, "ssl_key_file", "server.pem"); if (!certfile) certfile = libpbc_config_getstring (p, "ssl_cert_file", "server.pem"); if (!cafile) cafile = libpbc_config_getstring (p, "ssl_ca_file", NULL); if (!cadir) cadir = libpbc_config_getstring (p, "ssl_ca_path", NULL); gcfile = libpbc_config_getstring (p, "granting_cert_file", NULL); max_wait = libpbc_config_getint (p, "keyserver_max_wait_time", 0); if (max_wait < 0) max_wait = 0; /* xxx log connection information */ /* initalize the PRNG as best we can if we have to */ if (RAND_status () == 0) { pbc_time_t t = pbc_time (NULL); pid_t pid = getpid (); char buf[1024]; char *cmd[3] = { "/bin/ps", "-ef", NULL }; RAND_seed ((unsigned char *) &t, sizeof (t)); RAND_seed ((unsigned char *) &pid, sizeof (pid)); capture_cmd_output (p, cmd, buf, sizeof (buf)); RAND_seed ((unsigned char *) buf, sizeof (buf)); } /* Load SSL Error Strings */ SSL_load_error_strings (); /* initialize the OpenSSL connection */ SSL_library_init (); ctx = SSL_CTX_new (TLSv1_server_method ()); /* setup the correct certificate */ if (!SSL_CTX_use_certificate_file (ctx, certfile, filetype)) { logerrstr ("SSL_CTX_use_certificate_file"); exit (1); } if (!SSL_CTX_use_PrivateKey_file (ctx, keyfile, filetype)) { logerrstr ("SSL_CTX_use_PrivateKey_file"); exit (1); } if (!SSL_CTX_load_verify_locations (ctx, cafile, cadir)) { logerrstr ("SSL_CTX_load_verify_locations"); exit (1); } SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_callback); ssl = SSL_new (ctx); /* negotiate SSL */ SSL_set_rfd (ssl, 0); SSL_set_wfd (ssl, 1); SSL_set_accept_state (ssl); /* If no data in max_wait seconds, give up */ if (max_wait) { signal (SIGALRM, sig_alarm); alarm (max_wait); } if (SSL_accept (ssl) <= 0) { logerrstr ("SSL_accept"); ERR_print_errors_fp (stderr); exit (1); } if (max_wait) alarm (0); /* check certificate */ client_cert = SSL_get_peer_certificate (ssl); if (client_cert == NULL) { pbc_log_activity (p, PBC_LOG_ERROR, "client_cert == NULL???"); exit (1); } peer = get_cn_from_crt (client_cert); if (peer == NULL) { pbc_log_activity (p, PBC_LOG_ERROR, "peer == NULL???"); exit (1); } pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "peer cn: %s\n", peer); /* read HTTP query */ if ((c=SSL_read (ssl, buf, sizeof(buf)-1)) <= 0) { pbc_log_activity (p, PBC_LOG_ERROR, "SSL_read() failed"); ERR_print_errors_fp (stderr); exit (1); } buf[c] = '\0'; pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "REQ=%s", buf); for (ptr = buf; *ptr != '\0'; ptr++) { if (*ptr == '?' || *ptr == '&') { /* next arg */ /* look for 'genkey' */ if (!strncmp (ptr + 1, "genkey=yes", 10)) { op = GENKEY; } else if (!strncmp (ptr + 1, "genkey=no", 9)) { op = FETCHKEY; } else if (!strncmp (ptr + 1, "genkey=put", 10)) { op = SETKEY; } else if (!strncmp (ptr + 1, "genkey=permit", 13)) { op = PERMIT; } else if (!strncmp (ptr + 1, "genkey=getgc", 12)) { op = FETCHGC; } else if (!strncmp (ptr + 1, "genkey=setpkey", 12)) { op = SETPKEY; } /* look for 'setkey' */ else if (!strncmp (ptr + 1, "setkey=", 7)) { char *q; ptr++; /* ? or & */ ptr += 7; /* setkey= */ setkey = strdup (ptr); /* terminated by ? - this is a bit dubious, but i think it's compensated for later - ssw */ q = strchr (setkey, '?'); if (q) *q = '\0'; } } } if (op == NOOP) { pbc_log_activity (p, PBC_LOG_ERROR, "peer didn't specify an operation"); exit (1); } /* call doit */ r = doit (peer, context, op, setkey, client_cert); SSL_shutdown (ssl); return r; }