def check_auth(self, rpsl_obj_new: RPSLObject, rpsl_obj_current: Optional[RPSLObject]) -> ValidatorResult: """ Check whether authentication passes for all required objects. """ source = rpsl_obj_new.source() result = ValidatorResult() mntners_new = rpsl_obj_new.parsed_data['mnt-by'] logger.debug( f'Checking auth for {rpsl_obj_new}, mntners in new object: {mntners_new}' ) if not self._check_mntners(mntners_new, source): self._generate_failure_message(result, mntners_new, rpsl_obj_new) if rpsl_obj_current: mntners_current = rpsl_obj_current.parsed_data['mnt-by'] logger.debug( f'Checking auth for {rpsl_obj_current}, mntners in new object: {mntners_current}' ) if not self._check_mntners(mntners_current, source): self._generate_failure_message(result, mntners_current, rpsl_obj_new) if isinstance(rpsl_obj_new, RPSLMntner): # Dummy auth values are only permitted in existing objects, which are never pre-approved. if rpsl_obj_new.has_dummy_auth_value() and rpsl_obj_new.pk( ) not in self._pre_approved: if len(self.passwords) == 1: logger.debug( f'Object {rpsl_obj_new} submitted with dummy hash values and single password, ' f'replacing all hashes with currently supplied password.' ) rpsl_obj_new.force_single_new_password(self.passwords[0]) result.info_messages.add( 'As you submitted dummy hash values, all password hashes on this object ' 'were replaced with a new MD5-PW hash of the password you provided for ' 'authentication.') else: result.error_messages.add( f'Object submitted with dummy hash values, but multiple or no passwords ' f'submitted. Either submit all full hashes, or a single password.' ) elif not rpsl_obj_new.verify_auth(self.passwords, self.keycert_obj_pk): result.error_messages.add( f'Authorisation failed for the auth methods on this mntner object.' ) return result
def process_auth(self, rpsl_obj_new: RPSLObject, rpsl_obj_current: Optional[RPSLObject]) -> ValidatorResult: """ Check whether authentication passes for all required objects. Returns a ValidatorResult object with error/info messages, and fills result.mntners_notify with the RPSLMntner objects that may have to be notified. If a valid override password is provided, changes are immediately approved. On the result object, used_override is set to True, but mntners_notify is not filled, as mntner resolving does not take place. """ source = rpsl_obj_new.source() result = ValidatorResult() override_hash = get_setting('auth.override_password') if override_hash: for override in self.overrides: try: if md5_crypt.verify(override, override_hash): result.used_override = True logger.debug(f'Found valid override password.') return result else: logger.info(f'Found invalid override password, ignoring.') except ValueError as ve: logger.error(f'Exception occurred while checking override password: {ve} (possible misconfigured hash?)') elif self.overrides: logger.info(f'Ignoring override password, auth.override_password not set.') mntners_new = rpsl_obj_new.parsed_data['mnt-by'] logger.debug(f'Checking auth for new object {rpsl_obj_new}, mntners in new object: {mntners_new}') valid, mntner_objs_new = self._check_mntners(mntners_new, source) if not valid: self._generate_failure_message(result, mntners_new, rpsl_obj_new) if rpsl_obj_current: mntners_current = rpsl_obj_current.parsed_data['mnt-by'] logger.debug(f'Checking auth for current object {rpsl_obj_current}, ' f'mntners in new object: {mntners_current}') valid, mntner_objs_current = self._check_mntners(mntners_current, source) if not valid: self._generate_failure_message(result, mntners_current, rpsl_obj_new) result.mntners_notify = mntner_objs_current else: result.mntners_notify = mntner_objs_new if isinstance(rpsl_obj_new, RPSLMntner): if not rpsl_obj_current: result.error_messages.add('New mntner objects must be added by an administrator.') return result # Dummy auth values are only permitted in existing objects if rpsl_obj_new.has_dummy_auth_value(): if len(self.passwords) == 1: logger.debug(f'Object {rpsl_obj_new} submitted with dummy hash values and single password, ' f'replacing all hashes with currently supplied password.') rpsl_obj_new.force_single_new_password(self.passwords[0]) result.info_messages.add('As you submitted dummy hash values, all password hashes on this object ' 'were replaced with a new MD5-PW hash of the password you provided for ' 'authentication.') else: result.error_messages.add(f'Object submitted with dummy hash values, but multiple or no passwords ' f'submitted. Either submit only full hashes, or a single password.') elif not rpsl_obj_new.verify_auth(self.passwords, self.keycert_obj_pk): result.error_messages.add(f'Authorisation failed for the auth methods on this mntner object.') return result
def process_auth( self, rpsl_obj_new: RPSLObject, rpsl_obj_current: Optional[RPSLObject]) -> ValidatorResult: """ Check whether authentication passes for all required objects. Returns a ValidatorResult object with error/info messages, and fills result.mntners_notify with the RPSLMntner objects that may have to be notified. If a valid override password is provided, changes are immediately approved. On the result object, used_override is set to True, but mntners_notify is not filled, as mntner resolving does not take place. """ source = rpsl_obj_new.source() result = ValidatorResult() if self.check_override(): result.used_override = True logger.debug('Found valid override password.') return result mntners_new = rpsl_obj_new.parsed_data['mnt-by'] logger.debug( f'Checking auth for new object {rpsl_obj_new}, mntners in new object: {mntners_new}' ) valid, mntner_objs_new = self._check_mntners(mntners_new, source) if not valid: self._generate_failure_message(result, mntners_new, rpsl_obj_new) if rpsl_obj_current: mntners_current = rpsl_obj_current.parsed_data['mnt-by'] logger.debug( f'Checking auth for current object {rpsl_obj_current}, ' f'mntners in new object: {mntners_current}') valid, mntner_objs_current = self._check_mntners( mntners_current, source) if not valid: self._generate_failure_message(result, mntners_current, rpsl_obj_new) result.mntners_notify = mntner_objs_current else: result.mntners_notify = mntner_objs_new mntners_related = self._find_related_mntners(rpsl_obj_new, result) if mntners_related: related_object_class, related_pk, related_mntner_list = mntners_related logger.debug( f'Checking auth for related object {related_object_class} / ' f'{related_pk} with mntners {related_mntner_list}') valid, mntner_objs_related = self._check_mntners( related_mntner_list, source) if not valid: self._generate_failure_message(result, related_mntner_list, rpsl_obj_new, related_object_class, related_pk) result.mntners_notify = mntner_objs_related if isinstance(rpsl_obj_new, RPSLMntner): if not rpsl_obj_current: result.error_messages.add( 'New mntner objects must be added by an administrator.') return result # Dummy auth values are only permitted in existing objects if rpsl_obj_new.has_dummy_auth_value(): if len(self.passwords) == 1: logger.debug( f'Object {rpsl_obj_new} submitted with dummy hash values and single password, ' f'replacing all hashes with currently supplied password.' ) rpsl_obj_new.force_single_new_password(self.passwords[0]) result.info_messages.add( 'As you submitted dummy hash values, all password hashes on this object ' 'were replaced with a new BCRYPT-PW hash of the password you provided for ' 'authentication.') else: result.error_messages.add( 'Object submitted with dummy hash values, but multiple or no passwords ' 'submitted. Either submit only full hashes, or a single password.' ) elif not rpsl_obj_new.verify_auth(self.passwords, self.keycert_obj_pk): result.error_messages.add( 'Authorisation failed for the auth methods on this mntner object.' ) return result