def db_admin_serialize_node(session, tid, language, config_node='admin_node'): config = ConfigFactory(session, tid).serialize(config_node) # Contexts and Receivers relationship configured = session.query(models.ReceiverContext).filter( models.ReceiverContext.context_id == models.Context.id, models.Context.tid).count() > 0 misc_dict = { 'encryption_available': GCE.ENCRYPTION_AVAILABLE, 'languages_supported': LANGUAGES_SUPPORTED, 'languages_enabled': models.EnabledLanguage.list(session, tid), 'configured': configured, 'root_tenant': tid == 1, 'https_possible': tid == 1 or State.tenant_cache[1].reachable_via_web, } if tid != 1: root_tenant_node = ConfigFactory(session, 1) misc_dict['version'] = root_tenant_node.get_val(u'version') misc_dict['latest_version'] = root_tenant_node.get_val( u'latest_version') l10n_dict = ConfigL10NFactory(session, tid).serialize('node', language) return utils.sets.merge_dicts(config, misc_dict, l10n_dict)
def db_acme_cert_issuance(session, tid): priv_fact = ConfigFactory(session, tid, 'node') hostname = State.tenant_cache[tid].hostname raw_accnt_key = priv_fact.get_val(u'acme_accnt_key') accnt_key = serialization.load_pem_private_key(str(raw_accnt_key), password=None, backend=default_backend()) priv_key = priv_fact.get_val(u'https_priv_key') regr_uri = priv_fact.get_val(u'acme_accnt_uri') csr_fields = {'CN': hostname} # NOTE sha256 is always employed as hash fnc here. csr = tls.gen_x509_csr(priv_key, csr_fields, 256) tmp_chall_dict = State.tenant_state[tid].acme_tmp_chall_dict # Run ACME registration all the way to resolution cert_str, chain_str = letsencrypt.run_acme_reg_to_finish( hostname, regr_uri, accnt_key, priv_key, csr, tmp_chall_dict, Settings.acme_directory_url) priv_fact.set_val(u'https_cert', cert_str) priv_fact.set_val(u'https_chain', chain_str) State.tenant_cache[tid].https_cert = cert_str State.tenant_cache[tid].https_chain = chain_str
def db_admin_serialize_node(session, tid, language): config = ConfigFactory(session, tid, 'admin_node').serialize() # Contexts and Receivers relationship configured = session.query(models.ReceiverContext).filter( models.ReceiverContext.context_id == models.Context.id, models.Context.tid).count() > 0 misc_dict = { 'languages_supported': LANGUAGES_SUPPORTED, 'languages_enabled': models.EnabledLanguage.list(session, tid), 'configured': configured, 'root_tenant': tid == 1, 'https_possible': tid == 1 or State.tenant_cache[1].reachable_via_web, } if tid != 1: root_tenant_node = ConfigFactory(session, 1, 'node') misc_dict['version'] = root_tenant_node.get_val(u'version') misc_dict['latest_version'] = root_tenant_node.get_val( u'latest_version') misc_dict['enable_footer_customization'] = root_tenant_node.get_val( u'enable_footer_customization') l10n_dict = NodeL10NFactory(session, tid).localized_dict(language) return utils.sets.merge_dicts(config, misc_dict, l10n_dict)
def db_admin_serialize_node(session, tid, language, config_node='admin_node'): """ Transaction for fetching the node configuration as admin :param session: An ORM session :param tid: A tenant ID :param language: The language to be used on serialization :param config_node: The set of variables to be serialized :return: Return the serialized configuration for the specified tenant """ config = ConfigFactory(session, tid).serialize(config_node) logo = session.query(models.File.data).filter(models.File.tid == tid, models.File.id == 'logo').one_or_none() misc_dict = { 'languages_supported': LANGUAGES_SUPPORTED, 'languages_enabled': db_get_languages(session, tid), 'root_tenant': tid == 1, 'https_possible': tid == 1 or State.tenant_cache[1].reachable_via_web, 'encryption_possible': tid == 1 or State.tenant_cache[1].encryption, 'logo': logo if logo else '' } if tid != 1: root_tenant_node = ConfigFactory(session, 1) misc_dict['version'] = root_tenant_node.get_val('version') misc_dict['latest_version'] = root_tenant_node.get_val('latest_version') l10n_dict = ConfigL10NFactory(session, tid).serialize('node', language) return utils.sets.merge_dicts(config, misc_dict, l10n_dict)
def db_admin_serialize_node(session, tid, language, config_node='admin_node'): """ Transaction for fetching the node configuration as admin :param session: An ORM session :param tid: A tenant ID :param language: The language to be used on serialization :param config_node: The set of variables to be serialized :return: Return the serialized configuration for the specified tenant """ config = ConfigFactory(session, tid).serialize(config_node) misc_dict = { 'languages_supported': LANGUAGES_SUPPORTED, 'languages_enabled': models.EnabledLanguage.list(session, tid), 'root_tenant': tid == 1, 'https_possible': tid == 1 or State.tenant_cache[1].reachable_via_web, } if tid != 1: root_tenant_node = ConfigFactory(session, 1) misc_dict['version'] = root_tenant_node.get_val('version') misc_dict['latest_version'] = root_tenant_node.get_val( 'latest_version') l10n_dict = ConfigL10NFactory(session, tid).serialize('node', language) return utils.sets.merge_dicts(config, misc_dict, l10n_dict)
def db_acme_cert_request(session, tid): priv_fact = ConfigFactory(session, tid) hostname = State.tenant_cache[tid].hostname raw_accnt_key = priv_fact.get_val('acme_accnt_key') if not raw_accnt_key: raw_accnt_key = db_create_acme_key(session, tid) if isinstance(raw_accnt_key, str): raw_accnt_key = raw_accnt_key.encode() accnt_key = serialization.load_pem_private_key(raw_accnt_key, password=None, backend=default_backend()) priv_key = priv_fact.get_val('https_priv_key') cert_str, chain_str = letsencrypt.request_new_certificate( hostname, accnt_key, priv_key, State.tenant_state[tid].acme_tmp_chall_dict, Settings.acme_directory_url) priv_fact.set_val('https_cert', cert_str) priv_fact.set_val('https_chain', chain_str) State.tenant_cache[tid].https_cert = cert_str State.tenant_cache[tid].https_chain = chain_str
def db_update_node(session, tid, user_session, request, language): """ Transaction to update the node configuration :param session: An ORM session :param tid: A tenant ID :param user_session: The current user session :param request: The request data :param language: the language in which to localize data :return: Return the serialized configuration for the specified tenant """ config = ConfigFactory(session, tid) enable_escrow = not config.get_val('escrow') and request.get('escrow', False) disable_escrow = user_session.ek and config.get_val('escrow') and not request.get('escrow', False) config.update('node', request) if request['enable_ricochet_panel'] and not request['ricochet_address']: request['enable_ricochet_panel'] = False # Validate that IP addresses/ranges we're getting are goo if 'ip_filter_admin' in request and request['ip_filter_admin_enable'] and request['ip_filter_admin']: parse_csv_ip_ranges_to_ip_networks(request['ip_filter_admin']) if 'languages_enabled' in request and 'default_language' in request: db_update_enabled_languages(session, tid, request['languages_enabled'], request['default_language']) if language in db_get_languages(session, tid): ConfigL10NFactory(session, tid).update('node', request, language) if enable_escrow: crypto_escrow_prv_key, State.tenant_cache[tid].crypto_escrow_pub_key = GCE.generate_keypair() user = db_get(session, models.User, models.User.id == user_session.user_id) user.crypto_escrow_prv_key = Base64Encoder.encode(GCE.asymmetric_encrypt(user.crypto_pub_key, crypto_escrow_prv_key)) if tid == 1: session.query(models.User).update({'password_change_needed': True}, synchronize_session=False) else: session.query(models.User).filter(models.User.tid == tid).update({'password_change_needed': True}, synchronize_session=False) if disable_escrow: if tid == 1: session.query(models.User).update({'crypto_escrow_bkp1_key': ''}, synchronize_session=False) else: session.query(models.User).update({'crypto_escrow_bkp2_key': ''}, synchronize_session=False) session.query(models.User).filter(models.User.tid == tid).update({'crypto_escrow_prv_key': ''}, synchronize_session=False) config.set_val('crypto_escrow_pub_key', State.tenant_cache[tid].crypto_escrow_pub_key) db_refresh_memory_variables(session, [tid]) if tid == 1: log.setloglevel(config.get_val('log_level')) return db_admin_serialize_node(session, tid, language)
def signup_activation(session, state, tid, token, language): config = ConfigFactory(session, 1) if not config.get_val(u'enable_signup'): raise errors.ForbiddenOperation signup = session.query(models.Signup).filter( models.Signup.activation_token == token).one_or_none() if signup is None: return {} if not session.query( models.Config).filter(models.Config.tid == signup.tid).count(): tenant = session.query( models.Tenant).filter(models.Tenant.id == signup.tid).one() mode = config.get_val('mode') db_initialize_tenant(session, tenant, mode) password_admin = generateRandomKey(16) password_recipient = generateRandomKey(16) node_name = signup.organization_name if signup.organization_name else signup.subdomain wizard = { 'node_language': signup.language, 'node_name': node_name, 'admin_name': signup.name + ' ' + signup.surname, 'admin_password': password_admin, 'admin_mail_address': signup.email, 'receiver_name': signup.name + ' ' + signup.surname, 'receiver_password': password_recipient, 'receiver_mail_address': signup.email, 'profile': 'default', 'enable_developers_exception_notification': True } db_wizard(session, signup.tid, wizard, False, language) ids = [ r[0] for r in session.query(models.User.id).filter( models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == signup.tid) ] template_vars = { 'type': 'activation', 'node': db_admin_serialize_node(session, 1, language), 'notification': db_get_notification(session, 1, language), 'signup': serialize_signup(signup), 'password_admin': password_admin, 'password_recipient': password_recipient } state.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) db_refresh_memory_variables(session, [1])
def db_serialize_node(session, tid, language): """ Serialize the public node configuration. :param session: An ORM session :param tid: A tenant ID :param language: The language to be used during serialization :return: The serialization of the public node configuration """ node_dict = ConfigFactory(session, tid).serialize('public_node') l10n_dict = ConfigL10NFactory( session, tid, ).serialize('node', language) ret_dict = merge_dicts(node_dict, l10n_dict) ret_dict['root_tenant'] = tid == 1 ret_dict['languages_enabled'] = models.EnabledLanguage.list( session, tid) if node_dict['wizard_done'] else list(LANGUAGES_SUPPORTED_CODES) ret_dict['languages_supported'] = LANGUAGES_SUPPORTED records = session.query(models.File.id, models.File.data).filter( models.File.tid == tid, models.File.id.in_(['css', 'script'])) for x in records: ret_dict[x[0]] = True if tid != 1: root_tenant_node = ConfigFactory(session, 1) for varname in ['version', 'version_db', 'latest_version']: ret_dict[varname] = root_tenant_node.get_val(varname) if language not in models.EnabledLanguage.list(session, tid): language = root_tenant_node.get_val('default_language') root_tenant_l10n = ConfigL10NFactory(session, 1) if ret_dict['mode'] != 'default': ret_dict['footer'] = root_tenant_l10n.get_val('footer', language) ret_dict['whistleblowing_question'] = root_tenant_l10n.get_val( 'whistleblowing_question', language) ret_dict['whistleblowing_button'] = root_tenant_l10n.get_val( 'whistleblowing_button', language) ret_dict['enable_disclaimer'] = root_tenant_node.get_val( 'enable_disclaimer') ret_dict['disclaimer_title'] = root_tenant_l10n.get_val( 'disclaimer_title', language) ret_dict['disclaimer_text'] = root_tenant_l10n.get_val( 'disclaimer_text', language) records = session.query(models.File.id, models.File.data).filter( models.File.tid == 1, models.File.id.in_(['css', 'script'])) for x in records: if not ret_dict.get(x[0]): ret_dict[x[0]] = True return ret_dict
def db_serialize_node(session, tid, language): """ Serialize the public node configuration. """ node_dict = ConfigFactory(session, tid).serialize('public_node') l10n_dict = ConfigL10NFactory( session, tid, ).serialize('node', language) ret_dict = merge_dicts(node_dict, l10n_dict) ret_dict['root_tenant'] = tid == 1 ret_dict['languages_enabled'] = models.EnabledLanguage.list( session, tid) if node_dict['wizard_done'] else list(LANGUAGES_SUPPORTED_CODES) ret_dict['languages_supported'] = LANGUAGES_SUPPORTED files = [u'logo', u'favicon', u'css', u'script'] records = session.query(models.File.id, models.File.data).filter( models.File.tid == tid, models.File.id.in_([u'logo', u'favicon', u'css', u'script'])) for x in records: ret_dict[x[0]] = x[1] if x[0] == 'logo' else True if tid != 1: root_tenant_node = ConfigFactory(session, 1) for varname in ['version', 'version_db', 'latest_version']: ret_dict[varname] = root_tenant_node.get_val(varname) if language not in models.EnabledLanguage.list(session, tid): language = root_tenant_node.get_val(u'default_language') root_tenant_l10n = ConfigL10NFactory(session, 1) if ret_dict['mode'] != u'default': ret_dict['footer'] = root_tenant_l10n.get_val(u'footer', language) ret_dict['whistleblowing_question'] = root_tenant_l10n.get_val( u'whistleblowing_question', language) ret_dict['whistleblowing_button'] = root_tenant_l10n.get_val( u'whistleblowing_button', language) ret_dict['enable_disclaimer'] = root_tenant_node.get_val( u'enable_disclaimer') ret_dict['disclaimer_title'] = root_tenant_l10n.get_val( u'disclaimer_title', language) ret_dict['disclaimer_text'] = root_tenant_l10n.get_val( u'disclaimer_text', language) records = session.query(models.File.id, models.File.data).filter( models.File.tid == 1, models.File.id.in_([u'logo', u'favicon', u'css', u'script'])) for x in records: if not ret_dict[x[0]]: ret_dict[x[0]] = x[1] if x[0] == 'logo' else True return ret_dict
def db_get_onion_service_info(session, tid): node = ConfigFactory(session, tid) hostname = node.get_val('onionservice') key = node.get_val('tor_onion_key') old_hostname = node.get_val('old_onionservice') old_key = node.get_val('old_tor_onion_key') return tid, hostname, key, old_hostname, old_key
def db_serialize_node(session, tid, language): """ Serialize node info. """ # Contexts and Receivers relationship configured = session.query(models.ReceiverContext).filter( models.ReceiverContext.context_id == models.Context.id, models.Context.tid == tid).count() > 0 node_dict = ConfigFactory(session, tid, 'public_node').serialize() l10n_dict = NodeL10NFactory(session, tid).localized_dict(language) ret_dict = merge_dicts(node_dict, l10n_dict) ret_dict['root_tenant'] = tid == 1 ret_dict['languages_enabled'] = models.EnabledLanguage.list( session, tid) if node_dict['wizard_done'] else list(LANGUAGES_SUPPORTED_CODES) ret_dict['languages_supported'] = LANGUAGES_SUPPORTED ret_dict['configured'] = configured ret_dict['accept_submissions'] = State.accept_submissions ret_dict['logo'] = db_get_file(session, tid, u'logo') ret_dict['favicon'] = db_get_file(session, tid, u'favicon') ret_dict['css'] = db_get_file(session, tid, u'css') ret_dict['script'] = db_get_file(session, tid, u'script') if tid != 1: root_tenant_node = ConfigFactory(session, 1, 'public_node') if language not in models.EnabledLanguage.list(session, tid): language = root_tenant_node.get_val(u'default_language') for x in [u'logo', u'favicon', u'css', u'scripts']: if not ret_dict[x]: ret_dict[x] = db_get_file(session, 1, x) root_tenant_l10n = NodeL10NFactory(session, tid) if not root_tenant_node.get_val(u'enable_footer_customization'): ret_dict['footer'] = root_tenant_l10n.get_val(u'footer', language) if ret_dict['mode'] == u'whistleblowing.it': ret_dict['whistleblowing_question'] = root_tenant_l10n.get_val( u'whistleblowing_question', language) ret_dict['whistleblowing_button'] = root_tenant_l10n.get_val( u'whistleblowing_button', language) ret_dict['enable_disclaimer'] = root_tenant_node.get_val( u'enable_disclaimer') ret_dict['disclaimer_title'] = root_tenant_l10n.get_val( u'disclaimer_title', language) ret_dict['disclaimer_text'] = root_tenant_l10n.get_val( u'disclaimer_text', language) return ret_dict
def db_get_sites(session): sites = [] root_tenant = ConfigFactory(session, 1) root_domain = root_tenant.get_val('rootdomain') root_onionservice = root_tenant.get_val('onionservice') for tid in session.query(models.Tenant.id).filter( models.Tenant.active.is_(True)): tenant = ConfigFactory(session, tid[0]) site = { 'id': tid[0], 'name': tenant.get_val('name'), 'hostname': tenant.get_val('hostname'), 'onionservice': tenant.get_val('onionservice') } sites.append(site) if tid == 1 or tenant.get_val('mode') == 'default': pass subdomain = tenant.get_val('subdomain') if subdomain: site['hostname'] = subdomain + '.' + root_tenant.get_val( 'rootdomain') site['onionservice'] = subdomain + '.' + root_tenant.get_val( 'onionservice') return sites
def serialize_https_config_summary(session, tid): config = ConfigFactory(session, tid) file_summaries = {} for key, file_res_cls in FileHandler.mapped_file_resources.items(): file_summaries[key] = file_res_cls.db_serialize(session, tid) return { 'enabled': config.get_val('https_enabled'), 'files': file_summaries, 'acme': config.get_val('acme') }
def db_serialize_node(session, tid, language): """ Serialize the public node configuration. """ # Contexts and Receivers relationship node_dict = ConfigFactory(session, tid).serialize('public_node') l10n_dict = ConfigL10NFactory( session, tid, ).serialize('node', language) ret_dict = merge_dicts(node_dict, l10n_dict) ret_dict['root_tenant'] = tid == 1 ret_dict['languages_enabled'] = models.EnabledLanguage.list( session, tid) if node_dict['wizard_done'] else list(LANGUAGES_SUPPORTED_CODES) ret_dict['languages_supported'] = LANGUAGES_SUPPORTED files = [u'logo', u'favicon', u'css', u'script'] for x in files: ret_dict[x] = db_get_file(session, tid, x) if tid != 1: root_tenant_node = ConfigFactory(session, 1) for varname in ['version', 'version_db', 'latest_version']: ret_dict[varname] = root_tenant_node.get_val(varname) if language not in models.EnabledLanguage.list(session, tid): language = root_tenant_node.get_val(u'default_language') root_tenant_l10n = ConfigL10NFactory(session, 1) if ret_dict['mode'] == u'whistleblowing.it' or ret_dict[ 'mode'] == u'eat': ret_dict['footer'] = root_tenant_l10n.get_val(u'footer', language) ret_dict['whistleblowing_question'] = root_tenant_l10n.get_val( u'whistleblowing_question', language) ret_dict['whistleblowing_button'] = root_tenant_l10n.get_val( u'whistleblowing_button', language) ret_dict['enable_disclaimer'] = root_tenant_node.get_val( u'enable_disclaimer') ret_dict['disclaimer_title'] = root_tenant_l10n.get_val( u'disclaimer_title', language) ret_dict['disclaimer_text'] = root_tenant_l10n.get_val( u'disclaimer_text', language) for x in files: if not ret_dict[x]: ret_dict[x] = db_get_file(session, 1, x) return ret_dict
def signup_activation(session, state, tid, token, language): config = ConfigFactory(session, 1) if not config.get_val(u'enable_signup'): raise errors.ForbiddenOperation signup = session.query(models.Signup).filter(models.Signup.activation_token == token).one_or_none() if signup is None: return {} if not session.query(models.Config).filter(models.Config.tid == signup.tid).count(): tenant = session.query(models.Tenant).filter(models.Tenant.id == signup.tid).one() mode = config.get_val('mode') db_initialize_tenant(session, tenant, mode) password_admin = generateRandomKey(16) password_recipient = generateRandomKey(16) node_name = signup.organization_name if signup.organization_name else signup.subdomain wizard = { 'node_language': signup.language, 'node_name': node_name, 'admin_name': signup.name + ' ' + signup.surname, 'admin_password': password_admin, 'admin_mail_address': signup.email, 'receiver_name': signup.name + ' ' + signup.surname, 'receiver_password': password_recipient, 'receiver_mail_address': signup.email, 'profile': 'default', 'enable_developers_exception_notification': True } db_wizard(session, signup.tid, wizard, False, language) ids = [r[0] for r in session.query(models.User.id).filter(models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == signup.tid)] template_vars = { 'type': 'activation', 'node': db_admin_serialize_node(session, 1, language), 'notification': db_get_notification(session, 1, language), 'signup': serialize_signup(signup), 'password_admin': password_admin, 'password_recipient': password_recipient } state.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) db_refresh_memory_variables(session, [1])
def serialize_https_config_summary(session, tid): config = ConfigFactory(session, tid) file_summaries = {} for key, file_res_cls in FileHandler.mapped_file_resources.items(): file_summaries[key] = file_res_cls.db_serialize(session, tid) return { 'enabled': config.get_val(u'https_enabled'), 'running': State.process_supervisor.is_running(), 'status': State.process_supervisor.get_status(), 'files': file_summaries, 'acme': config.get_val(u'acme') }
def load_tls_dict(session, tid): """ A quick and dirty function to grab all of the tls config for use in subprocesses """ node = ConfigFactory(session, tid) return { 'tid': tid, 'ssl_key': node.get_val(u'https_priv_key'), 'ssl_cert': node.get_val(u'https_cert'), 'ssl_intermediate': node.get_val(u'https_chain'), 'https_enabled': node.get_val(u'https_enabled'), 'hostname': node.get_val(u'hostname'), }
def serialize_https_config_summary(session, tid): config = ConfigFactory(session, tid) file_summaries = {} for key, file_res_cls in FileHandler.mapped_file_resources.items(): file_summaries[key] = file_res_cls.db_serialize(session, tid) return { 'enabled': config.get_val(u'https_enabled'), 'running': State.process_supervisor.is_running(), 'status': State.process_supervisor.get_status(), 'files': file_summaries, 'acme': config.get_val(u'acme') }
def db_maybe_launch_https_workers(self, session): config = ConfigFactory(session, 1) # If root_tenant is disabled do not start https on = config.get_val(u'https_enabled') if not on: log.info("Not launching workers") return defer.succeed(None) site_cfgs = load_tls_dict_list(session) valid_cfgs, err = [], None # Determine which site_cfgs are valid and only pass those to the child. for db_cfg in site_cfgs: chnv = tls.ChainValidator() ok, err = chnv.validate(db_cfg, must_be_disabled=False, check_expiration=False) if ok and err is None: valid_cfgs.append(db_cfg) self.tls_cfg['site_cfgs'] = valid_cfgs if not valid_cfgs: log.info("Not launching https workers due to %s", err) return defer.fail(err) log.info("Decided to launch https workers") return self.launch_https_workers()
def get_l10n(session, tid, lang): """ Transaction for retrieving the custom texts configured for a specific language :param session: An ORM session :param tid: The tenant ID of the tenant on which perform the lookup :param lang: A requested language :return: A dictionary containing the custom texts configured for a specific language """ if tid != 1: config = ConfigFactory(session, tid) if config.get_val('mode') != 'default': tid = 1 path = langfile_path(lang) directory_traversal_check(Settings.client_path, path) custom_texts = session.query(models.CustomTexts).filter(models.CustomTexts.lang == lang, models.CustomTexts.tid == tid).one_or_none() custom_texts = custom_texts.texts if custom_texts is not None else {} texts = read_json_file(path) texts.update(custom_texts) return texts
def db_acme_cert_issuance(session, tid): priv_fact = ConfigFactory(session, tid) hostname = State.tenant_cache[tid].hostname # Temporary fix for https://github.com/certbot/certbot/issues/6246 # raw_accnt_key = priv_fact.get_val(u'acme_accnt_key') raw_accnt_key = db_create_acme_key(session, tid) if isinstance(raw_accnt_key, text_type): raw_accnt_key = raw_accnt_key.encode() accnt_key = serialization.load_pem_private_key(raw_accnt_key, password=None, backend=default_backend()) priv_key = priv_fact.get_val(u'https_priv_key') tmp_chall_dict = State.tenant_state[tid].acme_tmp_chall_dict # Run ACME registration all the way to resolution cert_str, chain_str = letsencrypt.run_acme_reg_to_finish(hostname, accnt_key, priv_key, hostname, tmp_chall_dict, Settings.acme_directory_url) priv_fact.set_val(u'https_cert', cert_str) priv_fact.set_val(u'https_chain', chain_str) State.tenant_cache[tid].https_cert = cert_str State.tenant_cache[tid].https_chain = chain_str
def db_acme_cert_issuance(session, tid): priv_fact = ConfigFactory(session, tid) hostname = State.tenant_cache[tid].hostname # Temporary fix for https://github.com/certbot/certbot/issues/6246 # raw_accnt_key = priv_fact.get_val(u'acme_accnt_key') raw_accnt_key = db_create_acme_key(session, tid) if isinstance(raw_accnt_key, text_type): raw_accnt_key = raw_accnt_key.encode() accnt_key = serialization.load_pem_private_key(raw_accnt_key, password=None, backend=default_backend()) priv_key = priv_fact.get_val(u'https_priv_key') tmp_chall_dict = State.tenant_state[tid].acme_tmp_chall_dict # Run ACME registration all the way to resolution cert_str, chain_str = letsencrypt.run_acme_reg_to_finish( hostname, accnt_key, priv_key, hostname, tmp_chall_dict, Settings.acme_directory_url) priv_fact.set_val(u'https_cert', cert_str) priv_fact.set_val(u'https_chain', chain_str) State.tenant_cache[tid].https_cert = cert_str State.tenant_cache[tid].https_chain = chain_str
def evaluate_update_notification(session, state, latest_version): priv_fact = ConfigFactory(session, 1) stored_latest = priv_fact.get_val('latest_version') # Check if the running version is lower than the latest version if parse_version(stored_latest) >= parse_version(latest_version): return Cache.invalidate() priv_fact.set_val('latest_version', latest_version) # Check to reduce number of email notifications of new updates if parse_version(__version__) != parse_version(stored_latest): return for user_desc in db_get_users(session, 1, 'admin'): if not user_desc['notification']: continue lang = user_desc['language'] template_vars = { 'type': 'software_update_available', 'latest_version': latest_version, 'node': db_admin_serialize_node(session, 1, lang), 'notification': db_get_notification(session, 1, lang), 'user': user_desc, } state.format_and_send_mail(session, 1, user_desc, template_vars)
def db_serialize(session, tid): config = ConfigFactory(session, tid) return { 'set': config.get_val(u'https_priv_key') != u'', 'gen': config.get_val(u'https_priv_gen') }
def db_serialize(session, tid): config = ConfigFactory(session, tid) return { 'set': config.get_val(u'https_priv_key') != u'', 'gen': config.get_val(u'https_priv_gen') }
def db_serialize_node(session, tid, language): """ Serialize node info. """ # Contexts and Receivers relationship configured = session.query(models.ReceiverContext).filter( models.ReceiverContext.context_id == models.Context.id, models.Context.tid == tid).count() > 0 node = ConfigFactory(session, tid, 'public_node').serialize() misc_dict = { 'languages_enabled': models.EnabledLanguage.list(session, tid) if node['wizard_done'] else list(LANGUAGES_SUPPORTED_CODES), 'languages_supported': LANGUAGES_SUPPORTED, 'configured': configured, 'accept_submissions': State.accept_submissions, 'logo': db_get_file(session, tid, u'logo'), 'favicon': db_get_file(session, tid, u'favicon'), 'css': db_get_file(session, tid, u'css'), 'homepage': db_get_file(session, tid, u'homepage'), 'script': db_get_file(session, tid, u'script') } l10n_dict = NodeL10NFactory(session, tid).localized_dict(language) if tid != 1: root_tenant_node = ConfigFactory(session, 1, 'public_node') misc_dict['enable_footer_customization'] = root_tenant_node.get_val( u'enable_footer_customization') if language not in models.EnabledLanguage.list(session, tid): language = root_tenant_node.get_val(u'default_language') root_tenant_l10n = NodeL10NFactory(session, tid) l10n_dict['footer'] = root_tenant_l10n.get_val(u'footer', language) return merge_dicts(node, l10n_dict, misc_dict)
def load_tls_dict(session, tid): """ Transaction for loading the TLS configuration of a tenant :param session: An ORM session :param tid: A tenant ID :return: The serialized TLS configuration for the specified tenant """ node = ConfigFactory(session, tid) return { 'tid': tid, 'ssl_key': node.get_val('https_key'), 'ssl_cert': node.get_val('https_cert'), 'ssl_intermediate': node.get_val('https_chain'), 'https_enabled': node.get_val('https_enabled'), 'hostname': node.get_val('hostname'), }
def db_admin_serialize_node(session, tid, language, config_node='admin_node'): config = ConfigFactory(session, tid).serialize(config_node) misc_dict = { 'languages_supported': LANGUAGES_SUPPORTED, 'languages_enabled': models.EnabledLanguage.list(session, tid), 'root_tenant': tid == 1, 'https_possible': tid == 1 or State.tenant_cache[1].reachable_via_web, } if tid != 1: root_tenant_node = ConfigFactory(session, 1) misc_dict['version'] = root_tenant_node.get_val('version') misc_dict['latest_version'] = root_tenant_node.get_val('latest_version') l10n_dict = ConfigL10NFactory(session, tid).serialize('node', language) return utils.sets.merge_dicts(config, misc_dict, l10n_dict)
def serialize_tenant(session, tenant, signup=None): from globaleaks.handlers.signup import serialize_signup node = ConfigFactory(session, tenant.id) ret = { 'id': tenant.id, 'label': tenant.label, 'active': tenant.active, 'subdomain': tenant.subdomain, 'hostname': node.get_val('hostname'), 'onionservice': node.get_val('onionservice'), 'mode': node.get_val('mode'), 'creation_date': tenant.creation_date } if signup is not None: ret['signup'] = serialize_signup(signup) return ret
def signup(session, state, tid, request, language): config = ConfigFactory(session, 1) if not config.get_val(u'enable_signup'): raise errors.ForbiddenOperation request['activation_token'] = generateRandomKey(32) request['language'] = language tenant_id = db_preallocate_tenant(session, { 'label': request['subdomain'], 'subdomain': request['subdomain'] }).id signup = models.Signup(request) signup.tid = tenant_id session.add(signup) # We need to send two emails # # The first one is sent to the platform owner with the activation email. # # The second goes to the instance administrators notifying them that a new # platform has been added. signup_dict = serialize_signup(signup) # Email 1 - Activation Link template_vars = { 'type': 'signup', 'node': db_admin_serialize_node(session, 1, language), 'notification': db_get_notification(session, 1, language), 'signup': signup_dict } state.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) # Email 2 - Admin Notification for user_desc in db_get_admin_users(session, 1): template_vars = { 'type': 'admin_signup_alert', 'signup': serialize_signup(signup), 'node': db_admin_serialize_node(session, 1, user_desc['language']), 'notification': db_get_notification(session, 1, user_desc['language']), 'user': user_desc, 'signup': signup_dict } state.format_and_send_mail(session, 1, user_desc, template_vars)
def db_serialize_node(session, tid, language): """ Serialize the public node configuration. """ # Contexts and Receivers relationship node_dict = ConfigFactory(session, tid).serialize('public_node') l10n_dict = ConfigL10NFactory(session, tid,).serialize('node', language) ret_dict = merge_dicts(node_dict, l10n_dict) ret_dict['root_tenant'] = tid == 1 ret_dict['languages_enabled'] = models.EnabledLanguage.list(session, tid) if node_dict['wizard_done'] else list(LANGUAGES_SUPPORTED_CODES) ret_dict['languages_supported'] = LANGUAGES_SUPPORTED files = [u'logo', u'favicon', u'css', u'script'] for x in files: ret_dict[x] = db_get_file(session, tid, x) if tid != 1: root_tenant_node = ConfigFactory(session, 1) if language not in models.EnabledLanguage.list(session, tid): language = root_tenant_node.get_val(u'default_language') root_tenant_l10n = ConfigL10NFactory(session, 1) if ret_dict['mode'] == u'whistleblowing.it' or ret_dict['mode'] == u'eat': ret_dict['footer'] = root_tenant_l10n.get_val(u'footer', language) ret_dict['whistleblowing_question'] = root_tenant_l10n.get_val(u'whistleblowing_question', language) ret_dict['whistleblowing_button'] = root_tenant_l10n.get_val(u'whistleblowing_button', language) ret_dict['enable_disclaimer'] = root_tenant_node.get_val(u'enable_disclaimer') ret_dict['disclaimer_title'] = root_tenant_l10n.get_val(u'disclaimer_title', language) ret_dict['disclaimer_text'] = root_tenant_l10n.get_val(u'disclaimer_text', language) for x in files: if not ret_dict[x]: ret_dict[x] = db_get_file(session, 1, x) return ret_dict
def db_acme_cert_issuance(session, tid): priv_fact = ConfigFactory(session, tid, 'node') hostname = State.tenant_cache[tid].hostname raw_accnt_key = priv_fact.get_val(u'acme_accnt_key') accnt_key = serialization.load_pem_private_key(raw_accnt_key.encode(), password=None, backend=default_backend()) priv_key = priv_fact.get_val(u'https_priv_key') tmp_chall_dict = State.tenant_state[tid].acme_tmp_chall_dict # Run ACME registration all the way to resolution cert_str, chain_str = letsencrypt.run_acme_reg_to_finish( hostname, accnt_key, priv_key, hostname, tmp_chall_dict, Settings.acme_directory_url) priv_fact.set_val(u'https_cert', cert_str) priv_fact.set_val(u'https_chain', chain_str) State.tenant_cache[tid].https_cert = cert_str State.tenant_cache[tid].https_chain = chain_str
def db_update_node(session, tid, request, language): """ Update and serialize the node infos :param tid: :param request: :param session: the session on which perform queries. :param language: the language in which to localize data :return: a dictionary representing the serialization of the node """ config = ConfigFactory(session, tid) config.update('node', request) if 'basic_auth' in request and request['basic_auth'] and request[ 'basic_auth_username'] and request['basic_auth_password']: config.set_val('basic_auth', True) config.set_val('basic_auth_username', request['basic_auth_username']) config.set_val('basic_auth_password', request['basic_auth_password']) else: config.set_val('basic_auth', False) config.set_val('basic_auth_username', '') config.set_val('basic_auth_password', '') if request['enable_ricochet_panel'] and not request['ricochet_address']: request['enable_ricochet_panel'] = False # Validate that IP addresses/ranges we're getting are goo if 'ip_filter_admin' in request and request[ 'ip_filter_admin_enable'] and request['ip_filter_admin']: parse_csv_ip_ranges_to_ip_networks(request['ip_filter_admin']) if 'ip_filter_whistleblower_enable' in request and request[ 'ip_filter_whistleblower_enable'] and request[ 'ip_filter_whistleblower']: parse_csv_ip_ranges_to_ip_networks(request['ip_filter_whistleblower']) if 'languages_enabled' in request and 'default_language' in request: db_update_enabled_languages(session, tid, request['languages_enabled'], request['default_language']) if language in models.EnabledLanguage.list(session, tid): ConfigL10NFactory(session, tid).update('node', request, language) db_refresh_memory_variables(session, [tid]) if tid == 1: log.setloglevel(config.get_val('log_level')) return db_admin_serialize_node(session, tid, language)
def signup(session, state, tid, request, language): config = ConfigFactory(session, 1) if not config.get_val(u'enable_signup'): raise errors.ForbiddenOperation request['activation_token'] = generateRandomKey(32) request['language'] = language tenant_id = db_preallocate_tenant(session, {'label': request['subdomain'], 'subdomain': request['subdomain']}).id signup = models.Signup(request) signup.tid = tenant_id session.add(signup) # We need to send two emails # # The first one is sent to the platform owner with the activation email. # # The second goes to the instance administrators notifying them that a new # platform has been added. signup_dict = serialize_signup(signup) # Email 1 - Activation Link template_vars = { 'type': 'signup', 'node': db_admin_serialize_node(session, 1, language), 'notification': db_get_notification(session, 1, language), 'signup': signup_dict } state.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) # Email 2 - Admin Notification for user_desc in db_get_admin_users(session, 1): template_vars = { 'type': 'admin_signup_alert', 'node': db_admin_serialize_node(session, 1, user_desc['language']), 'notification': db_get_notification(session, 1, user_desc['language']), 'user': user_desc, 'signup': signup_dict } state.format_and_send_mail(session, 1, user_desc, template_vars)
def perform_data_update(db_file): session = get_session(make_db_uri(db_file), foreign_keys=False) enabled_languages = [ lang.name for lang in session.query(models.EnabledLanguage) ] removed_languages = list( set(enabled_languages) - set(LANGUAGES_SUPPORTED_CODES)) if removed_languages: removed_languages.sort() removed_languages = ', '.join(removed_languages) raise Exception( "FATAL: cannot complete the upgrade because the support for some of the enabled languages is currently incomplete (%s)\n" "Read about how to handle this condition at: https://github.com/globaleaks/GlobaLeaks/wiki/Upgrade-Guide#lang-drop" % removed_languages) try: cfg = ConfigFactory(session, 1) stored_ver = cfg.get_val(u'version') if stored_ver != __version__: # The below commands can change the current store based on the what is # currently stored in the DB. for tid in [t[0] for t in session.query(models.Tenant.id)]: appdata = load_appdata() config.update_defaults(session, tid, appdata) db_update_defaults(session) db_fix(session) cfg.set_val(u'version', __version__) cfg.set_val(u'latest_version', __version__) cfg.set_val(u'version_db', DATABASE_VERSION) session.commit() except: session.rollback() raise finally: session.close()
def load_tls_dict(session, tid): """ A quick and dirty function to grab all of the tls config for use in subprocesses """ node = ConfigFactory(session, tid) return { 'ssl_key': node.get_val(u'https_priv_key'), 'ssl_cert': node.get_val(u'https_cert'), 'ssl_intermediate': node.get_val(u'https_chain'), 'ssl_dh': node.get_val(u'https_dh_params'), 'https_enabled': node.get_val(u'https_enabled'), 'hostname': node.get_val(u'hostname'), }
def get_l10n(session, tid, lang): if tid != 1: config = ConfigFactory(session, 1) if config.get_val(u'mode') == u'whistleblowing.it': tid = 1 path = langfile_path(lang) directory_traversal_check(Settings.client_path, path) if not os.path.exists(path): raise errors.ResourceNotFound() texts = read_json_file(path) custom_texts = session.query(models.CustomTexts).filter(models.CustomTexts.lang == lang, models.CustomTexts.tid == tid).one_or_none() custom_texts = custom_texts.texts if custom_texts is not None else {} texts.update(custom_texts) return texts
def evaluate_update_notification(session, state, latest_version): priv_fact = ConfigFactory(session, 1) stored_latest = priv_fact.get_val(u'latest_version') if V(stored_latest) < V(latest_version): priv_fact.set_val(u'latest_version', latest_version) if V(__version__) == V(latest_version): return for user_desc in db_get_admin_users(session, 1): lang = user_desc['language'] template_vars = { 'type': 'software_update_available', 'latest_version': latest_version, 'node': db_admin_serialize_node(session, 1, lang), 'notification': db_get_notification(session, 1, lang), 'user': user_desc, } state.format_and_send_mail(session, 1, user_desc, template_vars)
def perform_data_update(db_file): session = get_session(make_db_uri(db_file), foreign_keys=False) enabled_languages = [lang.name for lang in session.query(models.EnabledLanguage)] removed_languages = list(set(enabled_languages) - set(LANGUAGES_SUPPORTED_CODES)) if removed_languages: removed_languages.sort() removed_languages = ', '.join(removed_languages) raise Exception("FATAL: cannot complete the upgrade because the support for some of the enabled languages is currently incomplete (%s)\n" "Read about how to handle this condition at: https://github.com/globaleaks/GlobaLeaks/wiki/Upgrade-Guide#lang-drop" % removed_languages) try: cfg = ConfigFactory(session, 1) stored_ver = cfg.get_val(u'version') if stored_ver != __version__: # The below commands can change the current store based on the what is # currently stored in the DB. for tid in [t[0] for t in session.query(models.Tenant.id)]: appdata = load_appdata() config.update_defaults(session, tid, appdata) db_update_defaults(session) db_fix(session) cfg.set_val(u'version', __version__) cfg.set_val(u'latest_version', __version__) cfg.set_val(u'version_db', DATABASE_VERSION) session.commit() except: session.rollback() raise finally: session.close()
def can_perform_acme_run(session, tid): config = ConfigFactory(session, tid) acme = config.get_val(u'acme') no_cert_set = config.get_val(u'https_cert') == u'' return acme and no_cert_set
def is_acme_configured(session, tid): config = ConfigFactory(session, tid) acme = config.get_val(u'acme') cert_set = config.get_val(u'https_cert') != u'' return acme and cert_set
def can_perform_acme_renewal(session, tid): priv_fact = ConfigFactory(session, tid) a = is_acme_configured(session, tid) b = priv_fact.get_val(u'https_enabled') c = priv_fact.get_val(u'https_cert') return a and b and c
def db_get_onion_service_info(session, tid): node = ConfigFactory(session, tid) hostname = node.get_val(u'onionservice') key = node.get_val(u'tor_onion_key') return tid, hostname, key