Logo Search packages:      
Sourcecode: jabberd14 version File versions  Download package

static void mio_tls_process_credentials ( xmlnode  x,
const std::list< std::string > &  default_cacertfile_pem,
const std::list< std::string > &  default_cacertfile_der,
gnutls_dh_params_t  mio_tls_dh_params,
const std::list< std::string > &  crl_files_pem,
const std::list< std::string > &  crl_files_der 
) [static]

process a configuration element configuring a set of credentials in the configuration file

Parameters:
x the xmlnode containing the set
default_cacertfile file containing ca certificates to use if the set does not contain its own definition
mio_tls_dh_params DH params to use (for performance reasons the same params are used for all sets
crl_files_pem the CRL files in PEM format to load
crl_files_der the CRL files in DER format to load

Definition at line 478 of file mio_tls.cc.

References j_strcmp(), log_warn(), mio_tls_certtypes, mio_tls_ciphers, mio_tls_compile_certtypes(), mio_tls_compile_ciphers(), mio_tls_compile_compression(), mio_tls_compile_kx(), mio_tls_compile_mac(), mio_tls_compile_protocols(), mio_tls_compression, mio_tls_credentials, mio_tls_kx, mio_tls_mac, mio_tls_pool, mio_tls_protocols, xmlnode_get_attrib_ns(), xmlnode_get_data(), xmlnode_get_firstchild(), xmlnode_get_localname(), xmlnode_get_namespace(), and xmlnode_get_nextsibling().

Referenced by mio_ssl_init().

                                                                                                                                                                                                                                                                               {
    std::set<std::string> domains;
    int ret = 0;
    bool loaded_cacerts = false;
    std::string protocols;
    std::string kx;
    std::string ciphers;
    std::string certtypes = "X.509";
    std::string mac = "SHA1";
    std::string compression = "NULL";

    // prepare the credentials
    gnutls_certificate_credentials_t current_credentials = NULL;
    ret = gnutls_certificate_allocate_credentials (&current_credentials);
    if (ret < 0) {
      log_error(NULL, "Error initializing credentials: %s", gnutls_strerror(ret));
      return;
    }

    // iterate the child elements
    for (xmlnode cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {
      // we only process elements in the NS_JABBERD_CONFIGFILE namespace
      if (j_strcmp(xmlnode_get_namespace(cur), NS_JABBERD_CONFIGFILE) != 0) {
          continue;
      }

      // is it a default declaration?
      if (j_strcmp(xmlnode_get_localname(cur), "default") == 0) {
          domains.insert("*");
          continue;
      }

      // is it a domain declaration?
      if (j_strcmp(xmlnode_get_localname(cur), "domain") == 0) {
          char const *const domain = xmlnode_get_data(cur);

          // check that we had a domain name in the configuration
          if (domain == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <domain/> element inside the TLS configuration, that does not contain a domain name.");
            continue;
          }

          // add it to the set for domains for which we have to add the credentials after we loaded them
          domains.insert(domain);
          continue;
      }

      // a X.509 certificate in PEM format?
      if (j_strcmp(xmlnode_get_localname(cur), "pem") == 0) {
          char const *const pubfile = xmlnode_get_data(cur);
          char const * privfile = xmlnode_get_attrib_ns(cur, "private-key", NULL);

          // there needs to be a filename for the public key
          if (pubfile == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <pem/> element inside the TLS configuration, that does not contain a file-name.");
            continue;
          }

          // if there is no filename for the private key, use the same as for the public key (file containing both keys)
          if (privfile == NULL)
            privfile = pubfile;

          // load the X.509 certificate
          ret = gnutls_certificate_set_x509_key_file(current_credentials, pubfile, privfile, GNUTLS_X509_FMT_PEM);
          if (ret < 0) {
            log_error(NULL, "Error loading X.509 certificate (PEM) pub=%s/priv=%s: %s", pubfile, privfile, gnutls_strerror(ret));
            continue;
          }

          continue;
      }

      // a X.509 certificate in DER format?
      if (j_strcmp(xmlnode_get_localname(cur), "der") == 0) {
          char const *const pubfile = xmlnode_get_data(cur);
          char const * privfile = xmlnode_get_attrib_ns(cur, "private-key", NULL);

          // there needs to be a filename for the public key
          if (pubfile == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <der/> element inside the TLS configuration, that does not contain a file-name.");
            continue;
          }

          // if there is no filename for the private key, use the same as for the public key (file containing both keys)
          if (privfile == NULL)
            privfile = pubfile;

          // load the X.509 certificate
          ret = gnutls_certificate_set_x509_key_file(current_credentials, pubfile, privfile, GNUTLS_X509_FMT_DER);
          if (ret < 0) {
            log_error(NULL, "Error loading X.509 certificate (DER) pub=%s/priv=%s: %s", pubfile, privfile, gnutls_strerror(ret));
            continue;
          }

          continue;
      }

      // load a certification authority certificate
      if (j_strcmp(xmlnode_get_localname(cur), "ca") == 0) {
          bool format_der = j_strcmp(xmlnode_get_attrib_ns(cur, "type", NULL), "der") == 0;
          char const *const file = xmlnode_get_data(cur);

          // is there a filename?
          if (file == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <ca/> element inside the TLS configuration, that does not contain a file-name.");
            continue;
          }

          // load the CA's certificate
          ret = gnutls_certificate_set_x509_trust_file(current_credentials, file, format_der ? GNUTLS_X509_FMT_DER : GNUTLS_X509_FMT_PEM);
          if (ret < 0) {
            log_error(NULL, "Error loading certificate of CA (%s) %s: %s", format_der ? "DER" : "PEM", file, gnutls_strerror(ret));
            continue;
          }

          // we have had a CA certificate, we do not need to load the defaults
          loaded_cacerts = true;

          continue;
      }

      // load an OpenPGP key
      if (j_strcmp(xmlnode_get_localname(cur), "openpgp") == 0) {
          char const *const pubfile = xmlnode_get_data(cur);
          char const *const privfile = xmlnode_get_attrib_ns(cur, "private-key", NULL);

          // ensure that we have two filenames
          if (pubfile == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <openpgp/> element inside the TLS configuration, that does not contain a file-name.");
            continue;
          }
          if (privfile == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <openpgp/> element inside the TLS configuration, that does not contain a private-key file-name.");
            continue;
          }

          // load OpenPGP key/certificate
          ret = gnutls_certificate_set_openpgp_key_file(current_credentials, pubfile, privfile);
          if (ret < 0) {
            log_error(NULL, "Error loading OpenPGP key pub=%s/priv=%s: %s", pubfile, privfile, gnutls_strerror(ret));
            continue;
          }

          continue;
      }

      // load OpenPGP keyring
      if (j_strcmp(xmlnode_get_localname(cur), "keyring") == 0) {
          char const *const file = xmlnode_get_data(cur);

          if (file == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <keyring/> element inside the TLS configuration, that does not contain a file-name.");
            continue;
          }

          // load the OpenPGP keyring
          ret = gnutls_certificate_set_openpgp_keyring_file(current_credentials, file);
          if (ret < 0) {
            log_error(NULL, "Error loading OpenPGP keyring %s: %s", file, gnutls_strerror(ret));
            continue;
          }

          continue;
      }

      // load GnuPG trustdb
      if (j_strcmp(xmlnode_get_localname(cur), "trustdb") == 0) {
          char const *const file = xmlnode_get_data(cur);

          if (file == NULL) {
            log_warn(NULL, "Initializing TLS subsystem: <trustdb/> element inside the TLS configuration, that does not contain a file-name.");
            continue;
          }

          // load the GnuPG trustdb
          ret = gnutls_certificate_set_openpgp_trustdb(current_credentials, file);
          if (ret < 0) {
            log_error(NULL, "Error loading GnuPG trustdb %s: %s", file, gnutls_strerror(ret));
            continue;
          }
      }

      // setup protocols to use
      if (j_strcmp(xmlnode_get_localname(cur), "protocols") == 0) {
          char const *const protocols_data = xmlnode_get_data(cur);
          if (protocols_data != NULL)
            protocols = protocols_data;
          continue;
      }

      // setup key exchange protocols to use
      if (j_strcmp(xmlnode_get_localname(cur), "kx") == 0) {
          char const *const kx_data = xmlnode_get_data(cur);
          if (kx_data != NULL)
            kx = kx_data;
          continue;
      }

      // setup ciphers to use
      if (j_strcmp(xmlnode_get_localname(cur), "ciphers") == 0) {
          char const *const ciphers_data = xmlnode_get_data(cur);
          if (ciphers_data != NULL)
            ciphers = ciphers_data;
          continue;
      }

      // setup certificate types to use
      if (j_strcmp(xmlnode_get_localname(cur), "certtypes") == 0) {
          char const *const certtypes_data = xmlnode_get_data(cur);
          if (certtypes_data != NULL)
            certtypes = certtypes_data;
          continue;
      }

      // setup MAC algorithms to use
      if (j_strcmp(xmlnode_get_localname(cur), "mac") == 0) {
          char const *const mac_data = xmlnode_get_data(cur);
          if (mac_data != NULL)
            mac = mac_data;
          continue;
      }

      // setup compression algorithms to use
      if (j_strcmp(xmlnode_get_localname(cur), "compression") == 0) {
          char const *const compression_data = xmlnode_get_data(cur);
          if (compression_data != NULL)
            compression = compression_data;
          continue;
      }
    }

    /* set the DH params for this certificate */
    gnutls_certificate_set_dh_params(current_credentials, mio_tls_dh_params);

    // load CRL files
    std::list<std::string>::const_iterator crl_p;
    for (crl_p=crl_files_pem.begin(); crl_p!=crl_files_pem.end(); ++crl_p) {
      char const* file_to_load = crl_p->c_str();

      ret = gnutls_certificate_set_x509_crl_file(current_credentials, file_to_load, GNUTLS_X509_FMT_PEM);
      if (ret < 0) {
          log_error(NULL, "Error loading CRL file %s (PEM): %s", file_to_load, gnutls_strerror(ret));
      }
    }
    for (crl_p=crl_files_der.begin(); crl_p!=crl_files_der.end(); ++crl_p) {
      char const* file_to_load = crl_p->c_str();

      ret = gnutls_certificate_set_x509_crl_file(current_credentials, file_to_load, GNUTLS_X509_FMT_DER);
      if (ret < 0) {
          log_error(NULL, "Error loading CRL file %s (DER): %s", file_to_load, gnutls_strerror(ret));
      }
    }

    // loaded any CA certificate? if not load the defaults
    if (!loaded_cacerts) {
      std::list<std::string>::const_iterator p;
      for (p=default_cacertfile_pem.begin(); p!=default_cacertfile_pem.end(); ++p) {
          ret = gnutls_certificate_set_x509_trust_file(current_credentials, p->c_str(), GNUTLS_X509_FMT_PEM);
          if (ret < 0) {
            log_error(NULL, "Error loading default CA certificate %s (PEM): %s", p->c_str(), gnutls_strerror(ret));
          }
      }
      for (p=default_cacertfile_der.begin(); p!=default_cacertfile_der.end(); ++p) {
          ret = gnutls_certificate_set_x509_trust_file(current_credentials, p->c_str(), GNUTLS_X509_FMT_DER);
          if (ret < 0) {
            log_error(NULL, "Error loading default CA certificate %s (DER): %s", p->c_str(), gnutls_strerror(ret));
          }
      }
    }

    // make the credentials active for the selected domains
    bool credentials_used = false;
    std::set<std::string>::const_iterator p;
    for (p = domains.begin(); p!= domains.end(); ++p) {
      if (mio_tls_credentials.find(*p) != mio_tls_credentials.end()) {
          log_warn(NULL, "Redefinition of TLS credentials for domain %s. Ignoring redefinition.", p->c_str());
          continue;
      }

      credentials_used = true;
      mio_tls_credentials[*p] = current_credentials;
      if (protocols != "" && mio_tls_protocols.find(*p) == mio_tls_protocols.end()) {
          int const* compiled_protocols = mio_tls_compile_protocols(mio_tls_pool, protocols);
          if (compiled_protocols != NULL) {
            mio_tls_protocols[*p] = compiled_protocols;
          }
      }
      if (kx != "" && mio_tls_kx.find(*p) == mio_tls_kx.end()) {
          int const* compiled_kx = mio_tls_compile_kx(mio_tls_pool, kx);
          if (compiled_kx != NULL) {
            mio_tls_kx[*p] = compiled_kx;
          }
      }
      if (ciphers != "" && mio_tls_ciphers.find(*p) == mio_tls_ciphers.end()) {
          int const* compiled_ciphers = mio_tls_compile_ciphers(mio_tls_pool, ciphers);
          if (compiled_ciphers != NULL) {
            mio_tls_ciphers[*p] = compiled_ciphers;
          }
      }
      if (certtypes != "" && mio_tls_certtypes.find(*p) == mio_tls_certtypes.end()) {
          int const* compiled_certtypes = mio_tls_compile_certtypes(mio_tls_pool, certtypes);
          if (compiled_certtypes != NULL) {
            mio_tls_certtypes[*p] = compiled_certtypes;
          }
      }
      if (mac != "" && mio_tls_mac.find(*p) == mio_tls_mac.end()) {
          int const* compiled_mac = mio_tls_compile_mac(mio_tls_pool, mac);
          if (compiled_mac != NULL) {
            mio_tls_mac[*p] = compiled_mac;
          }
      }
      if (compression != "" && mio_tls_compression.find(*p) == mio_tls_compression.end()) {
          int const* compiled_compression = mio_tls_compile_compression(mio_tls_pool, compression);
          if (compiled_compression != NULL) {
            mio_tls_compression[*p] = compiled_compression;
          }
      }
    }

    // check if the credentials are used for any domain
    if (!credentials_used) {
      log_warn(NULL, "Found credentials definition, that is not used for any domain.");
      gnutls_certificate_free_credentials(current_credentials);
    }
}


Generated by  Doxygen 1.6.0   Back to index