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; }
void Gobby::CertificateManager::make_credentials() { InfCertificateCredentials* creds = inf_certificate_credentials_new(); gnutls_certificate_credentials_t gnutls_creds = inf_certificate_credentials_get(creds); if(m_preferences.security.authentication_enabled && m_key != NULL && m_certificates != NULL) { gnutls_certificate_set_x509_key( gnutls_creds, inf_certificate_chain_get_raw(m_certificates), inf_certificate_chain_get_n_certificates(m_certificates), m_key ); } if(m_preferences.security.use_system_trust) { const int n_cas = gnutls_certificate_set_x509_system_trust( gnutls_creds); if(n_cas < 0) { g_warning("Failed to add system CAs: %s\n", gnutls_strerror(n_cas)); } } if(!m_trust.empty()) { gnutls_certificate_set_x509_trust( gnutls_creds, &m_trust[0], m_trust.size() ); } if(m_dh_params != NULL) gnutls_certificate_set_dh_params(gnutls_creds, m_dh_params); gnutls_certificate_set_verify_flags( gnutls_creds, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); InfCertificateCredentials* old_creds = m_credentials; m_credentials = creds; m_signal_credentials_changed.emit(); if(old_creds != NULL) inf_certificate_credentials_unref(old_creds); }
static InfXmppConnection* inf_test_certificate_validate_setup_client(InfIo* io, const gchar* ca_file, const gchar* remote_hostname, GError** error) { InfIpAddress* addr; InfTcpConnection* conn; InfXmppConnection* xmpp; InfCertificateCredentials* creds; GPtrArray* cas; int res; guint i; creds = inf_certificate_credentials_new(); if(ca_file != NULL) { cas = inf_cert_util_read_certificate(ca_file, NULL, error); if(cas == NULL) { inf_certificate_credentials_unref(creds); return NULL; } res = gnutls_certificate_set_x509_trust( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)cas->pdata, cas->len ); for(i = 0; i < cas->len; ++i) gnutls_x509_crt_deinit(cas->pdata[i]); g_ptr_array_free(cas, TRUE); } addr = inf_ip_address_new_loopback4(); conn = inf_tcp_connection_new(io, addr, 6524); inf_ip_address_free(addr); xmpp = inf_xmpp_connection_new( conn, INF_XMPP_CONNECTION_CLIENT, g_get_host_name(), remote_hostname, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, creds, NULL, NULL ); inf_certificate_credentials_unref(creds); if(inf_tcp_connection_open(conn, error) == FALSE) { g_object_unref(conn); g_object_unref(xmpp); return NULL; } g_object_unref(conn); return xmpp; }
static InfdXmppServer* inf_test_certificate_setup_server(InfIo* io, const char* key_file, const char* cert_file, GError** error) { InfdTcpServer* tcp; InfdXmppServer* xmpp; gnutls_x509_privkey_t key; GPtrArray* certs; InfCertificateCredentials* creds; guint i; int res; key = inf_cert_util_read_private_key(key_file, error); if(!key) return NULL; certs = inf_cert_util_read_certificate(cert_file, NULL, error); if(!certs) { gnutls_x509_privkey_deinit(key); return NULL; } creds = inf_certificate_credentials_new(); res = gnutls_certificate_set_x509_key( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)certs->pdata, certs->len, key ); gnutls_x509_privkey_deinit(key); for(i = 0; i < certs->len; ++i) gnutls_x509_crt_deinit(certs->pdata[i]); g_ptr_array_free(certs, TRUE); if(res != 0) { inf_certificate_credentials_unref(creds); inf_gnutls_set_error(error, res); return NULL; } tcp = g_object_new( INFD_TYPE_TCP_SERVER, "io", io, "local-port", 6524, NULL ); if(infd_tcp_server_open(tcp, error) == FALSE) { inf_certificate_credentials_unref(creds); return NULL; } xmpp = infd_xmpp_server_new( tcp, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, creds, NULL, NULL ); /* Keep client connections alive */ g_signal_connect( G_OBJECT(xmpp), "new-connection", G_CALLBACK(inf_test_certificate_validate_new_connection_cb), NULL ); inf_certificate_credentials_unref(creds); return xmpp; }
static void infinoted_plugin_certificate_auth_deinitialize(gpointer plugin_info) { InfinotedPluginCertificateAuth* plugin; InfRequest* remove_acl_account_request; InfCertificateCredentials* creds; guint i; plugin = (InfinotedPluginCertificateAuth*)plugin_info; /* Remove super user account. Note that this is not strictly necessary, * since the acocunt is transient and therefore is not written to disk, * so will not be re-created at the next server start. However, to be sure, * we explicitly remove the account at this point. */ if(plugin->super_id != 0) { remove_acl_account_request = inf_browser_remove_acl_account( INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)), plugin->super_id, infinoted_plugin_certificate_auth_remove_acl_account_cb, plugin ); /* This should be instantaneous: if we are not called back within the call * to inf_browser_remove_acl_account(), then we don't care about the * result, since we are being deinitialized. */ if(remove_acl_account_request != NULL) { inf_signal_handlers_disconnect_by_func( plugin->set_acl_request, G_CALLBACK(infinoted_plugin_certificate_auth_remove_acl_account_cb), plugin ); } } if(plugin->set_acl_request != NULL) { inf_signal_handlers_disconnect_by_func( plugin->set_acl_request, G_CALLBACK(infinoted_plugin_certificate_auth_set_acl_cb), plugin ); g_object_unref(plugin->set_acl_request); } creds = infinoted_plugin_manager_get_credentials(plugin->manager); if(creds != NULL) gnutls_certificate_free_cas(inf_certificate_credentials_get(creds)); infd_directory_set_certificate( infinoted_plugin_manager_get_directory(plugin->manager), NULL, NULL ); /* If we have a ca_key set, the certificate that belongs to the key had * its ownership transferred to the directory, so make sure not to free * it twice here. */ for(i = 0; i < plugin->n_cas; ++i) if(plugin->ca_key == NULL || i != plugin->ca_key_index) gnutls_x509_crt_deinit(plugin->cas[i]); g_free(plugin->cas); if(plugin->ca_key != NULL) gnutls_x509_privkey_deinit(plugin->ca_key); g_free(plugin->ca_list_file); g_free(plugin->ca_key_file); g_free(plugin->super_user); }
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; }