void Gobby::CertificateManager::set_certificates(gnutls_x509_crt_t* certs, guint n_certs, const GError* error) { g_assert(n_certs == 0 || error == NULL); InfCertificateChain* old_certificates = m_certificates; m_certificates = NULL; if(n_certs > 0) m_certificates = inf_certificate_chain_new(certs, n_certs); else m_certificates = NULL; if(m_certificate_error != NULL) g_error_free(m_certificate_error); if(error != NULL) m_certificate_error = g_error_copy(error); else m_certificate_error = NULL; check_certificate_signature(); make_credentials(); // Note that this relies on the fact that // gnutls_certificate_set_x509_key makes a copy of the certificates if(old_certificates != NULL) inf_certificate_chain_unref(old_certificates); }
static gboolean infinoted_startup_load_credentials(InfinotedStartup* startup, GError** error) { gnutls_x509_crt_t* certs; guint n_certs; gnutls_certificate_credentials_t creds; int res; if(startup->options->security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { startup->private_key = infinoted_startup_load_key( startup->log, startup->options->create_key, startup->options->key_file, error ); if(startup->private_key == NULL) return FALSE; certs = infinoted_startup_load_certificate( startup->log, startup->options->create_certificate, startup->private_key, startup->options->certificate_file, startup->options->certificate_chain_file, &n_certs, error ); if(certs == NULL) return FALSE; /* Takes ownership of certificates: */ startup->certificates = inf_certificate_chain_new(certs, n_certs); startup->credentials = inf_certificate_credentials_new(); creds = inf_certificate_credentials_get(startup->credentials); res = gnutls_certificate_set_x509_key( creds, inf_certificate_chain_get_raw(startup->certificates), inf_certificate_chain_get_n_certificates(startup->certificates), startup->private_key ); if(res != 0) { inf_gnutls_set_error(error, res); return FALSE; } } return TRUE; }
static gboolean infinoted_plugin_certificate_auth_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginCertificateAuth* plugin; InfCertificateCredentials* creds; GPtrArray* read_certs; int res; guint i; gnutls_x509_crt_t* sign_certs; InfCertificateChain* sign_chain; gnutls_x509_privkey_t super_key; InfCertUtilDescription desc; gnutls_x509_crt_t super_cert; InfAclAccountId super_id; gnutls_x509_crt_t chain[2]; gboolean written; InfdDirectory* directory; InfBrowserIter iter; InfAclSheetSet sheet_set; InfAclSheet sheet; InfRequest* request; plugin = (InfinotedPluginCertificateAuth*)plugin_info; plugin->manager = manager; creds = infinoted_plugin_manager_get_credentials(manager); if(creds == NULL) { g_set_error( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CREDENTIALS, "%s", _("The certificate-auth plugin can only be used when TLS is enabled " "and a server certificate has been set.") ); return FALSE; } read_certs = inf_cert_util_read_certificate(plugin->ca_list_file, NULL, error); if(read_certs == NULL) return FALSE; if(read_certs->len == 0) { g_set_error( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CAS, _("File \"%s\" does not contain any CA certificates"), plugin->ca_list_file ); g_ptr_array_free(read_certs, TRUE); return FALSE; } plugin->n_cas = read_certs->len; plugin->cas = (gnutls_x509_crt_t*)g_ptr_array_free(read_certs, FALSE); res = gnutls_certificate_set_x509_trust( inf_certificate_credentials_get(creds), plugin->cas, plugin->n_cas ); if(res < 0) { inf_gnutls_set_error(error, res); return FALSE; } if(plugin->ca_key_file != NULL) { plugin->ca_key = inf_cert_util_read_private_key(plugin->ca_key_file, error); if(plugin->ca_key == NULL) return FALSE; /* Walk through certificates and find the certificate that the key * belongs to. */ for(i = 0; i < plugin->n_cas; ++i) if(inf_cert_util_check_certificate_key(plugin->cas[i], plugin->ca_key)) break; if(i == plugin->n_cas) { gnutls_x509_privkey_deinit(plugin->ca_key); plugin->ca_key = NULL; g_set_error( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_FOR_KEY, "%s", _("The given CA key does not match with any of the CA certificates") ); return FALSE; } plugin->ca_key_index = i; /* Set the signing certificate of the directory, so that it can handle * account creation requests. Note that this takes ownership of the * certificate, so we take special care in the cleanup code in * infinoted_plugin_certificate_auth_deinitialize(). */ sign_certs = g_malloc(sizeof(gnutls_x509_crt_t)); sign_certs[0] = plugin->cas[plugin->ca_key_index]; sign_chain = inf_certificate_chain_new(sign_certs, 1); infd_directory_set_certificate( infinoted_plugin_manager_get_directory(plugin->manager), plugin->ca_key, sign_chain ); inf_certificate_chain_unref(sign_chain); } if(plugin->super_user != NULL) { if(plugin->ca_key == NULL) { g_set_error( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_KEY, "%s", _("Cannot generate a superuser certificate without CA key") ); return FALSE; } /* Create a private key and certificate for the super user. */ infinoted_log_info( infinoted_plugin_manager_get_log(plugin->manager), _("Creating 4096-bit RSA private key for the super user account...") ); super_key = inf_cert_util_create_private_key(GNUTLS_PK_RSA, 4096, error); if(super_key == NULL) return FALSE; desc.validity = 12 * 3600; /* 12 hours */ desc.dn_common_name = "Super User"; desc.san_dnsname = NULL; super_cert = inf_cert_util_create_signed_certificate( super_key, &desc, plugin->cas[plugin->ca_key_index], plugin->ca_key, error ); if(super_cert == NULL) { gnutls_x509_privkey_deinit(super_key); return FALSE; } super_id = infd_directory_create_acl_account( infinoted_plugin_manager_get_directory(plugin->manager), _("Super User"), TRUE, /* transient */ &super_cert, 1, error ); if(super_id == 0) { gnutls_x509_crt_deinit(super_cert); gnutls_x509_privkey_deinit(super_key); return FALSE; } plugin->super_id = super_id; chain[0] = super_cert; chain[1] = plugin->cas[plugin->ca_key_index]; written = inf_cert_util_write_certificate_with_key( super_key, chain, 2, plugin->super_user, error ); gnutls_x509_crt_deinit(super_cert); gnutls_x509_privkey_deinit(super_key); if(written == FALSE) return FALSE; inf_browser_get_root( INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)), &iter ); directory = infinoted_plugin_manager_get_directory(plugin->manager); sheet.account = super_id; sheet.mask = INF_ACL_MASK_ALL; infd_directory_get_support_mask(directory, &sheet.perms); sheet_set.n_sheets = 1; sheet_set.own_sheets = NULL; sheet_set.sheets = &sheet; request = inf_browser_set_acl( INF_BROWSER(directory), &iter, &sheet_set, infinoted_plugin_certificate_auth_set_acl_cb, plugin ); if(request != NULL) { plugin->set_acl_request = request; g_object_ref(plugin->set_acl_request); } } return TRUE; }