if not getID() == "": addon = xbmcaddon.Addon(getID()) addon_name = getName() # Reset the ovpn files if action == "ovpn": if addon.getSetting("1_vpn_validated") == "" or xbmcgui.Dialog().yesno( addon_name, "Resetting the VPN provider will disconnect and reset all VPN connections, and then remove any files that have been created. Continue?" ): suspendConfigUpdate() # Disconnect so that live files are not being modified if isVPNConnected(): resetVPNConnections(addon) debugTrace("Deleting all generated files") # Delete the generated files, and reset the locations so it can be selected again removeGeneratedFiles() # Delete any values that have previously been validated vpn_provider = getVPNLocation(addon.getSetting("vpn_provider")) if isAlternative(vpn_provider): resetAlternative(vpn_provider) # Reset the IP service error counts, etc resetIPServices() addon = xbmcaddon.Addon(getID()) # Reset values that would have been stored as part of validation addon.setSetting("vpn_provider_validated", "") addon.setSetting("vpn_locations_list", "") addon.setSetting("vpn_username_validated", "") addon.setSetting("vpn_password_validated", "") # Re-enble the wizard addon.setSetting("vpn_wizard_enabled", "true") resumeConfigUpdate() xbmcgui.Dialog().ok(
def importWizard(): addon = xbmcaddon.Addon(getID()) addon_name = getName() errorMessage = "" success = False cancel = False xbmcgui.Dialog().ok(addon_name, "The User Defined import wizard helps you set up an unsupported VPN provider. It may not work without additional user intervention. You should review the import log and subsequent VPN logs to debug any problems.") # Warn the user that files will be deleted and kittens will be harmed if xbmcgui.Dialog().yesno(addon_name, "Any existing User Defined settings and files will be deleted. Do you want to continue?"): removeGeneratedFiles() success = clearUserData() addon.setSetting("vpn_provider", "User Defined") if not success: errorMessage = "Could not clear the UserDefined directory. Check the log." else: success = False errorMessage = "Import wizard has not been run, no settings or files have been changed." # Get the list of files to be used if success: if xbmcgui.Dialog().yesno(addon_name, "Select ALL files needed to connect to the VPN provider, including .ovpn, .key and .crt files. Select a directory (sub directories are ignored) or select multiple files within a directory?.", nolabel="Directory", yeslabel="Files"): directory_input = False files = xbmcgui.Dialog().browse(1, "Select all VPN provider files", "files", "", False, False, "", True) else: directory_input = True dname = xbmcgui.Dialog().browse(0, "Select a directory containing VPN provider files", "files", "", False, False, "", False) debugTrace("Import from directory " + dname) dirs, files = xbmcvfs.listdir(dname) # Separate the selected files into ovpn files and other files ovpn_files = [] other_files = [] for name in files: if directory_input: name = dname + name debugTrace("Found file " + name) if name.endswith(".ovpn"): ovpn_files.append(name) else: other_files.append(name) if len(ovpn_files) == 0: success = False errorMessage = "No .ovpn files found. You must provide at least one .ovpn file." # Copy and modify the ovpn files if success: # Create some logs to write out later summary = [] detail = [] summary.append("Importing selected files to User Defined directory, " + getUserDataPath("UserDefined/") + "\n") summary.append("at " + time.strftime('%Y-%m-%d %H:%M:%S') + "\n") detail.append("\n=== Import details ===\n\n") update = False rename = False if not xbmcgui.Dialog().yesno(addon_name, "Update the .ovpn files to best guess values and determine the best User Defined provider settings [I](recommended)[/I]?", nolabel="Yes", yeslabel="No"): update = True detail.append("Updating the .ovpn files to best guess settings\n") if not xbmcgui.Dialog().yesno(addon_name, "Rename the .ovpn files to indicate either a UDP or TCP connection type to allow filtering of connections [I](recommended)[/I]?", nolabel="Yes", yeslabel="No"): rename = True detail.append("Files will be renamed to indicate UDP or TCP\n") # Display dialog to show progress of copying files dialog_step = 100/(len(ovpn_files) + len(other_files)) progress = xbmcgui.DialogProgress() progress_title = "Copying User Defined files." progress.create(addon_name,progress_title) prog_step = 0 xbmc.sleep(500) try: dest_path = getUserDataPath("UserDefined/") debugTrace("Checking directory path exists before copying " + dest_path) if not os.path.exists(dest_path): infoTrace("userdefined.py", "Creating " + dest_path) os.makedirs(os.path.dirname(dest_path)) xbmc.sleep(500) # Loop around waiting for the directory to be created. After 10 seconds we'll carry # on and let he open file calls fail and throw an exception t = 0 while not os.path.exists(os.path.dirname(dest_path)): if t == 9: errorTrace("userdefined.py", "Waited 10 seconds to create directory but it never appeared") break xbmc.sleep(1000) t += 1 other_files_count = [] for fname in other_files: path, dest_name = os.path.split(fname) dest_name = getUserDataPath("UserDefined/" + dest_name) # Report file being copied, then do it progress_message = "Copying " + fname progress.update(prog_step, progress_title, progress_message) xbmc.sleep(100) prog_step += dialog_step infoTrace("userdefined.py", "Copying " + fname + " to " + dest_name) detail.append("Copying " + fname + " to " + dest_name + "\n") xbmcvfs.copy(fname, dest_name) if not xbmcvfs.exists(dest_name): raise IOError('Failed to copy user def file ' + fname + " to " + dest_name) other_files_count.append(0) if progress.iscanceled(): cancel = True break auth_count = 0 auth_found = 0 cert_count = 0 cert_found = 0 multiple_certs = False last_cert_found = "" ecert_count = 0 key_count = 0 key_found = 0 key_pass_found = 0 key_pass_count = 0 multiple_keys = False last_key_found = "" ekey_count = 0 if not cancel: metadata = getGitMetaData("UserDefined") mods = [] if not metadata == None: for line in metadata: line = line.strip(' \t\n\r') mods.append(line) for oname in ovpn_files: path, dest_name = os.path.split(oname) dest_name = getUserDataPath("UserDefined/" + dest_name) # Update dialog to saywhat's happening if update: progress_message = "Copying and updating " + oname else: progress_message = "Copying " + oname progress.update(prog_step, progress_title, progress_message) xbmc.sleep(100) prog_step += dialog_step # Copy the ovpn file infoTrace("userdefined.py", "Copying " + oname + " to " + dest_name) detail.append("Copying " + oname + " to " + dest_name + "\n") xbmcvfs.copy(oname, dest_name) if not xbmcvfs.exists(dest_name): raise IOError('Failed to copy user def ovpn ' + oname + " to " + dest_name) if update: # Read the copied file in and then overwrite it with any updates needed # Was doing a read from source and write here but this failed on Linux over an smb mount (file not found) auth = False keypass = False infoTrace("userdefined.py", "Updating " + dest_name) detail.append("Updating " + dest_name + "\n") source_file = open(dest_name, 'r') source = source_file.readlines() source_file.close() dest_file = open(dest_name, 'w') proto = "UDP" flags = [False, False, False, False, False] for line in source: line = line.strip(' \t\n\r') old_line = line i = 0 # Look for each non ovpn file uploaded and update it to make sure the path is good for fname in other_files: path, name = os.path.split(fname) if not line.startswith("#"): params = line.split() if len(params) > 2: # Remove the separator in order to get any fully qualified filename as space delimited params[1].replace(getSeparator(), " ") # Add in a leading space for unqualified filenames params[1] = " " + params[1] if params[1].endswith(" " + name): old_line = line line = params[0] + " " + "#PATH" + getSeparatorOutput() + name # Add any trailing parameters back in if len(params) > 2: for i in range(2, len(params)): line = line + " " + params[i] detail.append(" Found " + name + ", old line was : " + old_line + "\n") detail.append(" New line is " + line + "\n") other_files_count[i] += 1 if line.startswith("auth-user-pass"): auth_found += 1 auth = True if line.startswith("cert "): cert_found += 1 if line.startswith("key "): key_found += 1 if line.startswith("askpass "): key_pass_found += 1 keypass = True i += 1 # Do some tag counting to determine authentication methods to use if not line.startswith("#"): for mod in mods: flag, verb, parms = mod.split(",") if flag == "1" and line.startswith(verb) and parms in line: flags[0] = True if flag == "3" and line.startswith(verb): flags[2] = True if flag == "4" and line.startswith(verb): line = verb + " " + parms if flag == "5" and not flags[4] and verb in line: detail.append(" WARNING, " + parms + "\n") flags[4] = True if line.startswith("auth-user-pass"): auth_count += 1 if not auth: line = "auth-user-pass #PATH" + getSeparatorOutput() + "pass.txt" if line.startswith("cert "): cert_count += 1 if not last_cert_found == old_line: if not last_cert_found == "": multiple_certs = True last_cert_found = old_line if line.startswith("key "): key_count += 1 if not last_key_found == old_line: if not last_key_found == "": multiple_keys = True last_key_found = old_line if line.startswith("askpass"): key_pass_count += 1 if not keypass: line = "askpass #PATH" + getSeparatorOutput() + "key.txt" if line.startswith("proto "): if "tcp" in (line.lower()): proto = "TCP" if line.startswith("<cert>"): ecert_count += 1 if line.startswith("<key>"): ekey_count += 1 if not flags[2]: dest_file.write(line+"\n") flags[2] = False for mod in mods: flag, verb, parms = mod.split(",") if flag == "2": dest_file.write(verb+"\n") dest_file.close() flags[4] = False if flags[0]: if xbmcvfs.exists(dest_name): xbmcvfs.delete(dest_name) detail.append(" wARNING, couldn't import file as it contains errors or is unsupported\n") elif rename: proto = " (" + proto + ").ovpn" new_name = dest_name.replace(".ovpn", proto) if not xbmcvfs.exists(new_name): xbmcvfs.rename(dest_name, new_name) detail.append(" Renamed to " + new_name + "\n") else: detail.append(" WARNING, couldn't rename file to " + new_name + " as a file with that name already exists\n") if progress.iscanceled(): cancel = True break except Exception as e: errorTrace("userdefined.py", "Failed to copy (or update) file") errorTrace("userdefined.py", str(e)) success = False errorMessage = "Failed to copy (or update) selected files. Check the log." progress_message = "Outputting results of import wizard" progress.update(100, progress_title, progress_message) xbmc.sleep(500) # General import results summary.append("\n=== Summary of import ===\n\n") if cancel: summary.append("Import was cancelled\n") else: summary.append("Imported " + str(len(ovpn_files)) + " .ovpn files and " + str(len(other_files)) + " other files.\n") summary.append("\nYou should understand any WARNINGs below, and validate that the .ovpn files imported have been updated correctly.\n\n") summary.append("If the VPN connection fails view the VPN log to determine why, using Google to understand the errors if necessary.\n") summary.append("You can fix problems either by editing your local files and re-importing, or by editing the contents of the User Defined directory.\n\n") if update: # Report on how user names and passwords will be handled if auth_count > 0: if auth_found > 0: # Not using a password as resolved by file addon.setSetting("user_def_credentials", "false") summary.append("The auth-user-pass tag was found " + str(auth_count) + " times, but was resolved using a supplied file so user name and password don't need to be entered.\n") if not auth_found == auth_count: summary.append(" WARNING : The auth-user-pass tag was found " + str(auth_count) + " times, but only resolved using a supplied file " + str(auth_found) + " times. Some connections may not work.\n") else: # Using a password as auth-user-pass tag was found addon.setSetting("user_def_credentials", "true") summary.append("The auth-user-pass tag was found " + str(auth_count) + " times so assuming user name and password authentication is used.\n") if auth_count < len(ovpn_files): summary.append(" WARNING : The auth-user-pass tag was only found in " + str(auth_count) + " .ovpn files, out of " + str(len(ovpn_files)) + ". Some connections may not work.\n") else: # Not using a password as no auth-user-pass tag was found addon.setSetting("user_def_credentials", "false") summary.append("No auth-user-pass tag was found, so assuming user name and password is not needed.\n") # Report on how keys and certs will be handled if (cert_count > 0 or key_count > 0): summary.append("The key tag was found " + str(key_count) + " times, and the cert tag was found " + str(cert_count) + " times.\n") if cert_found > 0 or key_found > 0: # Key and cert resolved by file so not asking user for them addon.setSetting("user_def_keys", "None") summary.append("The key and certificate don't need to be requested as the key tags were resolved using a supplied file " + str(key_found) + " times, and the cert tags were resolved using a supplied file " + str(cert_found) + " times.\n") if (not cert_found == cert_count) or (not key_found == key_count): summary.append(" WARNING : The key or cert tags were not resolved by a supplied file for all occurrences. Some connections may not work.\n") else: if multiple_certs or multiple_keys: # Key and cert tags found with different file names, but no files supplied. Assume multiple files, user supplied addon.setSetting("user_def_keys", "Multiple") summary.append("Found key and cert tags with multiple filenames, but no key or certificate files were supplied. These will be requested during connection.\n") else: # Key and cert tags found with same file names, but no files supplied. Assume single file, user supplied addon.setSetting("user_def_keys", "Single") summary.append("Found key and cert tags all with the same filename, but no key or certificate files were supplied. These will be requested during connection.\n") if cert_count < len(ovpn_files) or key_count < len(ovpn_files): summary.append(" WARNING : The key tag was found " + str(key_count) + " times, and the cert tag was found " + str(cert_count) + " times. Expected to find one of each in all " + str(len(ovpn_files)) + " .ovpn files. Some connections may not work.\n") else: # Embedded key and certs found, so not asking user for them addon.setSetting("user_def_keys", "None") if (ekey_count > 0 or ecert_count > 0): if ekey_count == ecert_count and key_count == len(ovpn_files): summary.append("Using embedded user keys and certificates so keys and certs don't need to be entered.\n") else: summary.append(" WARNING : Using embedded user keys and certificates, but found " + str(ekey_count) + " keys and " + str(ecert_count) + " certificates in " + str(len(ovpn_files)) + " .ovpn files. There should be one of each in all .ovpn files otherwise some connections may not work.\n") else: summary.append("No user key or cert tags were found so assuming this type of authentication is not used.\n") # Report on how key passwords will be handled if key_pass_count > 0: if key_pass_found > 0: # Not using a password as resolved by file addon.setSetting("user_def_key_password", "false") summary.append("The askpass tag was found " + str(auth_count) + " times, but was resolved using a supplied file so the key password doesn't need to be entered.\n") if not key_pass_found == key_pass_count: summary.append(" WARNING : The askpass tag was found " + str(key_pass_count) + " times, but only resolved using a supplied file " + str(key_pass_found) + " times. Some connections may not work.\n") else: # Using a password as auth-user-pass tag was found addon.setSetting("user_def_key_password", "true") summary.append("The askpass tag was found " + str(key_pass_count) + " times so assuming key password authentication is used.\n") if key_pass_count < len(ovpn_files): summary.append(" WARNING : The askpass tag was only found in " + str(key_pass_count) + " .ovpn files, out of " + str(len(ovpn_files)) + ". Some connections may not work, or you may be asked to enter a password when it's not necessary.\n") else: # Not using a password as no askpass tag was found addon.setSetting("user_def_key_password", "false") summary.append("No askpass tag was found, so assuming key password is not needed.\n") # Report how many times each of the non .ovpn files were used i = 0 for oname in other_files: summary.append("File " + oname + " was found and used in .ovpn files " + str(other_files_count[i]) + " times.\n") if not other_files_count[i] == len(ovpn_files): if other_files_count[i] == 0: summary.append(" WARNING : " + oname + " was not used to update any .ovpn files and could be unused.\n") else: summary.append(" WARNING : The number of updates for " + oname + " was different to the number of .ovpn files, " + str(len(ovpn_files)) + ", which could be a problem.\n") i += 1 else: summary.append("None of the files were updated during import.\n") # Open a log file so all changes can be recorded without fouling up the kodi log log_name = getImportLogPath() if xbmcvfs.exists(log_name): xbmcvfs.delete(log_name) log_file = open(log_name, 'w') for line in summary: log_file.write(line) for line in detail: log_file.write(line) log_file.close() progress.close() xbmc.sleep(100) if success: if xbmcgui.Dialog().yesno(addon_name, "Import wizard finished. You should view the import log to review any issues, enter your user ID and password (if necessary) and then try and validate a VPN connection.", nolabel="OK", yeslabel="Import Log"): popupImportLog() else: xbmcgui.Dialog().ok(addon_name, errorMessage) return success
def connectVPN(connection_order, vpn_profile): # Don't know where this was called from so using plugin name to get addon handle addon = xbmcaddon.Addon("service.vpn.manager") addon_name = addon.getAddonInfo("name") # If we've not arrived here though the addon (because we've used the add-on setting # on the option menu), we want to surpress running the wizard as there's no need. addon.setSetting("vpn_wizard_run", "true") # Check openvpn installed and runs if not addon.getSetting("checked_openvpn") == "true": if checkVPNInstall(addon): addon.setSetting("checked_openvpn", "true") else: return if not addon.getSetting("ran_openvpn") == "true": stopVPN() if checkVPNCommand(addon): addon.setSetting("ran_openvpn", "true") else: return # The VPN protocol can be blank if this is a new run and the wizard is being used. # Force it to UDP as that's the most optimal and let them change in the settings. vpn_protocol = addon.getSetting("vpn_protocol") if vpn_protocol == "": addon.setSetting("vpn_protocol", "UDP") vpn_protocol = "UDP" # Do some stuff to set up text used in dialog windows connection_title = "" # Adjust strings below if changing number of conn_max if connection_order == "0" : connection_title = "" if connection_order == "1" : connection_title = " first" if connection_order == "2" : connection_title = " second" if connection_order == "3" : connection_title = " third" if connection_order == "4" : connection_title = " fourth" if connection_order == "5" : connection_title = " fifth" if connection_order == "6" : connection_title = " sixth" if connection_order == "7" : connection_title = " seventh" if connection_order == "8" : connection_title = " eighth" if connection_order == "9" : connection_title = " ninth" if connection_order == "10" : connection_title = " tenth" state = "" forceCycleLock() # Display a progress dialog box (put this on the screen quickly before doing other stuff) progress = xbmcgui.DialogProgress() progress_title = "Connecting to" + connection_title + " VPN." progress.create(addon_name,progress_title) debugTrace(progress_title) # Pause the monitor service progress_message = "Pausing VPN monitor." progress.update(1, progress_title, progress_message) if not stopService(): progress.close() # Display error result in an ok dialog errorTrace("common.py", "VPN monitor service is not running, can't start VPN") xbmcgui.Dialog().ok(progress_title, "Error, Service not running.\nCheck log and re-enable.") return if not progress.iscanceled(): progress_message = "VPN monitor paused." debugTrace(progress_message) progress.update(5, progress_title, progress_message) xbmc.sleep(500) # Stop any active VPN connection if not progress.iscanceled(): progress_message = "Stopping any active VPN connection." progress.update(6, progress_title, progress_message) stopVPNConnection() if not progress.iscanceled(): progress_message = "Disconnected from VPN." progress.update(10, progress_title, progress_message) xbmc.sleep(500) # Install the VPN provider existing_connection = "" if not progress.iscanceled(): vpn_provider = addon.getSetting("vpn_provider") # This is some code to copy the user name from a default file rather than use the user entered values. # It exists to help development where swapping between providers constantly is tedious. default_path = getUserDataPath(getVPNLocation(vpn_provider) + "/DEFAULT.txt") if connection_order == "1" and xbmcvfs.exists(default_path): default_file = open(default_path, 'r') default = default_file.readlines() default_file.close() default_value = default[0].strip(' \t\n\r') addon.setSetting("vpn_username", default_value) default_value = default[1].strip(' \t\n\r') addon.setSetting("vpn_password", default_value) # Reset the username/password if it's not being used if not usesPassAuth(vpn_provider): addon.setSetting("vpn_username", "") addon.setSetting("vpn_password", "") vpn_username = addon.getSetting("vpn_username") vpn_password = addon.getSetting("vpn_password") # Reset the setting indicating we've a good configuration for just this connection if not connection_order == "0": existing_connection = addon.getSetting(connection_order + "_vpn_validated") addon.setSetting(connection_order + "_vpn_validated", "") addon.setSetting(connection_order + "_vpn_validated_friendly", "") last_provider = addon.getSetting("vpn_provider_validated") last_credentials = addon.getSetting("vpn_username_validated") + " " + addon.getSetting("vpn_password_validated") if last_provider == "" : last_provider = "?" # Provider or credentials we've used previously have changed so we need to reset all validated connections vpn_credentials = vpn_username + " " + vpn_password if not last_provider == vpn_provider: last_credentials = "?" if not last_credentials == vpn_credentials: debugTrace("Credentials have changed since last time lthrough so need to revalidate") resetVPNConfig(addon, 1) # Generate or fix the OVPN files if we've not done this previously provider_gen = True if not progress.iscanceled(): if not ovpnFilesAvailable(getVPNLocation(vpn_provider)): # Fetch the list of locations available. If there are multiple, the user can select locations = getLocationFiles(getVPNLocation(vpn_provider)) default_label = "Default" i = 0 for location in locations: locations[i] = location[location.index("LOCATIONS")+10:location.index(".txt")] if locations[i] == "" : locations[i] = default_label i = i + 1 selected_profile = "" if len(locations) == 0: errorTrace("common.py", "No LOCATIONS.txt files found in VPN directory. Cannot generate ovpn files.") if len(locations) > 1: selected_location = xbmcgui.Dialog().select("Select connections profile", locations) selected_profile = locations[selected_location] if selected_profile == default_label : selected_profile = "" addon.setSetting("vpn_locations_list", selected_profile) progress_message = "Setting up VPN provider " + vpn_provider + "." progress.update(11, progress_title, progress_message) # Delete any old files in other directories debugTrace("Deleting all generated ovpn files") removeGeneratedFiles() # Generate new ones try: provider_gen = fixOVPNFiles(getVPNLocation(vpn_provider), selected_profile) except: errorTrace("Couldn't generate new .ovpn files") provider_gen = False xbmc.sleep(500) if provider_gen: if not progress.iscanceled(): progress_message = "Using VPN provider " + vpn_provider progress.update(15, progress_title, progress_message) xbmc.sleep(500) # Set up user credentials file if not progress.iscanceled() and usesPassAuth(vpn_provider): credentials_path = getCredentialsPath(addon) debugTrace("Attempting to use the credentials in " + credentials_path) if (not last_credentials == vpn_credentials) or (not xbmcvfs.exists(credentials_path)) or (not connectionValidated(addon)): progress_message = "Configuring authentication settings for user " + vpn_username + "." progress.update(16, progress_title, progress_message) provider_gen = writeCredentials(addon) got_keys = True keys_copied = True cancel_attempt = False cancel_clear = False if provider_gen: ovpn_name = "" if not progress.iscanceled(): if usesPassAuth(vpn_provider): progress_message = "Using authentication settings for user " + vpn_username + "." else: progress_message = "User authentication not used with " + vpn_provider + "." progress.update(19, progress_title, progress_message) xbmc.sleep(500) # Display the list of connections if not progress.iscanceled(): if not connection_order == "0": debugTrace("Displaying list of connections") all_connections = getProfileList(vpn_provider) ovpn_connections = getFilteredProfileList(all_connections, vpn_protocol, addon) ovpn_connections.sort() connections = getFriendlyProfileList(vpn_provider, ovpn_connections) if len(connections) > 0: if existing_connection == "": cancel_text = "[I]Cancel connection attempt[/I]" else: cancel_text = "[I]Cancel connection attempt and clear connection[/I]" cancel_clear = True connections.append(cancel_text) selected_connection = xbmcgui.Dialog().select("Select " + connection_title + " VPN profile", connections) # Based on the value selected, get the path name to the ovpn file ovpn_name = connections[selected_connection] if ovpn_name == cancel_text: ovpn_name = "" cancel_attempt = True else: ovpn_connection = ovpn_connections[selected_connection] else: ovpn_name = getFriendlyProfileName(vpn_provider, vpn_profile) ovpn_connection = vpn_profile if not progress.iscanceled() and not ovpn_name == "": # Fetch the key from the user if one is needed if usesUserKeys(getVPNLocation(vpn_provider)): # If a key already exists, skip asking for it if not (gotKeys(getVPNLocation(vpn_provider), ovpn_name)): # Stick out a helpful message if this is first time through if not gotKeys(getVPNLocation(vpn_provider), ""): xbmcgui.Dialog().ok(addon_name, vpn_provider + " provides unique key and certificate files to authenticate, typically called [I]client.key and client.crt[/I] or [I]user.key and user.crt[/I]. Make these files available on an accessable drive or USB key.") # Get the last directory browsed to avoid starting from the top start_dir = xbmcgui.Window(10000).getProperty("VPN_Manager_User_Directory") if usesSingleKey(getVPNLocation(vpn_provider)): select_title = "Select the user key file to use for all connections" else: select_title = "Select the user key file to use for this individual connection" key_file = xbmcgui.Dialog().browse(1, select_title, "files", ".key", False, False, start_dir, False) if key_file.endswith(".key"): start_dir = os.path.dirname(key_file) + getSeparator() if usesSingleKey(getVPNLocation(vpn_provider)): select_title = "Select the user certificate file to use for all connections" else: select_title = "Select the user certificate file to use for this individual connection" crt_file = xbmcgui.Dialog().browse(1, select_title, "files", ".crt", False, False, start_dir, False) if crt_file.endswith(".crt"): start_dir = os.path.dirname(crt_file) + getSeparator() xbmcgui.Window(10000).setProperty("VPN_Manager_User_Directory", start_dir) keys_copied = copyKeyAndCert(getVPNLocation(vpn_provider), ovpn_name, key_file, crt_file) got_keys = keys_copied else: got_keys = False else: got_keys = False # Try and connect to the VPN provider using the entered credentials if not progress.iscanceled() and not ovpn_name == "" and got_keys: progress_message = "Connecting using profile " + ovpn_name + "." debugTrace(progress_message) # Start the connection and wait a second before starting to check the state startVPN(ovpn_connection) i = 0 # Bad network takes over a minute to spot so loop for a bit longer (each loop is 2 seconds) loop_max = 38 if fakeConnection(): loop_max = 2 percent = 20 while i <= loop_max: progress.update(percent, progress_title, progress_message) xbmc.sleep(2000) state = getVPNConnectionStatus() if not (state == connection_status.UNKNOWN or state == connection_status.TIMEOUT) : break if progress.iscanceled(): break i = i + 1 percent = percent + 2 # Mess with the state to make it look as if we've connected to a VPN if fakeConnection() and not progress.iscanceled() and provider_gen and not ovpn_name == "" and got_keys: state = connection_status.CONNECTED # Determine what happened during the connection attempt if state == connection_status.CONNECTED : # Success, VPN connected! Display an updated progress window whilst we work out where we're connected to progress_message = "Connected, restarting VPN monitor." progress.update(97, progress_title, progress_message) # Set the final message to indicate success progress_message = "Connected, VPN monitor restarted." _, ip, country, isp = getIPInfo(addon) dialog_message = "Connected to a VPN in " + country + ".\nUsing profile " + ovpn_name + ".\nExternal IP address is " + ip + ".\nService Provider is " + isp + "." infoTrace("common.py", dialog_message) if ifDebug(): writeVPNLog() # Store that setup has been validated and the credentials used setVPNProfile(ovpn_connection) setVPNProfileFriendly(ovpn_name) if not connection_order == "0": addon.setSetting("vpn_provider_validated", vpn_provider) addon.setSetting("vpn_username_validated", vpn_username) addon.setSetting("vpn_password_validated", vpn_password) addon.setSetting(connection_order + "_vpn_validated", ovpn_connection) addon.setSetting(connection_order + "_vpn_validated_friendly", ovpn_name) setVPNState("started") setVPNRequestedProfile("") setVPNRequestedProfileFriendly("") setVPNLastConnectedProfile("") setVPNLastConnectedProfileFriendly("") setConnectionErrorCount(0) # Indicate to the service that it should update its settings updateService() elif progress.iscanceled() or cancel_attempt: # User pressed cancel. Don't change any of the settings as we've no idea how far we got # down the path of installing the VPN, configuring the credentials or selecting the connection # We're assuming here that if the VPN or user ID has been changed, then the connections are invalid # already. If the cancel happens during the connection validation, we can just use the existing one. # Set the final message to indicate user cancelled operation progress_message = "Cancelling connection attempt, restarting VPN monitor." progress.update(97, progress_title, progress_message) # Set the final message to indicate cancellation progress_message = "Cancelling connection attempt, VPN monitor restarted." # Restore the previous connection info dialog_message = "Cancelled connection attempt.\n" if not connection_order == "0": if not isVPNConnected(): if cancel_clear: dialog_message = dialog_message + "This connection has been removed from the list of valid connections." else: dialog_message = dialog_message + "This connection has not been validated." resetVPNConfig(addon, int(connection_order)) else: dialog_message = dialog_message + "Please reconnect." # Don't know how far we got, if we were trying to connect and then got cancelled, # there might still be an instance of openvpn running we need to kill stopVPN() else: # An error occurred, The current connection is already invalidated. The VPN credentials might # be ok, but if they need re-entering, the user must update them which will force a reset. progress_message = "Error connecting to VPN, restarting VPN monitor." progress.update(97, progress_title, progress_message) xbmc.sleep(500) # Set the final message to show an error occurred progress_message = "Error connecting to VPN, VPN monitor restarted." # First set of errors happened prior to trying to connect if not provider_gen: dialog_message = "Error creating OVPN or credentials file for provider.\nCheck log to determine cause of failure." elif not got_keys: if not keys_copied: dialog_message = "Failed to copy supplied user key and cert files.\nCheck log and retry." else: dialog_message = "User key and certificate files are required, but were not provided. Locate the files and try again." elif ovpn_name == "": dialog_message = "No unused VPN profiles were available for " + vpn_protocol + " protocol.\nChange VPN provider settings." else: # This second set of errors happened because we tried to connect and failed if state == connection_status.AUTH_FAILED: dialog_message = "Error connecting to VPN, authentication failed.\nCheck your username and password." credentials_path = getCredentialsPath(addon) if not connection_order == "0": addon.setSetting("vpn_username_validated", "") addon.setSetting("vpn_password_validated", "") elif state == connection_status.NETWORK_FAILED: dialog_message = "Error connecting to VPN, could not estabilish connection.\nCheck your username, password and network connectivity and retry." elif state == connection_status.TIMEOUT: dialog_message = "Error connecting to VPN, connection has timed out.\nTry using a different VPN profile or retry." else: dialog_message = "Error connecting to VPN, something unexpected happened.\nRetry to check openvpn operation and then check log." addon.setSetting("ran_openvpn", "false") # Output what when wrong with the VPN to the log writeVPNLog() if not connection_order == "0" : resetVPNConfig(addon, int(connection_order)) errorTrace("common.py", dialog_message) # The VPN might be having a spaz still so we want to ensure it's stopped stopVPN() # Restart service if not startService(): progress.close() errorTrace("common.py", "VPN monitor service is not running, VPN has started") dialog_message = "Error, Service not running.\nCheck log and reboot." else: # Close out the final progress dialog progress.update(100, progress_title, progress_message) xbmc.sleep(500) progress.close() freeCycleLock() # Display connection result in an ok dialog xbmcgui.Dialog().ok(progress_title, dialog_message) # Refresh the screen if this is not being done on settings screen if connection_order == "0" : xbmc.executebuiltin('Container.Refresh')
action = sys.argv[1] debugTrace("-- Entered managefiles.py with parameter " + action + " --") # Reset the ovpn files if action == "ovpn": if addon.getSetting("1_vpn_validated") == "" or xbmcgui.Dialog().yesno(addon_name, "Resetting the .ovpn files will reset all VPN connections. Connections must be re-validated before use.\nContinue?"): # Only used during development to create location files #generateAll() # Reset the connection before we do anything else resetVPNConnections(addon) debugTrace("Deleting all generated ovpn files") # Delete the ovpn files and the generated flag file. removeGeneratedFiles() # Remove any user/password files cleanPassFiles() xbmcgui.Dialog().ok(addon_name, "Deleted all .ovpn files. Validate a connection to recreate them.\n") # Copy the log file elif action == "log": log_path = "" dest_path = "" try: log_path = getLogPath() start_dir = "" dest_folder = xbmcgui.Dialog().browse(0, "Select folder to copy log file into", "files", "", False, False, start_dir, False) dest_path = "kodi " + datetime.datetime.now().strftime("%y-%m-%d %H-%M-%S") + ".log" dest_path = dest_folder + dest_path.replace(" ", "_")
def createUpdateChecker(): global flag fname = str(getAddonPath(True, vpn_provider + "/updatechecker.txt")) if os.path.isfile(fname): with open(fname, 'r+') as file: i = file.read() if i != timestr: try: removeGeneratedFiles() debugTrace("Removed") except Exception as e: print str(e) + ' on removing old ovpn files' try: updatePureResolver() debugTrace("Resolver Updated") except Exception as e: print str(e) + ' on updating resolver' try: checkLatestFailover() debugTrace("Failover Checked") except Exception as e: print str(e) + ' on checking failover' try: checkLatestCountries() debugTrace("Countries List Updated") except Exception as e: print str(e) + ' on updating counties list' try: checkLatestVersion() debugTrace("Latest Addon version checked") except Exception as e: print str(e) + ' on checking latest version' file.seek(0) file.truncate() file.write(timestr) debugTrace('file overwritten') else: debugTrace('No need to check now') file.close() else: try: removeGeneratedFiles() debugTrace("Removed") except Exception as e: print str(e) + ' on removing old ovpn files' try: updatePureResolver() debugTrace("Resolver Updated") except Exception as e: print str(e) + ' on updating resolver' try: checkLatestFailover() debugTrace("Failover Checked") except Exception as e: print str(e) + ' on checking failover' try: checkLatestCountries() debugTrace("Countries List Updated") except Exception as e: print str(e) + ' on updating counties list' try: checkLatestVersion() debugTrace("Latest Addon version checked") except Exception as e: print str(e) + ' on checking latest version' with open(fname, 'w') as file: file.write(timestr) file.close() debugTrace('file created and written') if flag == 1: debugTrace('yes') return True else: debugTrace('no') return False