def is_user_blocked(cls, username): user = {} with cls._lock: now = datetime.now() user = cls._failed_logins.get(username) #Block username for 'login_block_timeout' seconds if failed consecutively for 'login_retry_times' times if user and len(user['time'] ) >= SystemSettingsManage.get_login_retry_times(): dt = abs((now - user['time'][-1]).total_seconds()) if dt < SystemSettingsManage.get_tamper_protection_timeout(): return True cls._failed_logins.pop(username, None) return False
def GET(self, *args, **kwargs): result = {'SDCERR': 1, 'InfoMsg': "Device is busy"} if not cherrypy.session.get('swupdate', None): return result try: mode = int(kwargs.get('mode', 0)) except Exception as e: result['InfoMsg'] = 'Mode must be 0 (block/block mode) or 1 ' return result try: proc = Popen([SWUpdate.SWUPDATE_SCRIPT, "get-update", str(mode)], stdout=PIPE, stderr=PIPE) outs, errs = proc.communicate( timeout=SystemSettingsManage.get_user_callback_timeout()) if proc.returncode: ret_string = errs.decode("utf-8") result['InfoMsg'] = ret_string.replace("\n", "") result['SDCERR'] = proc.returncode else: result['InfoMsg'] = "Updated" result['SDCERR'] = 0 except TimeoutExpired: proc.kill() outs, errs = proc.communicate() result['InfoMsg'] = "Update checking timeout" except Exception as e: result['InfoMsg'] = "{}".format(e) return result
def POST(self): result = { 'SDCERR': WEBLCM_ERRORS.get('SDCERR_FAIL'), 'InfoMsg': '', } post_data = cherrypy.request.json username = post_data.get('username') password = post_data.get('password') permission = post_data.get('permission') if UserManageHelper.user_exists(username): result['InfoMsg'] = f'user {username} already exists' return result if not username or not password or not permission: result['InfoMsg'] = 'Missing user name, password, or permission' return result if UserManageHelper.getNumberOfUsers( ) < SystemSettingsManage.get_max_web_clients(): if UserManageHelper.addUser(username, password, permission): result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_SUCCESS') result['InfoMsg'] = 'User added' else: result['InfoMsg'] = 'failed to add user' else: result['InfoMsg'] = 'Max number of users reached' return result
def login_failed(cls, username): with cls._lock: now = datetime.now() user = cls._failed_logins.get(username, {}) if user: user['time'] = [ dt for dt in user['time'] if abs((now - dt).total_seconds()) < SystemSettingsManage.get_login_retry_window() ] if len(user['time'] ) >= SystemSettingsManage.get_login_retry_times(): user['time'].pop(0, None) else: user['time'] = [] user['time'].append(now) cls._failed_logins[username] = user
def GET(self, *args, **kwargs): typ = kwargs.get('type', None) if not typ: syslog('FileManage Get - no filename provided') raise cherrypy.HTTPError(400, 'no filename provided') fil = '{0}{1}'.format(typ, ".zip") path = '{0}{1}'.format("/tmp/", fil) if typ == "config": password = kwargs.get('password', None) if not password: syslog('FileManage Get - no password provided') raise cherrypy.HTTPError(400, 'no password provided') p = subprocess.Popen([ FileManage.FILE_MANAGE_SCRIPT, "config", "zip", weblcm_def.FILEDIR_DICT.get(typ), path, password ]) syslog("Configuration zipped for user") elif typ == "log": password = kwargs.get('password', None) if not password: syslog('FileManage Get - no password provided') raise cherrypy.HTTPError(400, 'no password provided') p = subprocess.Popen([ FileManage.FILE_MANAGE_SCRIPT, "log", "zip", FileManage._log_data_dir, path, password ]) syslog("System log zipped for user") elif typ == "debug": p = subprocess.Popen([ FileManage.FILE_MANAGE_SCRIPT, "debug", "zip", ' '.join([ FileManage._log_data_dir, weblcm_def.FILEDIR_DICT.get('config') ]), path, SystemSettingsManage.get_cert_for_file_encryption() ]) syslog("Configuration and system log zipped/encrypted for user") else: syslog(f"FileManage GET - unknown file type {typ}") raise cherrypy.HTTPError(400, f'unknown file type {typ}') p.wait() if os.path.isfile(path): objFile = static.serve_file(path, 'application/x-download', 'attachment', fil) os.unlink(path) return objFile syslog(f"Failed to create file {path} for user") raise cherrypy.HTTPError(500, f'failed to create file {path}')
def popenHelper(self, method="", zone="", dt=""): proc = Popen([DateTimeSetting.DATE_TIME_SCRIPT, method, zone, dt], stdout=PIPE, stderr=PIPE) try: outs, errs = proc.communicate( timeout=SystemSettingsManage.get_user_callback_timeout()) except TimeoutExpired: proc.kill() outs, errs = proc.communicate() return (proc.returncode, outs, errs)
def get_reg_domain_info(cls): if not os.path.exists(NetworkStatusHelper._IW_PATH): return "WW" try: proc = Popen(["iw", "reg", "get"], stdout=PIPE, stderr=PIPE) outs, errs = proc.communicate(timeout=SystemSettingsManage.get_user_callback_timeout()) if not proc.returncode: s = re.split('phy#', outs.decode("utf-8")) #Return regulatory domain of phy#0 m = re.search('country [A-Z][A-Z]', s[1] if len(s) > 1 else s[0]) if m: return m.group(0)[8:10] except TimeoutExpired: proc.kill() outs, errs = proc.communicate() syslog(LOG_ERR, "Call 'iw reg get' timeout") except Exception as e: syslog(LOG_ERR, "Call 'iw reg get' failed") return "WW"
def PUT(self): result = { 'SDCERR': WEBLCM_ERRORS.get('SDCERR_FAIL'), 'InfoMsg': 'Reboot required', } setOptions = ['unset', 'fips', 'fips_wifi'] post_data = cherrypy.request.json fips = post_data.get('fips', None) if fips not in setOptions: result[ 'InfoMsg'] = f'Invalid option: {fips}; valid options: {setOptions}' return result try: proc = Popen([Fips.FIPS_SCRIPT, fips], stdout=PIPE, stderr=PIPE) except Exception as e: syslog("FIPS SET exception: %s" % e) result['InfoMsg'] = 'Not a FIPS image' return result try: outs, errs = proc.communicate( timeout=SystemSettingsManage.get_user_callback_timeout()) except TimeoutExpired: proc.kill() outs, errs = proc.communicate() syslog("FIPS SET timeout: %s" % e) result['InfoMsg'] = 'FIPS SET timeout' except Exception as e: syslog("FIPS set exception: %s" % e) result['InfoMsg'] = 'FIPS SET exception: {}'.format(e) if not proc.returncode: result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_SUCCESS') else: syslog("FIPS set error: %s" % e) result['InfoMsg'] = 'FIPS SET error' return result
def get_frequency_info(cls, interface, frequency): if not os.path.exists(NetworkStatusHelper._IW_PATH): return frequency try: proc = Popen(["iw", "dev"], stdout=PIPE, stderr=PIPE) outs, errs = proc.communicate(timeout=SystemSettingsManage.get_user_callback_timeout()) if not proc.returncode: ifces = re.split('Interface', outs.decode("utf-8")) for ifce in ifces: lines = ifce.splitlines() if (lines[0].strip() != interface) or (len(lines) < 7): continue m = re.search('[2|5][0-9]{3}', lines[6]) if m: return m.group(0) except TimeoutExpired: proc.kill() outs, errs = proc.communicate() syslog(LOG_ERR, "Call 'iw dev' timeout") except Exception as e: syslog(LOG_ERR, "Call 'iw dev' failed") return frequency
def GET(self, *args, **kwargs): result = { 'SDCERR': WEBLCM_ERRORS.get('SDCERR_SUCCESS'), 'InfoMsg': '', 'status': "unset" } try: proc = Popen([Fips.FIPS_SCRIPT, 'status'], stdout=PIPE, stderr=PIPE) except Exception as e: syslog("FIPS get exception: %s" % e) result['InfoMsg'] = 'Not a FIPS image' return result try: outs, errs = proc.communicate( timeout=SystemSettingsManage.get_user_callback_timeout()) except TimeoutExpired: proc.kill() outs, errs = proc.communicate() syslog("FIPS get timeout: %s" % e) result['InfoMsg'] = 'FIPS GET timeout' except Exception as e: syslog("FIPS get exception: %s" % e) result['InfoMsg'] = 'FIPS GET exception: {}'.format(e) if not proc.returncode: try: result['status'] = outs.decode("utf-8").strip() except Exception as e: syslog('FIPS GET exception: %s' % e) else: syslog("FIPS GET error: %d" % proc.returncode) result['InfoMsg'] = 'FIPS GET error' return result
def do_swupdate( args, callback=None, timeout=SystemSettingsManage.get_user_callback_timeout()): try: proc = Popen(args, stdout=PIPE, stderr=PIPE) outs, errs = proc.communicate(timeout=timeout) if proc.returncode: ret_string = errs.decode("utf-8") result['InfoMsg'] = ret_string.replace("\n", "") result['SDCERR'] = proc.returncode else: if not callback or callback(dryrun) > 0: result['InfoMsg'] = '' result['SDCERR'] = 0 except TimeoutExpired: proc.kill() outs, errs = proc.communicate() result['InfoMsg'] = "Update checking timeout" except Exception as e: result['InfoMsg'] = "{}".format(e) return
def definitions(self, *args, **kwargs): plugins = [] for k in cherrypy.request.app.config['plugins']: plugins.append(k) settings = {} #Whether to display 'zone' on the 'edit connection' page settings['firewalld_disabled'] = Root._firewalld_disabled settings['session_timeout'] = SystemSettingsManage.get_session_timeout( ) return { 'SDCERR': weblcm_def.WEBLCM_ERRORS.get('SDCERR_SUCCESS'), 'InfoMsg': '', 'Definitions': { 'SDCERR': weblcm_def.WEBLCM_ERRORS, 'PERMISSIONS': weblcm_def.USER_PERMISSION_TYPES, 'DEVICE_TYPES': weblcm_def.WEBLCM_DEVTYPE_TEXT, 'DEVICE_STATES': weblcm_def.WEBLCM_STATE_TEXT, 'PLUGINS': plugins, 'SETTINGS': settings, } }
def POST(self): result = { 'SDCERR': WEBLCM_ERRORS.get('SDCERR_FAIL', 1), 'REDIRECT': 0, 'PERMISSION': "", 'InfoMsg': '', } post_data = cherrypy.request.json username = post_data.get('username', "") password = post_data.get('password', "") syslog(f"Attempt to login user {username}") #Return if username is blocked if not cherrypy.session.get('USERNAME', None): if LoginManageHelper.is_user_blocked(username): result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_USER_BLOCKED') result['InfoMsg'] = 'User blocked' return result default_username = cherrypy.request.app.config['weblcm'].get( 'default_username', "root") default_password = cherrypy.request.app.config['weblcm'].get( 'default_password', "summit") #If default password is not changed, redirect to passwd update page. if ((username == default_username) and (password == default_password)): cnt = UserManageHelper.getNumberOfUsers() if not cnt: UserManageHelper.addUser( username, password, " ".join(USER_PERMISSION_TYPES['UserPermissionTypes'])) if not cnt or UserManageHelper.verify(default_username, default_password): LoginManageHelper.login_reset(username) if LoginManageHelper.is_user_logged_in(username): result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_USER_LOGGED') result['InfoMsg'] = 'User already logged in' return result cherrypy.session['USERNAME'] = username result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_SUCCESS') result['REDIRECT'] = 1 result['InfoMsg'] = 'Password change required' syslog(f"User {username} logged in") return result #Session is created, but default password was not changed. if cherrypy.session.get('USERNAME', None) == default_username: if UserManageHelper.verify(default_username, default_password): result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_SUCCESS') result['REDIRECT'] = 1 result['InfoMsg'] = 'Password change required' syslog(f"User {username} logged in") return result #If session already exists, return success; otherwise verify login username and password. if not cherrypy.session.get('USERNAME', None): if not UserManageHelper.verify(username, password): LoginManageHelper.login_failed(username) result['InfoMsg'] = 'unable to verify user/password' return result LoginManageHelper.login_reset(username) if LoginManageHelper.is_user_logged_in(username): result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_USER_LOGGED') result['InfoMsg'] = 'User already logged in' return result cherrypy.session['USERNAME'] = username result['PERMISSION'] = UserManageHelper.getPermission( cherrypy.session.get('USERNAME', None)) #Don't display "system_user" page for single user mode if SystemSettingsManage.get_max_web_clients() == 1: result['PERMISSION'] = result['PERMISSION'].replace( "system_user", "") result['SDCERR'] = WEBLCM_ERRORS.get('SDCERR_SUCCESS') result['InfoMsg'] = 'User logged in' syslog(f"user {username} logged in") return result
webapp.firmware = SWUpdate() webapp.reboot = Reboot() webapp.factoryReset = FactoryReset() webapp.datetime = DateTimeSetting() webapp.positioningSwitch = PositioningSwitch() webapp.positioning = Positioning() if Bluetooth is not None: webapp.bluetooth = Bluetooth() webapp.fips = Fips() setup_http_server() logging.getLogger("cherrypy").propagate = False cherrypy.request.hooks.attach('before_handler', force_session_checking) #Server config cherrypy.config.update({ 'tools.sessions.timeout': SystemSettingsManage.get_session_timeout(), }) cherrypy.quickstart(webapp, '/', config=weblcm_def.WEBLCM_PYTHON_SERVER_CONF_FILE)