def pexpect_ask_password(values): """ Interact with process when pexpect found a matching string for password question It may Ack previously entered password if several password are asked in the same run. This is a mirror from osx_stack.pexpect_ask_password """ process_question = values["child_result_list"][-1] try: for pattern, auth_realm in values["extra_args"]["auth_realms"]: if re.search(pattern, process_question): if values["extra_args"]["process_meta"].setdefault( "previous_auth_realm", None) == None: password_mistyped = False elif values["extra_args"]["process_meta"][ "previous_auth_realm"] != auth_realm: values["extra_args"]["key_chain"].ack_password( values["extra_args"]["process_meta"] ["previous_auth_realm"]) password_mistyped = False else: password_mistyped = True values["extra_args"]["process_meta"][ "previous_auth_realm"] = auth_realm return values["extra_args"]["key_chain"].get_password( auth_realm, password_mistyped) + "\n" except CancelOperationException: Output.verbose("Operation cancelled.") values["extra_args"]["process_meta"]["was_cancelled"] = True # Stop current process return True
def __init__(self, args): self.args = args self.key_chain = Key_Chain(self) self.returncode = None self.set_username(args) self.cfg = conf.get_config() Output.verbose(pprint.pformat(self.cfg)) self.networks_check = Networks_Check(self.cfg, self) self.networks_check.scan() self.entries = [] already_added = [] for m_name in self.cfg["global"].get("entries_order", ()): if m_name in self.cfg["CIFS_mount"]: entry = CIFS_Mount(self, self.cfg, m_name, self.key_chain) self.entries.append(entry) already_added.append(m_name) self.cfg["CIFS_mount"][m_name]["entry"] = entry else: Output.warning("Entry not found '{0}'.".format(m_name)) for m_name in self.cfg["CIFS_mount"]: if m_name not in already_added: entry = CIFS_Mount(self, self.cfg, m_name, self.key_chain) self.entries.append(entry) self.cfg["CIFS_mount"][m_name]["entry"] = entry os_check(self)
def open_file_manager(mount): def _cb(success, output, exit_code): pass path = mount.settings["Windows_letter"] cmd = [s.format(path=path) for s in WIN_CONST.CMD_OPEN.split(" ")] Output.verbose("cmd: " + " ".join(cmd)) NonBlockingQtProcess(cmd, _cb)
def cifs_umount(mount): def _cb(success, output, exit_code): if not success: mount.ui.notify_user("Umount failure :<br>{}".format(output)) cmd = [OSX_CONST.CMD_UMOUNT, "\"{local_path}\"".format(**mount.settings)] Output.verbose("cmd: " + " ".join(cmd)) NonBlockingQtProcess( cmd, _cb, )
def cifs_umount(mount): try: Output.verbose("Doing umount of {0}".format( mount.settings["Windows_letter"])) win32wnet.WNetCancelConnection2(mount.settings["Windows_letter"], 0, False) cifs_uncache_is_mounted(mount) except pywintypes.error as e: if e.winerror == 2401: # (2401, "WNetCancelConnection2", "There are open files on the connection.") mount.ui.notify_user(e.strerror) elif e.winerror == 2250: # (2250, 'WNetCancelConnection2', 'This network connection does not exist.') mount.ui.notify_user(e.strerror) else: Output.error("failed : {0}".format(e)) debug_send("umount:\n{0}".format(e))
def open_file_manager(mount): def _cb(success, output, exit_code): pass if (mount.settings["Linux_CIFS_method"] == "gvfs" and not mount.settings["Linux_gvfs_symlink"]): path = None for f in os.listdir(LIN_CONST.GVFS_DIR): if LIN_CONST.GVFS_GENERATION == 1: if re.match( r"{server_share} \S+ {server_name}".format( **mount.settings), f): path = os.path.join(LIN_CONST.GVFS_DIR, f, mount.settings["server_subdir"]) else: if (re.match(r"^smb-share:", f) and re.search( r"domain={realm_domain}(,|$)".format(**mount.settings), f, flags=re.IGNORECASE) and re.search( r"server={server_name}(,|$)".format( **mount.settings), f) and re.search( r"share={server_share}(,|$)".format( **mount.settings), f) and re.search( r"user={realm_username}(,|$)".format( **mount.settings), f)): path = os.path.join(LIN_CONST.GVFS_DIR, f, mount.settings["server_subdir"]) if path is None: raise Exception("Error: Could not find the GVFS mountpoint.") else: path = mount.settings["local_path"] if LIN_CONST.CMD_OPEN is None: Output.warning( "Cannot open location '{}', xdg-open not found.".format(path)) return cmd = [s.format(path=path) for s in LIN_CONST.CMD_OPEN.split(" ")] Output.verbose("cmd: " + " ".join(cmd)) NonBlockingQtProcess( cmd, _cb, )
def main_CLI(args): Output.verbose("*" * 10 + " " + str(datetime.datetime.now()) + " " + "*" * 10) Output.verbose("ENACdrives " + CONST.FULL_VERSION) Output.verbose("Detected OS : " + CONST.OS_DISTRIB + " " + CONST.OS_SYS + " " + CONST.OS_VERSION + "\n") Output.debug("LOCAL_USERNAME:"******"LOCAL_GROUPNAME:" + CONST.LOCAL_GROUPNAME) Output.debug("LOCAL_UID:" + str(CONST.LOCAL_UID)) Output.debug("LOCAL_GID:" + str(CONST.LOCAL_GID)) Output.debug("HOME_DIR:" + CONST.HOME_DIR) Output.debug("USER_CONF_FILE:" + CONST.USER_CONF_FILE) Output.debug("RESOURCES_DIR:" + CONST.RESOURCES_DIR + "\n") Output.debug("IMAGES_DIR:" + CONST.IMAGES_DIR + "\n") Output.debug("DEFAULT_MNT_DIR:" + CONST.DEFAULT_MNT_DIR + "\n") release_number_validation = validate_release_number() if release_number_validation == 'too old': Output.warning(CONST.NEED_TO_UPDATE_MSG) elif release_number_validation == 'newer': Output.normal(CONST.NEWER_THAN_PROD_MSG) if args.version: Output.cli("ENACdrives " + CONST.FULL_VERSION) sys.exit(0) ui = CLI(args) sys.exit(ui.run())
def load_config(self): self.cfg = conf.get_config() self.networks_check = Networks_Check(self.cfg, self) Output.verbose(pprint.pformat(self.cfg)) # Delete previous config for entry in self.entries: entry.destroy() self.entries = [] for msg in self.msgs: msg.destroy() self.msgs = [] # Instanciate new config objects entries_added = [] for entry_name in self.cfg["global"].get("entries_order", ()): if entry_name in self.cfg["CIFS_mount"]: entry = CIFS_Mount(self, self.cfg, entry_name, self.key_chain) self.entries.append(UI_Mount_Entry(self, entry)) entries_added.append(entry_name) else: Output.warning("Entry not found '{0}'.".format(entry_name)) for entry_name in self.cfg.get("CIFS_mount", {}): if entry_name not in entries_added: entry = CIFS_Mount(self, self.cfg, entry_name, self.key_chain) self.entries.append(UI_Mount_Entry(self, entry)) if CONST.OS_SYS == "Windows": self.windows_letter_manager.refresh_letters() for entry in self.entries: self.entries_layer.addLayout(entry) for msg in self.cfg["msg"]: msg_item = UI_Msg(self.cfg["msg"][msg]["text"], self.cfg["msg"][msg]["icon"]) self.msgs.append(msg_item) self.msgs_layout.addWidget(msg_item)
def main_GUI(): Output.verbose("*" * 10 + " " + str(datetime.datetime.now()) + " " + "*" * 10) Output.verbose("ENACdrives " + CONST.FULL_VERSION) Output.verbose("Detected OS : " + CONST.OS_DISTRIB + " " + CONST.OS_SYS + " " + CONST.OS_VERSION) Output.debug("LOCAL_USERNAME:"******"LOCAL_GROUPNAME:" + CONST.LOCAL_GROUPNAME) Output.debug("LOCAL_UID:" + str(CONST.LOCAL_UID)) Output.debug("LOCAL_GID:" + str(CONST.LOCAL_GID)) Output.debug("HOME_DIR:" + CONST.HOME_DIR) Output.debug("USER_CONF_FILE:" + CONST.USER_CONF_FILE) Output.debug("RESOURCES_DIR:" + CONST.RESOURCES_DIR) Output.debug("IMAGES_DIR:" + CONST.IMAGES_DIR + "\n") Output.debug("DEFAULT_MNT_DIR:" + CONST.DEFAULT_MNT_DIR + "\n") Output.br() app = QtWidgets.QApplication(sys.argv) ui = GUI() sys.exit(app.exec_())
def cifs_mount(mount): # 1) Make mountpoint if not os.path.exists(mount.settings["local_path"]): try: os.makedirs(mount.settings["local_path"]) except OSError: pass if not os.path.isdir(mount.settings["local_path"]): raise Exception("Error while creating dir : %s" % mount.settings["local_path"]) # 2) Mount s_path = re.sub(r" ", r"%20", mount.settings["server_path"]) cmd = [ OSX_CONST.CMD_MOUNT_SMBFS, r"//{realm_domain}\;{realm_username}@{server_name}/{s_path}".format( s_path=s_path, **mount.settings), "\"{local_path}\"".format(**mount.settings) ] Output.verbose("cmd: " + " ".join(cmd)) for _ in range(3): # 3 attempts (for passwords mistyped) process_meta = { "was_cancelled": False, } try: (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "(?i)password": pexpect_ask_password, }, extra_args={ "auth_realms": [(r"Password", mount.settings["realm"])], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.MOUNT_TIMEOUT, ) except pexpect.ExceptionPexpect as e: raise Exception("Error while mounting : %s" % e.value) if exit_status == 0: mount.key_chain.ack_password(mount.settings["realm"]) return True elif exit_status == 77: # Bad password mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) else: mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) if process_meta["was_cancelled"]: if (os.path.isdir(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): try: os.rmdir(mount.settings["local_path"]) except OSError as e: Output.warning("Could not rmdir : {}".format(e)) return False else: mount.ui.notify_user("Mount failure :<br>{}".format(output)) return False mount.ui.notify_user("Mount failure")
def cifs_umount(mount): def _cb_gvfs(success, output, exit_code): if not success: mount.ui.notify_user("Umount failure :<br>{}".format(output)) cifs_uncache_is_mounted(mount) if mount.settings["Linux_CIFS_method"] == "gvfs": # gvfs umount apparently never locks on open files. # 1) Umount share = re.sub(r" ", r"%20", mount.settings["server_share"]) if LIN_CONST.GVFS_GENERATION <= 3: cmd = [ LIN_CONST.CMD_GVFS_MOUNT, "-u", r"smb://{realm_domain};{realm_username}@{server_name}/{share}". format(share=share, **mount.settings) ] else: cmd = [ LIN_CONST.CMD_GIO_MOUNT, "mount", "-u", r"smb://{realm_domain};{realm_username}@{server_name}/{share}". format(share=share, **mount.settings) ] Output.verbose("cmd: " + " ".join(cmd)) if mount.ui.UI_TYPE == "GUI": NonBlockingQtProcess( cmd, _cb_gvfs, env=dict(os.environ, LANG="C", LC_ALL="C", LANGUAGE="C"), ) else: _cb_gvfs(**BlockingProcess.run( cmd, env=dict(os.environ, LANG="C", LC_ALL="C", LANGUAGE="C"), )) else: # "mount.cifs" # 1) uMount cmd = [LIN_CONST.CMD_UMOUNT, "{local_path}"] if CONST.LOCAL_UID != 0: cmd.insert(0, "sudo") cmd = [s.format(**mount.settings) for s in cmd] Output.verbose("cmd: " + " ".join(cmd)) # for i in xrange(3): # 3 attempts (for passwords mistyped) process_meta = { "was_cancelled": False, } (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "(?i)password": pexpect_ask_password, }, extra_args={ "auth_realms": [ (r"\[sudo\] password", "sudo"), ], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.UMOUNT_TIMEOUT, ) if exit_status == 0: mount.key_chain.ack_password("sudo") else: if process_meta["was_cancelled"]: mount.key_chain.invalidate_if_no_ack_password("sudo") elif "device is busy" in output: mount.key_chain.ack_password("sudo") mount.ui.notify_user("Umount failure: Device is busy.") return False else: mount.key_chain.invalidate_if_no_ack_password("sudo") mount.ui.notify_user("Umount failure") return False
def cifs_mount(mount): if mount.settings["Linux_CIFS_method"] == "gvfs": # 1) Remove broken symlink or empty dir if mount.settings["Linux_gvfs_symlink"]: if (os.path.lexists(mount.settings["local_path"]) and not os.path.exists(mount.settings["local_path"])): os.unlink(mount.settings["local_path"]) if (os.path.isdir(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): os.rmdir(mount.settings["local_path"]) if os.path.exists(mount.settings["local_path"]): mount.ui.notify_user("Error : Path {} already exists".format( mount.settings["local_path"])) return False # 2) Mount share = re.sub(r" ", r"%20", mount.settings["server_share"]) if LIN_CONST.GVFS_GENERATION <= 3: cmd = [ LIN_CONST.CMD_GVFS_MOUNT, r"smb://{realm_domain}\;{realm_username}@{server_name}/{share}" .format(share=share, **mount.settings) ] else: cmd = [ LIN_CONST.CMD_GIO_MOUNT, "mount", r"smb://{realm_domain}\;{realm_username}@{server_name}/{share}" .format(share=share, **mount.settings) ] Output.verbose("cmd: " + " ".join(cmd)) process_meta = { "was_cancelled": False, } try: (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "Password:"******"auth_realms": [(r"Password:"******"realm"])], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.MOUNT_TIMEOUT, ) except pexpect.ExceptionPexpect as exc: mount.ui.notify_user("Error while mounting :<br>{}".format( exc.value)) return False if "error" not in output.lower() and exit_status == 0: mount.key_chain.ack_password(mount.settings["realm"]) else: mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) if process_meta["was_cancelled"]: return False else: mount.ui.notify_user("Mount failure :<br>{}".format(output)) return False cifs_uncache_is_mounted(mount) else: # "mount.cifs" if LIN_CONST.CMD_MOUNT_CIFS is None: mount.ui.notify_user( "Error missing binary <b>mount.cifs</b>. On Ubuntu you can install it with <i>sudo apt-get install cifs-utils</i>" ) return False # 1) Make mount dir (remove broken symlink if needed) if (os.path.lexists(mount.settings["local_path"]) and not os.path.exists(mount.settings["local_path"])): os.unlink(mount.settings["local_path"]) if not os.path.exists(mount.settings["local_path"]): try: os.makedirs(mount.settings["local_path"]) except OSError: pass if (os.path.islink(mount.settings["local_path"]) or not os.path.isdir(mount.settings["local_path"])): mount.ui.notify_user("Error while creating dir : %s" % mount.settings["local_path"]) return False # 2) Mount s_path = re.sub(" ", "\\ ", mount.settings["server_path"]) cmd = [ LIN_CONST.CMD_MOUNT_CIFS, "//{server_name}/{s_path}", "{local_path}", "-o", "user={realm_username},domain={realm_domain}," "uid={local_uid},gid={local_gid}," "file_mode={Linux_mountcifs_filemode}," "dir_mode={Linux_mountcifs_filemode}," "{Linux_mountcifs_options}" ] if CONST.LOCAL_UID != 0: cmd.insert(0, "sudo") cmd = [s.format(s_path=s_path, **mount.settings) for s in cmd] Output.verbose("cmd: " + " ".join(cmd)) # for i in xrange(3): # 3 attempts (for passwords mistyped) process_meta = { "was_cancelled": False, } (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "(?i)password": pexpect_ask_password, }, extra_args={ "auth_realms": [(r"\[sudo\] password", "sudo"), (r"Password", mount.settings["realm"])], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.MOUNT_TIMEOUT, ) if exit_status == 0: mount.key_chain.ack_password("sudo") mount.key_chain.ack_password(mount.settings["realm"]) else: mount.key_chain.invalidate_if_no_ack_password("sudo") mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) if process_meta["was_cancelled"]: if (os.path.exists(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): try: os.rmdir(mount.settings["local_path"]) except OSError as e: Output.warning("Could not rmdir : {0}".format(e)) else: mount.ui.notify_user("Mount failure : {}".format(output)) return False return True
def cifs_mount(mount): remote = r"\\{server_name}\{server_path}".format(**mount.settings) local = mount.settings["Windows_letter"] Output.normal("remote={}\nlocal={}".format(remote, local)) # 1st attempt without password try: Output.verbose("1st attempt without password") win32wnet.WNetAddConnection2( win32netcon.RESOURCETYPE_DISK, local, remote, ) Output.verbose("succeeded") cifs_uncache_is_mounted(mount) return True except pywintypes.error as e: if e.winerror == 5: # (5, 'WNetAddConnection2', 'Access is denied.') pass elif e.winerror == 86: # (86, "WNetAddConnection2", "The specified network password is not correct.") pass elif e.winerror == 1326: # (1326, "WNetAddConnection2", "Logon failure: unknown user name or bad password.") pass elif e.winerror == 31: # (31, 'WNetAddConnection2', 'A device attached to the system is not functioning.') pass elif e.winerror == 53: # (53, 'WNetAddConnection2', 'The network path was not found.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 55: # (55, 'WNetAddConnection2', 'The specified network resource or device is no longer available.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 64: # (64, 'WNetAddConnection2', 'Le nom réseau spécifié n’est plus disponible.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 67: # (67, 'WNetAddConnection2', 'The network name cannot be found.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 71: # (71, 'WNetAddConnection2', 'No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 85: # (85, 'WNetAddConnection2', 'The local device name is already in use.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 121: # (121, 'WNetAddConnection2', 'The semaphore timeout period has expired.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1202: # (1202, 'WNetAddConnection2', 'The local device name has a remembered connection to another network resource.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1208: # (1208, 'WNetAddConnection2', 'An extended error has occurred.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1219: # (1219, 'WNetAddConnection2', 'Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1222: # (1222, 'WNetAddConnection2', 'The network is not present or not started.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1265: # (1265, 'WNetAddConnection2', 'The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1272: # (1272, 'WNetAddConnection2', "You can't access this shared folder because your organization's security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.") mount.ui.notify_user(e.strerror) return False elif e.winerror == 1311: # (1311, 'WNetAddConnection2', 'There are currently no logon servers available to service the logon request.') # (1311, 'WNetAddConnection2', "We can't sign you in with this credential because your domain isn't available. Make sure your device is connected to your organization's network and try again. If you previously signed in on this device with another credential, you can sign in with that credential.") mount.ui.notify_user(e.strerror) return False elif e.winerror == 1331: # (1331, 'WNetAddConnection2', "This user can't sign in because this account is currently disabled.") mount.ui.notify_user(e.strerror) return False elif e.winerror == 1907: # (1907, 'WNetAddConnection2', "The user's password must be changed before signing in.") pass else: Output.error("failed : {0}".format(e)) debug_send("mount without password:\n{0}".format(e)) # 2nd attempt with password wrong_password = False for _ in range(3): try: pw = mount.key_chain.get_password(mount.settings["realm"], wrong_password) wrong_password = False Output.verbose("New attempt with password") win32wnet.WNetAddConnection2( win32netcon.RESOURCETYPE_DISK, local, remote, None, r"{0}\{1}".format(mount.settings["realm_domain"], mount.settings["realm_username"]), pw, 0) mount.key_chain.ack_password(mount.settings["realm"]) Output.verbose("succeeded") cifs_uncache_is_mounted(mount) return True except pywintypes.error as e: if e.winerror == 86: # (86, "WNetAddConnection2", "The specified network password is not correct.") mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) wrong_password = True elif e.winerror == 1326: # (1326, "WNetAddConnection2", "Logon failure: unknown user name or bad password.") mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) wrong_password = True elif e.winerror == 5: # (5, 'WNetAddConnection2', 'Access is denied.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 31: # (31, 'WNetAddConnection2', 'A device attached to the system is not functioning.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 53: # (53, 'WNetAddConnection2', 'The network path was not found.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 55: # (55, 'WNetAddConnection2', 'The specified network resource or device is no longer available.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 64: # (64, 'WNetAddConnection2', 'Le nom réseau spécifié n’est plus disponible.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 67: # (67, 'WNetAddConnection2', 'The network name cannot be found.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 71: # (71, 'WNetAddConnection2', 'No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 85: # (85, 'WNetAddConnection2', 'The local device name is already in use.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 121: # (121, 'WNetAddConnection2', 'The semaphore timeout period has expired.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1202: # (1202, 'WNetAddConnection2', 'The local device name has a remembered connection to another network resource.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1208: # (1208, 'WNetAddConnection2', 'An extended error has occurred.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1219: # (1219, 'WNetAddConnection2', 'Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1222: # (1222, 'WNetAddConnection2', 'The network is not present or not started.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1265: # (1265, 'WNetAddConnection2', 'The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you.') mount.ui.notify_user(e.strerror) return False elif e.winerror == 1272: # (1272, 'WNetAddConnection2', "You can't access this shared folder because your organization's security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.") mount.ui.notify_user(e.strerror) return False elif e.winerror == 1311: # (1311, 'WNetAddConnection2', 'There are currently no logon servers available to service the logon request.') # (1311, 'WNetAddConnection2', "We can't sign you in with this credential because your domain isn't available. Make sure your device is connected to your organization's network and try again. If you previously signed in on this device with another credential, you can sign in with that credential.") mount.ui.notify_user(e.strerror) return False elif e.winerror == 1331: # (1331, 'WNetAddConnection2', "This user can't sign in because this account is currently disabled.") mount.ui.notify_user(e.strerror) return False elif e.winerror == 1907: # (1907, 'WNetAddConnection2', "The user's password must be changed before signing in.") mount.ui.notify_user(e.strerror) return False else: Output.error("failed : {0}".format(e)) debug_send("mount with password:\n{0}".format(e)) mount.ui.notify_user(e.strerror) except CancelOperationException: Output.verbose("Operation cancelled.") return False return False
def get_config(): # Create cache_dir if not already existent if not os.path.exists(CONST.USER_CACHE_DIR): os.makedirs(CONST.USER_CACHE_DIR) # HARD CODED CONFIG default_config = { 'global': { 'Linux_CIFS_method': 'gvfs', 'Linux_gvfs_symlink': False, 'Linux_mountcifs_dirmode': '0770', 'Linux_mountcifs_filemode': '0770', 'Linux_mountcifs_options': 'rw,nobrl,noserverino,iocharset=utf8,sec=ntlm'}, 'CIFS_mount': {}, 'network': {}, 'realm': {}, 'msg': {}, } cfg = default_config # USER CONFIG -> get only username from [global] user_config = None username = None try: with open(CONST.USER_CONF_FILE, "r") as f: user_config = read_config_source(f) username = user_config.get("global", {}).get("username", None) if username is not None: Output.verbose("Loaded username '{}' from User context. ({})".format(username, CONST.USER_CONF_FILE)) else: Output.normal("Username not found in User context. ({})".format(CONST.USER_CONF_FILE)) except FileNotFoundException: Output.normal("Username not found in User context. ({})".format(CONST.USER_CONF_FILE)) if username is None: if CONST.AD_USERNAME is not None: username = CONST.AD_USERNAME Output.verbose("Loaded username '{}' from environment variables (user in domain '{}').".format(username, CONST.AD_DOMAIN)) # Save to config file and reload it for after save_username(username) with open(CONST.USER_CONF_FILE, "r") as f: user_config = read_config_source(f) else: Output.normal("Username not found in environment variables (user not in a domain).") # ENACDRIVE SERVER CONFIG (included cache function) if username is not None: config_url = CONST.CONFIG_URL.format(username=username) cache_filename = os.path.join(CONST.USER_CACHE_DIR, hashlib.md5(config_url.encode()).hexdigest()) try: with urllib.request.urlopen(config_url, timeout=CONST.URL_TIMEOUT) as response: lines = [bytes_decode(l) for l in response.readlines()] # Output.debug("get_config {} : {}".format(config_url, lines)) s_io = io.StringIO("".join(lines)) enacdrives_config = read_config_source(s_io) merge_configs(cfg, enacdrives_config) s_io.seek(0) with open(cache_filename, "w") as f: f.writelines(s_io.readlines()) Output.verbose("Loaded config from ENACdrives server ({})".format(config_url)) except (socket.timeout, urllib.error.URLError, ConfigException) as e: Output.warning("Could not load config ENACdrives server. ({})".format(config_url)) Output.warning("Got error : {}".format(e)) try: with open(cache_filename, "r") as f: cached_config = read_config_source(f) merge_configs(cfg, cached_config) Output.normal("Loaded config from cache file. ({})".format(cache_filename)) except FileNotFoundException: Output.warning("Could not load config from cache file. ({})".format(cache_filename)) else: Output.normal("Skipping config from ENACdrives server (no username).") # SYSTEM CONFIG try: with open(CONST.SYSTEM_CONF_FILE, "r") as f: system_config = read_config_source(f) merge_configs(cfg, system_config) Output.verbose("Loaded config from System context. ({})".format(CONST.SYSTEM_CONF_FILE)) except FileNotFoundException: Output.normal("No config found from System context. ({})".format(CONST.SYSTEM_CONF_FILE)) # USER CONFIG if user_config is not None: merge_configs(cfg, user_config) Output.verbose("Loaded config from User context. ({})".format(CONST.USER_CONF_FILE)) else: Output.normal("No config found from User context. ({})".format(CONST.USER_CONF_FILE)) cfg = validate_config(cfg) return cfg
def save_windows_letter(section_name, letter): """ Parse config file and change/add only what is necessary """ lines = ["", ] try: with open(CONST.USER_CONF_FILE, "r") as f: lines = f.readlines() # Parse file, search for name = section_name in [CIFS_mount] line_nb = -1 good_section_name = False letter_w_no_section_name_line_nb = None skip_this_section = True section_name_line_nb = None option_line_nb = None for l in lines: line_nb += 1 if l.startswith("["): good_section_name = False letter_w_no_section_name_line_nb = None try: current_section = re.match(r"\[(\S+)\]$", l).groups()[0] if current_section == "CIFS_mount": skip_this_section = False except AttributeError: skip_this_section = True continue if skip_this_section: continue try: k, v = re.match(r"([^=]*)=(.*)", l).groups() k, v = k.strip(), v.strip() except AttributeError: continue if k == "name": if v == section_name: good_section_name = True if letter_w_no_section_name_line_nb is not None: option_line_nb = letter_w_no_section_name_line_nb break if section_name_line_nb is None: section_name_line_nb = line_nb else: skip_this_section = True continue elif k == "Windows_letter": if good_section_name: option_line_nb = line_nb break else: # Unknown name=xyz yet letter_w_no_section_name_line_nb = line_nb # Windows_letter found in config file if option_line_nb is not None: Output.verbose("Changing {}'s Windows_letter='{}' in config file {}".format(section_name, letter, CONST.USER_CONF_FILE)) lines[option_line_nb] = "Windows_letter = {}\n".format(letter) # Windows_letter not found, but [CIFS_mount] found elif section_name_line_nb is not None: Output.verbose("Saving {}'s Windows_letter='{}' in config file {}".format(section_name, letter, CONST.USER_CONF_FILE)) lines.insert(section_name_line_nb+1, "Windows_letter = {}\n".format(letter)) # [CIFS_mount] not found else: Output.verbose("Saving {}'s Windows_letter='{}' in config file {}".format(section_name, letter, CONST.USER_CONF_FILE)) lines.append("[CIFS_mount]\n") lines.append("name = {}\n".format(section_name)) lines.append("Windows_letter = {}\n".format(letter)) lines.append("\n") except FileNotFoundException: Output.verbose("Saving {}'s Windows_letter='{}' to new config file {}".format(section_name, letter, CONST.USER_CONF_FILE)) lines.append("[CIFS_mount]\n") lines.append("name = {}\n".format(section_name)) lines.append("Windows_letter = {}\n".format(letter)) lines.append("\n") with open(CONST.USER_CONF_FILE, "w") as f: f.writelines(lines)
def save_username(username): """ Parse config file and change/add only what is necessary """ lines = ["", ] try: with open(CONST.USER_CONF_FILE, "r") as f: lines = f.readlines() # Parse file, search for username = xxx in [global] current_section = None line_nb = -1 global_section_line_nb = None username_line_nb = None for l in lines: line_nb += 1 if l.startswith("["): try: current_section = re.match(r"\[(\S+)\]$", l).groups()[0] if current_section == "global" and global_section_line_nb is None: global_section_line_nb = line_nb except AttributeError: current_section = None continue if current_section != "global": continue try: k, v = re.match(r"([^=]*)=(.*)", l).groups() k, v = k.strip(), v.strip() except AttributeError: continue if k == "username": username_line_nb = line_nb break # username found in config file if username_line_nb is not None: Output.verbose("Changing to username='******' in config file {}".format(username, CONST.USER_CONF_FILE)) lines[username_line_nb] = "username = {}\n".format(username) # username not found, but [global] found elif global_section_line_nb is not None: Output.verbose("Saving username='******' in config file {}".format(username, CONST.USER_CONF_FILE)) lines.insert(global_section_line_nb+1, "username = {}\n".format(username)) # [global] not found else: Output.verbose("Saving username='******' in config file {}".format(username, CONST.USER_CONF_FILE)) lines.insert(0, "[global]\n") lines.insert(1, "username = {}\n".format(username)) lines.insert(2, "\n") except FileNotFoundException: Output.verbose("Saving username='******' to new config file {}".format(username, CONST.USER_CONF_FILE)) lines.insert(0, "[global]\n") lines.insert(1, "username = {}\n".format(username)) lines.insert(2, "\n") with open(CONST.USER_CONF_FILE, "w") as f: f.writelines(lines)