def check(fn, self, *a, **kw): is_api = util.is_api() request = cherrypy.request if not handle_api and is_api: raise RequestRefused(404) if handle_api is ONLY_API and not is_api: raise RequestRefused(404) _methods = methods if _methods: if isinstance(_methods, basestring): _methods = [ _methods ] if request.method not in _methods: raise RequestRefused(405) # verify that version info is good; do it here so that any URI access # will trigger the check startup.initVersionInfo() # add a convenience property to all request objects to get at the # current relative URI request.relative_uri = request.path_info + (('?' + request.query_string) if request.query_string else '') if cherrypy.config.get('root_endpoint') not in ['/', None, '']: request.relative_uri = cherrypy.config.get('root_endpoint') + request.relative_uri # CSRF protection # Disable in tests by setting cherrypy.config.update({'environment': 'test_suite'}) if verify_session and request.method == 'POST' and not cherrypy.config.get('environment') == 'test_suite': is_xhr = util.is_xhr() form_key = request.headers.get('X-Splunk-Form-Key') if is_xhr else request.params.get('splunk_form_key') # verify that the incoming form key matches server's version if not util.isValidFormKey(form_key): if is_xhr: logger.warn('CSRF: validation failed because client XHR did not include proper header') else: logger.warn('CSRF: validation failed because HTTP POST did not include expected parameter') if must_login: if is_xhr: raise cherrypy.HTTPError(401, _('Splunk cannot authenticate the request. CSRF validation failed.')) else: return self.redirect_to_url('/account/login', _qs=[ ('return_to', util.current_url_path()) ] ) logger.warn('CSRF: skipping 401 redirect response because endpoint did not request protection') # basic input cleansing if trim_spaces: for key, value in kw.iteritems(): if isinstance(value, basestring): kw[key] = value.strip() if kw[key] != value: logger.debug('Leading/trailing whitespaces were trimmed in "%s" argument' % key) return fn(self, *a, **kw)
def passwordchange(self, newpassword=None, confirmpassword=None, return_to=None, **kw): ''' Suggest admin to change the password on first time run ''' # We set must_login to False in the expose_page decoator so we can perform the checks here instead # and give the user a more useful message if the session has expired leaving the password unchanged if not cherrypy.session.get('sessionKey', None) or not util.isValidFormKey(kw['splunk_form_key']): # The user intended to change the password; reset the flag so this page will be shown again cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs(return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) err = None templateArgs = { 'err' : err, 'return_to' : return_to, 'cpSessionKey' : cherrypy.session.id } if newpassword != confirmpassword: templateArgs['err'] = _("Passwords didn't match, please try again.") return self.render_template('account/passwordchange.html', templateArgs) if newpassword == 'changeme': templateArgs['err'] = _("For security reasons, the new password must be different from the default one.") return self.render_template('account/passwordchange.html', templateArgs) try: user = User.get('admin') user.password = newpassword if not user.save(): logger.error('Unable to save new admin password.') except splunk.AuthenticationFailed: cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs(return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) except splunk.RESTException, e: err = e.get_message_text() if ':' in err: err = err[err.find(':')+2:] logger.error("Failed to change the password: %s." % err) templateArgs['err'] = err return self.render_template('account/passwordchange.html', templateArgs)
def passwordchange(self, newpassword=None, confirmpassword=None, return_to=None, cval=None, **kw): ''' Suggest admin to change the password on first time run And force flagged users to change their passwords before they continue ''' # We set must_login to False in the expose_page decoator so we can perform the checks here instead # and give the user a more useful message if the session has expired leaving the password unchanged # but first we check if the passwords pass err = None templateArgs = { 'err' : err, 'return_to' : return_to, 'cpSessionKey' : cherrypy.session.id } if 'fpc' in cherrypy.session: templateArgs['fpc'] = True if not newpassword or len(newpassword) == 0: templateArgs['err'] = _("Empty passwords are not allowed.") return self.render_template('account/passwordchange.html', templateArgs) if newpassword != confirmpassword: templateArgs['err'] = _("Passwords didn't match, please try again.") return self.render_template('account/passwordchange.html', templateArgs) if newpassword == 'changeme': templateArgs['err'] = _("For security reasons, the new password must be different from the default one.") return self.render_template('account/passwordchange.html', templateArgs) # Forced Password Change workflow is checked before the session check b/c user isn't authenticated yet if 'fpc' in cherrypy.session: try: # Fetch the user's verified cached credentials from when they originally attempted to login with AccountController.credential_lock: # Will raise a KeyError if the credentials have expired from the LRU or CP was restarted credentials = AccountController.credential_cache[cherrypy.session.id] if newpassword == credentials['password']: templateArgs['err'] = _("For security reasons, the new password must be different from the previous one.") return self.render_template('account/passwordchange.html', templateArgs) # Will be resetup, if required, by self.login() del cherrypy.session['fpc'] with AccountController.credential_lock: try: del AccountController.credential_cache[cherrypy.session.id] except KeyError: pass # Fake a login form submission; this call must return as soon as the call to login() completes! return self.login(username=credentials['username'], password=credentials['password'], newpassword=newpassword, return_to=return_to, cval=cherrypy.session['cval']) except (splunk.AuthenticationFailed, KeyError): cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs(return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) if not cherrypy.session.get('sessionKey', None) or not util.isValidFormKey(kw['splunk_form_key']): # The user intended to change the password; reset the flag so this page will be shown again cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs(return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) try: user = User.get(cherrypy.session['user']['name']) user.password = newpassword if not user.save(): logger.error('Unable to save new admin password.') except splunk.AuthenticationFailed: cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs(return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) except splunk.RESTException, e: err = e.get_message_text() if ':' in err: err = err[err.find(':')+2:] logger.error("Failed to change the password: %s." % err) templateArgs['err'] = err return self.render_template('account/passwordchange.html', templateArgs)
def passwordchange(self, newpassword=None, confirmpassword=None, return_to=None, **kw): ''' Suggest admin to change the password on first time run ''' # We set must_login to False in the expose_page decoator so we can perform the checks here instead # and give the user a more useful message if the session has expired leaving the password unchanged if not cherrypy.session.get('sessionKey', None) or not util.isValidFormKey( kw['splunk_form_key']): # The user intended to change the password; reset the flag so this page will be shown again cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs( return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) err = None templateArgs = { 'err': err, 'return_to': return_to, 'cpSessionKey': cherrypy.session.id } if newpassword != confirmpassword: templateArgs['err'] = _( "Passwords didn't match, please try again.") return self.render_template('account/passwordchange.html', templateArgs) if newpassword == 'changeme': templateArgs['err'] = _( "For security reasons, the new password must be different from the default one." ) return self.render_template('account/passwordchange.html', templateArgs) try: user = User.get('admin') user.password = newpassword if not user.save(): logger.error('Unable to save new admin password.') except splunk.AuthenticationFailed: cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs( return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) except splunk.RESTException, e: err = e.get_message_text() if ':' in err: err = err[err.find(':') + 2:] logger.error("Failed to change the password: %s." % err) templateArgs['err'] = err return self.render_template('account/passwordchange.html', templateArgs)
def check(fn, self, *a, **kw): is_api = util.is_api() request = cherrypy.request if not handle_api and is_api: raise RequestRefused(404) if handle_api is ONLY_API and not is_api: raise RequestRefused(404) _methods = methods if _methods: if isinstance(_methods, basestring): _methods = [_methods] if request.method not in _methods: raise RequestRefused(405) # verify that version info is good; do it here so that any URI access # will trigger the check startup.initVersionInfo() # add a convenience property to all request objects to get at the # current relative URI request.relative_uri = request.path_info + ( ('?' + request.query_string) if request.query_string else '') if cherrypy.config.get('root_endpoint') not in ['/', None, '']: request.relative_uri = cherrypy.config.get( 'root_endpoint') + request.relative_uri # CSRF protection # Disable in tests by setting cherrypy.config.update({'environment': 'test_suite'}) if verify_session and request.method == 'POST' and not cherrypy.config.get( 'environment') == 'test_suite': is_xhr = util.is_xhr() form_key = request.headers.get( 'X-Splunk-Form-Key') if is_xhr else request.params.get( 'splunk_form_key') # verify that the incoming form key matches server's version if not util.isValidFormKey(form_key): if is_xhr: logger.warn( 'CSRF: validation failed because client XHR did not include proper header' ) else: logger.warn( 'CSRF: validation failed because HTTP POST did not include expected parameter' ) if must_login: if is_xhr: raise cherrypy.HTTPError( 401, _('Splunk cannot authenticate the request. CSRF validation failed.' )) else: return self.redirect_to_url( '/account/login', _qs=[('return_to', util.current_url_path())]) logger.warn( 'CSRF: skipping 401 redirect response because endpoint did not request protection' ) # basic input cleansing if trim_spaces: for key, value in kw.iteritems(): if isinstance(value, basestring): kw[key] = value.strip() if kw[key] != value: logger.debug( 'Leading/trailing whitespaces were trimmed in "%s" argument' % key) return fn(self, *a, **kw)
def passwordchange(self, newpassword=None, confirmpassword=None, return_to=None, cval=None, **kw): ''' Suggest admin to change the password on first time run And force flagged users to change their passwords before they continue ''' # We set must_login to False in the expose_page decoator so we can perform the checks here instead # and give the user a more useful message if the session has expired leaving the password unchanged # but first we check if the passwords pass err = None templateArgs = { 'err': err, 'return_to': return_to, 'cpSessionKey': cherrypy.session.id } if 'fpc' in cherrypy.session: templateArgs['fpc'] = True if not newpassword or len(newpassword) == 0: templateArgs['err'] = _("Empty passwords are not allowed.") return self.render_template('account/passwordchange.html', templateArgs) if newpassword != confirmpassword: templateArgs['err'] = _( "Passwords didn't match, please try again.") return self.render_template('account/passwordchange.html', templateArgs) if newpassword == 'changeme': templateArgs['err'] = _( "For security reasons, the new password must be different from the default one." ) return self.render_template('account/passwordchange.html', templateArgs) # Forced Password Change workflow is checked before the session check b/c user isn't authenticated yet if 'fpc' in cherrypy.session: try: # Fetch the user's verified cached credentials from when they originally attempted to login with AccountController.credential_lock: # Will raise a KeyError if the credentials have expired from the LRU or CP was restarted credentials = AccountController.credential_cache[ cherrypy.session.id] if newpassword == credentials['password']: templateArgs['err'] = _( "For security reasons, the new password must be different from the previous one." ) return self.render_template('account/passwordchange.html', templateArgs) # Will be resetup, if required, by self.login() del cherrypy.session['fpc'] with AccountController.credential_lock: try: del AccountController.credential_cache[ cherrypy.session.id] except KeyError: pass # Fake a login form submission; this call must return as soon as the call to login() completes! return self.login(username=credentials['username'], password=credentials['password'], newpassword=newpassword, return_to=return_to, cval=cherrypy.session['cval']) except (splunk.AuthenticationFailed, KeyError): cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs( return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) if not cherrypy.session.get('sessionKey', None) or not util.isValidFormKey( kw['splunk_form_key']): # The user intended to change the password; reset the flag so this page will be shown again cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs( return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) try: user = User.get(cherrypy.session['user']['name']) user.password = newpassword if not user.save(): logger.error('Unable to save new admin password.') except splunk.AuthenticationFailed: cherrypy.session.delete() self.setLoginFlag(False) templateArgs = self.getLoginTemplateArgs( return_to=return_to, session_expired_pw_change=True) return self.render_template('account/login.html', templateArgs) except splunk.RESTException, e: err = e.get_message_text() if ':' in err: err = err[err.find(':') + 2:] logger.error("Failed to change the password: %s." % err) templateArgs['err'] = err return self.render_template('account/passwordchange.html', templateArgs)