+/* Global variables */
+BIO *bio_err;
+
+
+/* Create an SSL context. If certificate verification is requested
+ * then load the file containing the CA chain and verify the certificate
+ * sent by the peer.
+ */
+SSL_CTX *os_ssl_keys(int is_server, const char *os_dir, const char *ciphers, const char *cert, const char *key, const char *ca_cert)
+{
+ SSL_CTX *ctx = NULL;
+
+ if (!(ctx = get_ssl_context(ciphers))) {
+ goto SSL_ERROR;
+ }
+
+ /* If a CA certificate has been specified then load it and verify the peer */
+ if (ca_cert) {
+ debug1("%s: DEBUG: Peer verification requested.", ARGV0);
+
+ if (!load_ca_cert(ctx, ca_cert)) {
+ goto SSL_ERROR;
+ }
+
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
+ }
+
+ /* Loading a certificate and key is mandatory for the server and optional for clients */
+ if (is_server) {
+ char default_cert[PATH_MAX + 1];
+ char default_key[PATH_MAX + 1];
+
+ if (!cert) {
+ snprintf(default_cert, PATH_MAX + 1, "%s%s", os_dir, CERTFILE);
+ cert = default_cert;
+ }
+
+ if (!key) {
+ snprintf(default_key, PATH_MAX + 1, "%s%s", os_dir, KEYFILE);
+ key = default_key;
+ }
+
+ if (!load_cert_and_key(ctx, cert, key)) {
+ goto SSL_ERROR;
+ }
+
+ debug1("%s: DEBUG: Returning CTX for server.", ARGV0);
+ } else {
+ if (cert && key) {
+ if (!load_cert_and_key(ctx, cert, key)) {
+ goto SSL_ERROR;
+ }
+ }
+
+ debug1("%s: DEBUG: Returning CTX for client.", ARGV0);
+ }