def signup_activation(session, state, tid, token, language): node = config.ConfigFactory(session, 1, 'node') if not node.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 = node.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, state, 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 __init__(self, tokenlist, tid, type='submission'): self.tokenlist = tokenlist self.tid = tid self.id = generateRandomKey(42) self.type = type self.creation_date = datetime.utcnow() self.uploaded_files = [] self.solved = False self.question = generateRandomKey(20)
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_generate_password_reset_token(session, user): """ Transaction for issuing password reset tokens :param session: An ORM session :param user: The user for which issuing a password reset token """ user.reset_password_token = generateRandomKey() user.reset_password_date = datetime_now() if user.last_login > datetime_null(): template = 'password_reset_validation' else: template = 'account_activation' user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': template, 'user': user_desc, 'reset_token': user.reset_password_token, 'node': db_admin_serialize_node(session, user.tid, user.language), 'notification': db_get_notification(session, user.tid, user.language) } State.format_and_send_mail(session, user.tid, user_desc, template_vars)
def db_generate_password_reset_token(session, state, tid, username_or_email, allow_admin_reset=False): from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node from globaleaks.handlers.user import user_serialize_user users = session.query(models.User).filter( or_(models.User.username == username_or_email, models.User.mail_address == username_or_email), models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == tid).distinct() for user in users: if not allow_admin_reset and user.role == u'admin': continue user.reset_password_token = generateRandomKey(32) user.reset_password_date = datetime_now() user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'password_reset_validation', 'user': user_desc, 'reset_token': user.reset_password_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } state.format_and_send_mail(session, tid, user_desc, template_vars)
def get_dummy_file(content=None): filename = generateRandomKey() content_type = 'application/octet' if content is None: content = base64.b64decode(VALID_BASE64_IMG) temporary_file = SecureTemporaryFile(Settings.tmp_path) with temporary_file.open('w') as f: f.write(content) f.finalize_write() State.TempUploadFiles[os.path.basename( temporary_file.filepath)] = temporary_file return { 'id': filename, 'date': datetime_now(), 'name': filename, 'description': 'description', 'body': temporary_file, 'size': len(content), 'filename': os.path.basename(temporary_file.filepath), 'type': content_type, 'submission': False }
def generate_password_reset_token(session, state, tid, username_or_email, allow_admin_reset=False): from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node from globaleaks.handlers.user import user_serialize_user users = session.query(models.User).filter( or_(models.User.username == username_or_email, models.User.mail_address == username_or_email), models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == tid ).distinct() for user in users: if not allow_admin_reset and user.role == u'admin': continue user.reset_password_token = generateRandomKey(32) user.reset_password_date = datetime_now() user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'password_reset_validation', 'user': user_desc, 'reset_token': user.reset_password_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } state.format_and_send_mail(session, tid, user_desc, template_vars)
def generate_password_reset_token(session, state, tid, username_or_email): from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node from globaleaks.handlers.user import user_serialize_user users = session.query(models.User).filter( or_(models.User.username == username_or_email, models.User.mail_address == username_or_email), models.User.tid == tid).distinct() for user in users: user.reset_password_token = generateRandomKey(32) user.reset_password_date = datetime_now() user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'password_reset_validation', 'user': user_desc, 'reset_token': user.reset_password_token, 'node': db_admin_serialize_node(session, tid, user.language), 'notification': db_get_notification(session, tid, user.language) } state.format_and_send_mail(session, tid, user_desc, template_vars) return {'redirect': '/login/passwordreset/requested'}
def __init__(self, tokenlist, tid): self.tokenlist = tokenlist self.tid = tid self.id = generateRandomKey() self.creation_date = datetime_now() self.uploaded_files = [] self.solved = False
def __init__(self, tid, user_id, user_role, pcn, cc): self.id = generateRandomKey(42) self.tid = tid self.user_id = user_id self.user_role = user_role self.pcn = pcn self.cc = cc self.expireCall = None
def __init__(self, tid, user_id, user_role, pcn, cc): self.id = generateRandomKey(42) self.tid = tid self.user_id = user_id self.user_role = user_role self.pcn = pcn self.cc = cc self.expireCall = None
def db_user_update_user(session, tid, user_session, request): """ Transaction for updating an existing user :param session: An ORM session :param tid: A tenant ID :param user_session: A session of the user invoking the transaction :param request: A user request data :return: A user model """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] user.public_name = request['public_name'] if request[ 'public_name'] else request['name'] if request['password']: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, request['old_password'], user.salt, user.password): raise errors.InvalidOldPassword user_session.cc = set_user_password(tid, user, request['password'], user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey() user_desc = user_serialize_user(session, user, user.language) user_desc['mail_address'] = request['mail_address'] template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, tid, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) parse_pgp_options(user, request) return user
def process_receiverfiles(state, files_maps): """ Function that process uploaded receiverfiles :param state: A reference to the application state :param files_maps: descriptos of whistleblower files to be processed """ for _, receiverfiles_map in files_maps.items(): key = receiverfiles_map['crypto_tip_pub_key'] filename = receiverfiles_map['filename'] filecode = filename.split('.')[0] plaintext_name = "%s.plain" % filecode encrypted_name = "%s.encrypted" % filecode plaintext_path = os.path.abspath( os.path.join(Settings.attachments_path, plaintext_name)) encrypted_path = os.path.abspath( os.path.join(Settings.attachments_path, encrypted_name)) receiverfiles_map[ 'filename'] = encrypted_name if key else plaintext_name sf = state.get_tmp_file_by_name(filename) for rcounter, rf in enumerate(receiverfiles_map['rfiles']): if key: rf['filename'] = encrypted_name else: rf['filename'] = plaintext_path try: with sf.open('rb') as encrypted_file: if not rf['receiver']['pgp_key_public']: receiverfiles_map[ 'pgp_encrypted_for_everybody'] = False continue pgp_name = "%s.pgp" % generateRandomKey() pgp_path = os.path.abspath( os.path.join(Settings.attachments_path, pgp_name)) encrypt_file_with_pgp( state, encrypted_file, rf['receiver']['pgp_key_public'], rf['receiver']['pgp_key_fingerprint'], pgp_path) rf['filename'] = pgp_name rf['status'] = 'encrypted' except Exception as excep: log.err( "%d# Unable to complete PGP encrypt for %s on %s: %s. marking the file as unavailable.", rcounter, rf['receiver']['name'], rf['filename'], excep) rf['status'] = 'unavailable' if not receiverfiles_map['pgp_encrypted_for_everybody']: if key: write_encrypted_file(key, sf, encrypted_path) else: write_plaintext_file(sf, plaintext_path)
def process_receiverfiles(state, receiverfiles_maps): """ @param receiverfiles_maps: the mapping of ifile/rfiles to be created on filesystem @return: return None """ for id, receiverfiles_map in receiverfiles_maps.items(): key = receiverfiles_map['crypto_tip_pub_key'] filename = receiverfiles_map['filename'] filecode = filename.split('.')[0] plaintext_name = "%s.plain" % filecode encrypted_name = "%s.encrypted" % filecode plaintext_path = os.path.abspath( os.path.join(Settings.attachments_path, plaintext_name)) encrypted_path = os.path.abspath( os.path.join(Settings.attachments_path, encrypted_name)) sf = state.get_tmp_file_by_name(filename) if key: receiverfiles_map['filename'] = encrypted_name write_encrypted_file(key, sf, encrypted_path) for rf in receiverfiles_map['rfiles']: rf['filename'] = encrypted_name else: for rcounter, rfileinfo in enumerate(receiverfiles_map['rfiles']): with sf.open('rb') as encrypted_file: if rfileinfo['receiver']['pgp_key_public']: try: pgp_name = "pgp_encrypted-%s" % generateRandomKey( 16) pgp_path = os.path.abspath( os.path.join(Settings.attachments_path, pgp_name)) encrypt_file_with_pgp( state, encrypted_file, rfileinfo['receiver']['pgp_key_public'], rfileinfo['receiver']['pgp_key_fingerprint'], pgp_path) rfileinfo['filename'] = pgp_name rfileinfo['status'] = u'encrypted' except Exception as excep: log.err( "%d# Unable to complete PGP encrypt for %s on %s: %s. marking the file as unavailable.", rcounter, rfileinfo['receiver']['name'], rfileinfo['filename'], excep) rfileinfo['status'] = u'unavailable' elif state.tenant_cache[ receiverfiles_map['tid']].allow_unencrypted: receiverfiles_map['plaintext_file_needed'] = True rfileinfo['filename'] = plaintext_name rfileinfo['status'] = u'reference' else: rfileinfo['status'] = u'nokey' if receiverfiles_map['plaintext_file_needed']: write_plaintext_file(sf, plaintext_path)
def __init__(self, tid, user_id, user_tid, user_role, pcn, two_factor, cc, ek): self.id = generateRandomKey(42) self.tid = tid self.user_id = user_id self.user_tid = user_tid self.user_role = user_role self.pcn = pcn self.two_factor = two_factor self.cc = cc self.ek = ek self.expireCall = None
def signup(session, state, tid, request, language): node = config.ConfigFactory(session, 1, 'node') if not node.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 __init__(self, filesdir): """ Create the AES Key to encrypt the uploaded file and initialize the cipher """ self.key = os.urandom(32) self.key_id = generateRandomKey(16) self.key_counter_nonce = os.urandom(16) self.cipher = Cipher(algorithms.AES(self.key), modes.CTR(self.key_counter_nonce), backend=crypto_backend) self.filepath = os.path.join(filesdir, "%s.aes" % self.key_id) self.enc = self.cipher.encryptor() self.dec = None
def process_receiverfiles(state, receiverfiles_maps): """ @param receiverfiles_maps: the mapping of ifile/rfiles to be created on filesystem @return: return None """ for id, receiverfiles_map in receiverfiles_maps.items(): key = receiverfiles_map['crypto_tip_pub_key'] filename = receiverfiles_map['filename'] filecode = filename.split('.')[0] plaintext_name = "%s.plain" % filecode encrypted_name = "%s.encrypted" % filecode plaintext_path = os.path.abspath(os.path.join(Settings.attachments_path, plaintext_name)) encrypted_path = os.path.abspath(os.path.join(Settings.attachments_path, encrypted_name)) sf = state.get_tmp_file_by_name(filename) if key: receiverfiles_map['filename'] = encrypted_name write_encrypted_file(key, sf, encrypted_path) for rf in receiverfiles_map['rfiles']: rf['filename'] = encrypted_name else: for rcounter, rfileinfo in enumerate(receiverfiles_map['rfiles']): with sf.open('rb') as encrypted_file: if rfileinfo['receiver']['pgp_key_public']: try: pgp_name = "pgp_encrypted-%s" % generateRandomKey(16) pgp_path = os.path.abspath(os.path.join(Settings.attachments_path, pgp_name)) encrypt_file_with_pgp(state, encrypted_file, rfileinfo['receiver']['pgp_key_public'], rfileinfo['receiver']['pgp_key_fingerprint'], pgp_path) rfileinfo['filename'] = pgp_name rfileinfo['status'] = u'encrypted' except Exception as excep: log.err("%d# Unable to complete PGP encrypt for %s on %s: %s. marking the file as unavailable.", rcounter, rfileinfo['receiver']['name'], rfileinfo['filename'], excep) rfileinfo['status'] = u'unavailable' elif state.tenant_cache[receiverfiles_map['tid']].allow_unencrypted: receiverfiles_map['plaintext_file_needed'] = True rfileinfo['filename'] = plaintext_name rfileinfo['status'] = u'reference' else: rfileinfo['status'] = u'nokey' if receiverfiles_map['plaintext_file_needed']: write_plaintext_file(sf, plaintext_path)
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 regenerate(self, session_id): session = self.pop(session_id) session.id = generateRandomKey() self[session.id] = session return session
def db_user_update_user(session, state, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(new_password, user.salt) user.password_change_date = datetime_now() if State.tenant_cache[1].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_prv_key = GCE.symmetric_encrypt( enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } state.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(state, user, request) return user
def regenerate(self, session_id): session = self.pop(session_id) session.id = generateRandomKey(42) self.set(session.id, session) return session
def signup(session, request, language): """ Transact handling the registration of a new signup :param session: An ORM session :param request: A user request :param language: A language of the request """ config = ConfigFactory(session, 1) if not config.get_val('enable_signup'): raise errors.ForbiddenOperation request['activation_token'] = generateRandomKey(32) request['language'] = language # Delete the tenants created for the same subdomain that have still not been activated # Ticket reference: https://github.com/globaleaks/GlobaLeaks/issues/2640 subquery = session.query(models.Tenant.id) \ .filter(models.Signup.subdomain == request['subdomain'], not_(models.Signup.activation_token.is_(None)), models.Tenant.id == models.Signup.tid, models.Tenant.subdomain == models.Signup.subdomain) \ .subquery() session.query(models.Tenant).filter( models.Tenant.id.in_(subquery)).delete(synchronize_session=False) 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_users(session, 1, 'admin'): 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 signup_activation(session, token, hostname, language): """ Transaction registering the activation of a platform registered via signup :param session: An ORM session :param token: A activation token :param language: A language of the request """ config = ConfigFactory(session, 1) if not config.get_val('enable_signup'): raise errors.ForbiddenOperation ret = session.query(models.Signup, models.Tenant) \ .filter(models.Signup.activation_token == token, models.Tenant.id == models.Signup.tid).one_or_none() if ret is None: return {} signup, tenant = ret[0], ret[1] signup.activation_token = None mode = config.get_val('mode') db_initialize_tenant(session, tenant, mode) password_admin = generateRandomKey(16) password_receiver = generateRandomKey(16) node_name = signup.organization_name if signup.organization_name else signup.subdomain wizard = { 'node_language': signup.language, 'node_name': node_name, 'admin_username': '******', 'admin_name': signup.name + ' ' + signup.surname, 'admin_password': password_admin, 'admin_mail_address': signup.email, 'receiver_username': '******', 'receiver_name': signup.name + ' ' + signup.surname, 'receiver_password': password_receiver, 'receiver_mail_address': signup.email, 'profile': 'default', 'skip_recipient_account_creation': False, 'enable_developers_exception_notification': True } db_wizard(session, signup.tid, hostname, wizard) 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': wizard['admin_password'], 'password_recipient': wizard['receiver_password'] } State.format_and_send_mail(session, 1, {'mail_address': signup.email}, template_vars) db_refresh_memory_variables(session, [signup.tid])
def get_random_password(): return text_type(generateRandomKey(16))
def db_user_update_user(session, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword # Regenerate the password hash only if different from the best choice on the platform if user.hash_alg != GCE.HASH: user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() password_hash = GCE.hash_password(new_password, user.salt) # Check that the new password is different form the current password if user.password == password_hash: raise errors.PasswordReuseError user.password = password_hash user.password_change_date = datetime_now() if State.tenant_cache[tid].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: # Th First first password change triggers the generation # of the user encryption private key and its backup user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_bkp_key, user.crypto_rec_key = GCE.generate_recovery_key( user_session.cc) # If the user had already enabled two factor before encryption was not enable # encrypt the two factor secret if user.two_factor_secret: user.two_factor_secret = GCE.asymmetric_encrypt( user.crypto_pub_key, user.two_factor_secret) user.crypto_prv_key = GCE.symmetric_encrypt( enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) user_desc['mail_address'] = request['mail_address'] template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, tid, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(user, request) return user
def db_user_update_user(session, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(new_password, user.salt) user.password_change_date = datetime_now() if State.tenant_cache[1].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_prv_key = GCE.symmetric_encrypt(enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(user, request) return user
def file_delivery(session): """ This function roll over the InternalFile uploaded, extract a path, id and receivers associated, one entry for each combination. representing the ReceiverFile that need to be created. """ receiverfiles_maps = {} whistleblowerfiles_maps = {} for ifile, itip in session.query(models.InternalFile, models.InternalTip) \ .filter(models.InternalFile.new.is_(True), models.InternalTip.id == models.InternalFile.internaltip_id) \ .order_by(models.InternalFile.creation_date) \ .limit(20): ifile.new = False src = ifile.filename filecode = src.split('.')[0] if itip.crypto_tip_pub_key: itip.filename = "%s.encrypted" % filecode else: itip.filename = "%s.plain" % filecode for rtip, user in session.query(models.ReceiverTip, models.User) \ .filter(models.ReceiverTip.internaltip_id == ifile.internaltip_id, models.User.id == models.ReceiverTip.receiver_id): receiverfile = models.ReceiverFile() receiverfile.internalfile_id = ifile.id receiverfile.receivertip_id = rtip.id # https://github.com/globaleaks/GlobaLeaks/issues/444 # avoid to mark the receiverfile as new if it is part of a submission # this way we avoid to send unuseful messages receiverfile.new = not ifile.submission session.add(receiverfile) if ifile.id not in receiverfiles_maps: receiverfiles_maps[ifile.id] = { 'src': src, 'key': itip.crypto_tip_pub_key, 'rfiles': [] } if user.pgp_key_public: receiverfile.filename = "%s.pgp" % generateRandomKey() receiverfile.status = 'encrypted' else: receiverfile.filename = itip.filename receiverfile.status = 'reference' receiverfiles_maps[ifile.id]['rfiles'].append({ 'dst': os.path.abspath(os.path.join(Settings.attachments_path, receiverfile.filename)), 'pgp_key_public': user.pgp_key_public, 'pgp_key_fingerprint': user.pgp_key_fingerprint }) for wbfile, itip in session.query(models.WhistleblowerFile, models.InternalTip)\ .filter(models.WhistleblowerFile.new.is_(True), models.ReceiverTip.id == models.WhistleblowerFile.receivertip_id, models.InternalTip.id == models.ReceiverTip.internaltip_id) \ .order_by(models.WhistleblowerFile.creation_date) \ .limit(20): wbfile.new = False src = wbfile.filename filecode = src.split('.')[0] if itip.crypto_tip_pub_key: wbfile.filename = "%s.encrypted" % filecode else: wbfile.filename = "%s.plain" % filecode whistleblowerfiles_maps[wbfile.id] = { 'key': itip.crypto_tip_pub_key, 'src': src, 'dst': os.path.abspath(os.path.join(Settings.attachments_path, wbfile.filename)), } return receiverfiles_maps, whistleblowerfiles_maps
def regenerate(self, session_id): session = self.pop(session_id) session.id = generateRandomKey(42) self.set(session.id, session) return session