def unlock_machine(): # Remove security settings from the machine so it can be used by admins to do # maintenance/etc... ret = True # Make sure we disable student accounts! if not UserAccounts.disable_student_accounts(): p("}}rbUnable to disable student accounts!}}xx") return False # Log out student accounts! if not UserAccounts.log_out_all_students(): p("}}rbUnable to log out students!}}xx") return False # Reset group policy GroupPolicy.reset_group_policy_to_default() # Reset firewall GroupPolicy.reset_firewall_policy() return ret
def ensure_admin(): # Get the is in administrators, is uac, and username and return them return (UserAccounts.is_in_admin_group(), UserAccounts.is_uac_admin(), UserAccounts.get_current_user())
def credential_input_verify_loop(): # Loop until we quit or get good stuff # Return a list of values # student_full_name, laptop_admin_user, laptop_admin_password ret = [] mgmt_version = CredentialProcess.get_mgmt_version() smc_url = RegistrySettings.get_reg_value(value_name="smc_url", default="https://smc.ed") canvas_url = "" canvas_access_token = "" student_user = RegistrySettings.get_reg_value(value_name="student_user") student_full_name = "" student_password = "" smc_admin_user = RegistrySettings.get_reg_value(app="OPEService", value_name="smc_admin_user", default="admin") smc_admin_password = "" laptop_admin_user = "" laptop_admin_password = "" loop_running = True while loop_running: p("\n}}gb Version: " + mgmt_version + "}}xx") p(""" }}mn====================================================================== }}mn| }}ybOPE Credential App }}mn| }}mn| }}xxThis app will add student credentials to the computer and }}mn| }}mn| }}xxsecure the laptop for inmate use. }}mn| }}mn| }}yn(answer with quit to stop this tool) }}mn| }}mn======================================================================}}xx """) # 4 - Ask for input (smc server, login, student name, etc...) p("}}ynEnter URL for SMC Server }}cn[enter for " + smc_url + "]:}}xx ", False) tmp = input() tmp = tmp.strip() if tmp.lower() == "quit": p("}}rnGot QUIT - exiting credential!}}xx") return None if tmp == "": tmp = smc_url smc_url = tmp # Make sure url has https or http in it if "https://" not in smc_url.lower() and "http://" not in smc_url.lower(): smc_url = "https://" + smc_url p("}}ynPlease enter the ADMIN user name }}cn[enter for " + smc_admin_user + "]:}}xx ", False) tmp = input() tmp = tmp.strip() if tmp.lower() == "quit": p("}}rnGot QUIT - exiting credential!}}xx") return None if tmp == "": tmp = smc_admin_user smc_admin_user = tmp p("}}ynPlease enter ADMIN password }}cn[characters will not show]:}}xx", False) tmp = getpass.getpass(" ") if tmp.lower() == "quit": p("}}rnGot QUIT - exiting credential!}}xx") return None if tmp == "": p("}}rbA password is required.}}xx") continue smc_admin_password = tmp tmp = "" last_student_user_prompt = "" while tmp.strip() == "": if student_user != "": last_student_user_prompt = " }}cn[enter for previous student " + student_user + "]" # p("}}mb\t- Found previously credentialed user: }}xx" + str(last_student_user)) p("}}ynPlease enter the username for the student" + last_student_user_prompt + ":}}xx ", False) tmp = input() if tmp.lower() == "quit": p("}}rnGot QUIT - exiting credential!}}xx") return None if tmp.strip() == "": tmp = student_user student_user = tmp.strip() # - Bounce off SMC - verify_ope_account_in_smc try: result = RestClient.verify_ope_account_in_smc(student_user, smc_url, smc_admin_user, smc_admin_password) if result is None: # Should show errors during the rest call, so none here #p("}}rbUnable to validate student against SMC!}}xx") # Jump to top of loop and try again continue #return False # sys.exit(-1) except Exception as ex: p("}}rbError - Unable to verify student in SMC}}xx\n" + str(ex)) # Jump to top of loop and try again continue # If not None - result will be a tuple of information laptop_admin_user, student_full_name, smc_version = result # Verify that the info is correct txt = """ }}mn====================================================================== }}mn| }}gbFound Student - Continue? }}mn| }}mn| }}ynCredential Version: }}cn<mgmt_version>}}mn| }}mn| }}ynSMC URL: }}cn<smc_url>}}mn| }}mn| }}ynSMC Version: }}cn<smc_version>}}mn| }}mn| }}ynLaptop Admin User: }}cn<admin_user>}}mn| }}mn| }}ynStudent Username: }}cn<student_user>}}mn| }}mn| }}ynSystem Serial Number: }}cn<bios_serial_number>}}mn| }}mn| }}ynDisk Serial Number: }}cn<disk_serial_number>}}mn| }}mn======================================================================}}xx """ col_size = 44 txt = txt.replace("<mgmt_version>", mgmt_version.ljust(col_size)) txt = txt.replace("<smc_url>", smc_url.ljust(col_size)) txt = txt.replace("<smc_version>", smc_version.ljust(col_size)) txt = txt.replace("<admin_user>", laptop_admin_user.ljust(col_size)) txt = txt.replace("<admin_pass>", "******".ljust(col_size)) student_text = student_user + " (" + student_full_name + ")" txt = txt.replace("<student_user>", student_text.ljust(col_size)) txt = txt.replace("<bios_serial_number>", CredentialProcess.COMPUTER_INFO['bios_serial_number'].ljust(col_size)) txt = txt.replace("<disk_serial_number>", CredentialProcess.COMPUTER_INFO['disk_boot_drive_serial_number'].ljust(col_size)) p(txt) p("}}ybPress Y to continue: }}xx", False) tmp = input() tmp = tmp.strip().lower() if tmp != "y": p("}}cnCanceled - trying again....}}xx") continue # Show the warning regarding locking down the boot options p(""" }}mn====================================================================== }}mn| }}rb==================== WARNING!!! ==================== }}mn| }}mn| }}xxEnsure that the boot from USB or boot from SD card options in }}mn| }}mn| }}xxthe bios are disabled and that the admin password is set to a }}mn| }}mn| }}xxstrong random password. }}mn| }}mn======================================================================}}xx """) p("}}ybHave you locked down the BIOS? Press Y to continue: }}xx", False) tmp = input() tmp = tmp.strip().lower() if tmp != "y": p("}}cnCanceled - trying again....}}xx") continue # - Bounce off SMC - lms/credential_student.json/?? result = None try: ex_info = dict() ex_info["logged_in_user"] = UserAccounts.get_current_user() ex_info["admin_user"] = laptop_admin_user ex_info["current_student"] = student_user ex_info["mgmt_version"] = mgmt_version ex_info.update(CredentialProcess.COMPUTER_INFO) result = RestClient.credential_student_in_smc( student_user, smc_url, smc_admin_user, smc_admin_password, dict(ex_info=ex_info)) if result is None: p("}}rbUnable to credential student via SMC!}}xx") # Jump to top of loop and try again continue #return False # sys.exit(-1) except Exception as ex: p("}}rbError - Unable to credential student via SMC}}xx\n" + str(ex)) # Jump to top of loop and try again continue (student_full_name, canvas_url, canvas_access_token, student_password, laptop_admin_password) = result loop_running = False ret = (student_user, student_full_name, student_password, laptop_admin_user, laptop_admin_password, canvas_access_token, canvas_url, smc_url) return ret
def start_upgrade_process(branch=None, force_upgrade=None): ret = True if not CredentialProcess.is_time_to_upgrade(): p("}}gnNot time to check for upgrades yet, skipping...}}xx", log_level=3) return True RegistrySettings.set_reg_value(value_name="last_upgrade_time", value=time.time()) curr_branch = branch if curr_branch is None: # See if a parameter was provided curr_branch = util.get_param(2, None) # Force upgrade - even if versions match if force_upgrade is None: force_upgrade = util.get_param(3, "") if force_upgrade.lower() != "-f": force_upgrade = False else: force_upgrade = True # If branch is still empty, get it from the registry if curr_branch is None: curr_branch = RegistrySettings.get_reg_value(value_name="install_branch", default="master") # Start by grabbing any new stuff from the git server ret = ProcessManagement.git_pull_branch(curr_branch) if ret is False: # Not critical if this fails - apply whatever is present if it is # a different version number # return False p("}}ybWARNING - Unable to pull updates for git server!}}xx") pass # Save the current branch for next time RegistrySettings.set_reg_value(value_name="install_branch", value=curr_branch) # Check the mgmt.version files to see if we have a new version ope_laptop_binaries_path = os.path.expandvars("%programdata%\\ope\\tmp\\ope_laptop_binaries") # Get the path to the mgmt.version file git_version_path = os.path.join(ope_laptop_binaries_path, "Services", "mgmt", "mgmt.version") # Do we have a new version? curr_version = CredentialProcess.get_mgmt_version() git_version = CredentialProcess.get_mgmt_version(git_version_path) if git_version == "NO VERSION": # No version file found p("}}ynNo version file found in git repo, skipping upgrade!}}xx") return False if not CredentialProcess.is_version_newer(curr_version, git_version) and force_upgrade is not True: # Same version - no upgrade needed p("}}gnOPE Software up to date: " + str(git_version) + " not newer than " + str(curr_version) + " - (not upgrading)}}xx") return True # Version is different, prep for update forced = "" if force_upgrade: forced = "}}yb(upgrade forced)}}gn" p("}}gnFound new version " + forced + " - starting upgrade process: " + \ curr_version + " --> " + git_version + "}}xx") # Lock user accounts if not UserAccounts.disable_student_accounts(): p("}}rbERROR - Unable to disable student accounts prior to upgrade!}}xx") return False # Make sure students are logged out if not UserAccounts.log_out_all_students(): p("}}rbERROR - Unable to log out student accounts prior to upgrade!}}xx") return False p("}}ynLaunching OPE Software Update process...}}xx") # run the upgrade_ope.cmd from the TMP rc folder!!! bat_path = os.path.join(ope_laptop_binaries_path, "Services\\mgmt\\rc\\upgrade_ope.cmd") # Add the redirect so we end up with a log file if not ProcessManagement.run_detatched_cmd(bat_path + " >> %programdata%\\ope\\tmp\\log\\upgrade.log 2>&1"): p("}}rbERROR - Unable to start upgrade process!}}xx") return False # Make sure to exit this app?? #sys.exit(0) return ret
def lock_machine(): # Apply secuirty settings and re-enable student account so it can be # handed back to a student ret = True # Get the current credentialed student student_user_name = CredentialProcess.get_credentialed_student() if student_user_name is None: p("}}rbNot Credentiled! - Unable to find credentialed student - not locking machine!}}xx") return False # Get the current admin user name admin_user_name = CredentialProcess.get_credentialed_admin() if admin_user_name is None: p("}}rbNot Credentiled! - Unable to find credentialed admin account - not locking machine!}}xx") return False # Log out the student if not UserAccounts.log_out_user(student_user_name): p("}}rbError - Unable to logout student: " + str(student_user_name) + "}}xx") return False # Apply firewall rules if not GroupPolicy.apply_firewall_policy(): p("}}rbError - Could Not apply firewall policy!\nStudent Account NOT unlocked!}}xx") return False # Apply group policy if not GroupPolicy.apply_group_policy(): p("}}rbError - Could Not apply group policy!\nStudent Account NOT unlocked!}}xx") return False # Lock down boot options if not FolderPermissions.lock_boot_settings(): p("}}rbError - Could not lock boot settings!\nStudent Account NOT unlocked!}}xx") return False # Reset registry permissions if not RegistrySettings.set_default_ope_registry_permissions(): p("}}rbError - Could not reset registry permissions!\nStudent Account NOT unlocked!}}xx") return False # Reset folder permissions if not FolderPermissions.set_default_ope_folder_permissions(): p("}}rbError - Could not reset ope folder permissions!\nStudent Account NOT unlocked!}}xx") return False # Reset student users group memberships if not UserAccounts.set_default_groups_for_student(student_user_name): p("}}rbError - Could not reset default groups for student!\nStudent Account NOT unlocked!}}xx") return False # Reset admin users group memberships if not UserAccounts.set_default_groups_for_admin(admin_user_name): p("}}rbError - Could not reset default groups for the admin account!\nStudent Account NOT unlocked!}}xx") return False # Ensure the OPEService is running if not CredentialProcess.ensure_opeservice_running(): p("}}rbError - Verify OPEService is running!\nStudent Account NOT unlocked!}}xx") return False # Enable student account if not UserAccounts.enable_account(student_user_name): p("}}rbError - Failed to enable student account: " + str(student_user_name) + "}}xx") return False return ret
def credential_laptop(): # Are we running as admin w UAC?? if not UserAccounts.is_uac_admin(): p("}}rbNot Admin in UAC mode! - UAC Is required for credential process.}}xx") return False # Get computer info CredentialProcess.COMPUTER_INFO = Computer.get_machine_info(print_info=False) # Are we in a domain? if CredentialProcess.COMPUTER_INFO["cs_part_of_domain"] is True: p("}}rbSystem is doing to an Active Directory Domain - NOT SUPPORTED!\n" + "Please remove this from the domain as it might interfere with security settings.}}xx") return False # Are we using a proper edition win 10? (Home not supported, ed, pro, enterprise ok?) # OK - win 10 - pro, ed, enterprise # NOT OK - non win 10, win 10 home is_win10 = False is_win10_home = True os_caption = CredentialProcess.COMPUTER_INFO["os_caption"] if "Microsoft Windows 10" in os_caption: is_win10 = True if "Enterprise" in os_caption or "Professional" in os_caption or "Education" in os_caption: is_win10_home = False if is_win10 is not True: p("}}rbNOT RUNNING ON WINDOWS 10!!!\nThis software is designed to work win windows 10 ONLY!\n (Enterprise, Professional, or Education OK, Home edition NOT supported)}}xx") return False if is_win10_home is True: p("}}rbWIN10 HOME EDITION DETECTED!\nThis software is designed to work win windows 10 ONLY!\n (Enterprise, Professional, or Education OK, Home edition NOT supported)}}xx") return False # Disable guest account p("}}gnDisabling guest account}}xx", debug_level=2) UserAccounts.disable_guest_account() # Make sure folder exist and have proper permissions if not FolderPermissions.set_default_ope_folder_permissions(): p("}}rbERROR - Unable to ensure folders are present and permissions are setup properly!}}xx") return False CredentialProcess.trust_ope_certs() # Disable all student accounts UserAccounts.disable_student_accounts() result = CredentialProcess.credential_input_verify_loop() if result is None: # Unable to verify? return False (student_user, student_name, student_password, admin_user, admin_password, canvas_access_token, canvas_url, smc_url) = result # - Create local student account p("}}gnCreating local student windows account...}}xx") if not UserAccounts.create_local_student_account(student_user, student_name, student_password): p("}}rbError setting up OPE Student Account}}xx\n " + str(ex)) return False # - Setup admin user p("}}gnCreating local admin windows account...}}xx") try: UserAccounts.create_local_admin_account(admin_user, "OPE Laptop Admin", admin_password) except Exception as ex: p("}}rbError setting up OPE Laptop Admin Account}}xx\n " + str(ex)) admin_password = "" # Store the credential information if not RegistrySettings.store_credential_info(canvas_access_token, canvas_url, smc_url, student_user, student_name, admin_user): p("}}rbError saving registry info!}}xx") return False # Create desktop shortcut #p("\n}}gnSetting up LMS App...}}xx") Computer.create_win_shortcut( lnk_path = "c:\\users\\public\\desktop\\OPE LMS.lnk", ico_path = "%programdata%\\ope\\Services\\lms\\logo_icon.ico", target_path = "%programdata%\\ope\\Services\\lms\\ope_lms.exe", description = "Offline LMS app for Open Prison Education project" ) p("}}gnLocking machine - applying security settings...}}xx") if not CredentialProcess.lock_machine(): p("}}rbERROR - Unable to lock machine after credentail!}}xx") return False return True
def take_screenshot(): ret = False ScreenShot.init_globals() if ScreenShot.DISABLE_SSHOT: p("}}ybSkipping screen shot - disabled by .disable_sshot file}}xx", log_level=2) return # Find the logged in user and run the sshot.exe app cmd = os.path.join(util.BINARIES_FOLDER, "sshot\\sshot.exe") p("}}gnTrying to run " + cmd + "}}xx", log_level=4) user_token = UserAccounts.get_active_user_token() if user_token is None: p("}}ynUnable to get user token - screen locked?}}xx", log_level=2) return ret sidObj, intVal = win32security.GetTokenInformation( user_token, win32security.TokenUser) #source = win32security.GetTokenInformation(tokenh, TokenSource) if sidObj: accountName, domainName, accountTypeInt = \ win32security.LookupAccountSid(".", sidObj) else: p("}}rnUnable to get User Token! }}xx", log_level=1) return None #p("}}gnFound User Token: " + str(user_token) + "}}xx", log_level=5) # If user is in the administrators group, skip taking the sshot if UserAccounts.is_in_admin_group(accountName): p("}}mbUser (" + accountName + ") is in admin group, skipping screen shot...}}xx") return True p("}}gnRunning As: " + accountName + "}}xx", log_level=2) # Put this token in the logged in session #win32security.SetTokenInformation(user_token_copy, win32security.TokenSessionId, session_id) # Use win create process function si = win32process.STARTUPINFO() si.dwFlags = win32process.STARTF_USESHOWWINDOW si.wShowWindow = win32con.SW_NORMAL # si.lpDesktop = "WinSta0\Default" si.lpDesktop = "WinSta0\\Default" # Setup envinroment for the user environment = win32profile.CreateEnvironmentBlock(user_token, False) try: ( hProcess, hThread, dwProcessId, dwThreadId ) = win32process.CreateProcessAsUser( user_token, None, # AppName (really command line, blank if cmd line supplied) "\"" + cmd + "\"", # Command Line (blank if app supplied) None, # Process Attributes None, # Thread Attributes 0, # Inherits Handles win32con. NORMAL_PRIORITY_CLASS, # or win32con.CREATE_NEW_CONSOLE, environment, # Environment os.path.dirname(cmd), # Curr directory si) # Startup info p("Process Started: " + str(dwProcessId), log_level=5) p(hProcess, log_level=5) ret = True except Exception as e: p("}}rnError launching process:}}xx\n" + str(e), log_level=1) # Cleanup user_token.close() # else: # # Not logged in as system user, run as current user # try: # timeout = 10 # 10 seconds? # # Log an error if the process doesn't return 0 # # stdout=PIPE and stderr=STDOUT instead of capture_output=True # p("}}gnRunning as current user " + user_name + "}}xx") # proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,timeout=timeout, check=False) # if (proc.returncode == 0): # p("Command Results: " + cmd + "\n" + proc.stdout.decode()) # ret = True # else: # p("*** Command Failed!: " + cmd + "(" + str(proc.returncode) + ") \n" + proc.stdout.decode()) # except Exception as ex: # p("*** Command Exception! " + cmd + " \n" + \ # str(ex)) if ret is True: p("}}gnSnapped.}}xx", log_level=3) return ret
def scan_nics(): # May need to call this before calling this function so that COM works # pythoncom.CoInitialize() - called in the main function # Make sure device list is initialized NetworkDevices.init_device_list() p("scanning for unauthorized nics...", log_level=4) nic_list = NetworkDevices.get_nics_w32() for nic in nic_list: (nic_name, nic_network_name, nic_ip_addresses, nic_connected, nic_enabled, attribs, iface, nic_if_index) = nic # Make sure we remove local link ips (169.254.?.?) filtered_nic_ip_addresses = NetworkDevices.filter_local_link_ip_addresses( nic_ip_addresses) # NOTE - nic_enabled - 0 = enabled, 22 = disabled, all others - ?? (not enabled) # Use nic descrition to match - it doesn't have #2 etc.. at the end nic_description = iface.Description # Returns T/F for (matched_nic_name, matched_nic_ip) r = NetworkDevices.is_nic_approved(nic_description, filtered_nic_ip_addresses) num_ips = len(filtered_nic_ip_addresses) # Possible on scenarios, # A - Nic is not approved (IP doesn't matter) - turn off # B - Nic is on, approved, and has good IP - leave alone # C - Nic is on, approved, has NO IP (e.g. unplugged/offline) - allow DHCP attempts # D - Nic is on, approved, has BAD IP! (good adapter plugged into bad network!) # *** NOTE - This is security issue - who plugged into bad network!?! # Possible off scenarios # E - Nic is off, not approved, IP doesn't matter # F - Nic is off, approved, has no IP - needs to turn on and allow DHCP # # A - If adapter isn't on the list, kill it. if r[0] is not True and nic_enabled == 0: p("}}ynUnApproved NIC Detected (NO IP) - Disabling " + \ nic_name + "}}xx", log_level=1) try: NetworkDevices.disable_nic(nic_if_index) except Exception as ex: p("}}rb** ERROR - UNABLE TO DISABLE DEVICE: " + nic_name + "}}xx\n" + str(ex), log_level=1) continue # B - Nic is approved and has good IP and is on if r[0] is True and r[1] is True and nic_enabled == 0: # Good nic, good ip, adapter on. p("}}gn** Nic approved and good ip: " + nic_name + "}}xx", log_level=5) continue # C - Nic is on, approved, has no IP (should be trying to get IP via DHCP) if r[0] is True and num_ips == 0 and nic_enabled == 0: # Good nic, waiting for dhcp, adapter on. p("}}gn** Nic approved, waiting for dhcp: " + nic_name + "}}xx", log_level=5) continue # D - Nic is on, approved, has BAD IP! (good adapter plugged into bad network!) # *** NOTE - This is security issue - who plugged into bad network!?! if r[0] is True and nic_enabled == 0 and r[ 1] is False and num_ips > 0: # Good nic on bad network. disable it! curr_user = UserAccounts.get_active_user_name() p("}}rb** Approved NIC on BAD IP Network Detected - Disabling " + \ nic_name + " " + str(nic_ip_addresses) + " - why is this plugged into another network?!}}xx", log_level=1) try: NetworkDevices.disable_nic(nic_if_index) except Exception as ex: p("}}rb** ERROR - UNABLE TO DISABLE DEVICE: " + nic_name + "}}xx\n" + str(ex), log_level=1) continue # E - Nic is off, not approved, IP doesn't matter if nic_enabled == 22 and r[0] is not True: # Bad nic - already off p("}}yn** Unapproved nic, already disabled " + nic_name + "}}xx", log_level=4) continue # F - Nic is off, approved, has no IP - needs to turn on and allow DHCP if nic_enabled == 22 and r[0] is True: # Turn on so it can try for DHCP address p("}}gb** Approved nic found disabled, enabling " + nic_name + "}}xx", log_level=4) try: NetworkDevices.enable_nic(nic_if_index) except Exception as ex: p("}}rb** ERROR - UNABLE TO ENABLE DEVICE: " + nic_name + "}}xx\n" + str(ex), log_level=1) continue # If none of the previous entries match, kill the device if it is enabled if nic_enabled == 0: # Failsafe p("}}rb**** No rule for this nic, disabling! " + nic_name + "}}xx") try: NetworkDevices.disable_nic(nic_if_index) except Exception as ex: p("}}rb** ERROR - UNABLE TO DISABLE DEVICE: " + nic_name + "}}xx\n" + str(ex), log_level=1) continue # OLD commands #cmd = "netsh interface set interface \"" + dev_id + "\" admin=ENABLED" #cmd = "netsh interface set interface \"" + dev_id + "\" admin=DISABLED" return True