def remove_directory_recursive(self, path): """ Function Type : Success """ try: shutil.rmtree(path) except (IOError, OSError), err: if err.errno == errno.EACCES: raise PermissionDeniedError("Could not remove directory %s" % path) raise err
def get_file_content(self, filename, as_admin=False, admin_password=None): if self.ssh: # Supposedly in Windows, sshd account has admin privileges, so as_admin can be ignored try: return self.ssh.get_contents(filename) except IOError, exc: if exc.errno == errno.EACCES: raise PermissionDeniedError( "Permission denied attempting to read file %s" % filename)
def create_directory_recursive(self, path): """ Function Type : Success """ try: os.makedirs(path) except (IOError, OSError), err: if err.errno == errno.EACCES: raise PermissionDeniedError("Could not create directory %s" % path) raise
def delete_file(self, path): """ Function Type : Success """ try: os.remove(path) except (IOError, OSError), err: if err.errno == errno.EACCES: raise PermissionDeniedError("Could not delete file %s" % path) raise err
def remove_directory(self, path): """ Function Type : Success """ try: os.rmdir(path) except (IOError, OSError) as err: if err.errno == errno.EACCES: raise PermissionDeniedError("Could not remove directory %s" % path) raise err
def save_file_content_and_backup(self, path, content, backup_extension, as_admin=False, admin_password=None): # Check if dir, where config file will be stored is writable dirname, filename = splitpath(path) if not as_admin and not self.is_dir_writable(dirname.strip(" \r\t\n")): raise PermissionDeniedError("Cannot write to directory %s" % dirname) if self.ssh is not None: ## Get home dir for using as tmpdir homedir, status = self.process_ops.get_cmd_output("echo ~") if type(homedir) is unicode: homedir = homedir.encode("utf8") if type(homedir) is str: homedir = homedir.strip(" \r\t\n") else: homedir = None dprint_ex(2, "Got home dir", homedir) if not homedir: raise Exception("Unable to get path for remote home directory") tmpfilename = homedir + "/.wba.temp" dprint_ex( 1, "Remotely writing contents to temporary file %s" % tmpfilename) dprint_ex(3, content) self.ssh.set_contents(tmpfilename, content) if backup_extension: dprint_ex(1, "Backing up %s" % path) backup_cmd = "/bin/cp " + quote_path(path) + " " + quote_path( path + backup_extension) self.process_ops.exec_cmd(backup_cmd, as_admin, admin_password) copy_to_dest = "/bin/cp " + quote_path( tmpfilename) + " " + quote_path(path) delete_tmp = "/bin/rm " + quote_path(tmpfilename) dprint_ex(1, "Copying file to final destination: %s" % copy_to_dest) self.process_ops.exec_cmd(copy_to_dest, as_admin, admin_password) dprint_ex(1, "Deleting tmp file: %s" % delete_tmp) self.process_ops.exec_cmd(delete_tmp) else: raise Exception("No SSH session active, cannot save file remotely")
def copy_file(self, source, target, target_backup = ""): """ Function Type : Success """ try: # Does a backup if it was required if target_backup: shutil.copy(target, target_backup) shutil.copy(source, target) except (IOError, OSError), e: if e.errno == errno.EACCES: raise PermissionDeniedError("Can't copy %s to %s" % (source, target)) raise
def async_refresh(self, callback): # get list of privileges that actually exist if not self.schema_privilege_names: try: result = self.ctrl_be.exec_query("DESCRIBE mysql.db") except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the used account has rights to the MySQL grant tables.\n%s"%e) raise e if result is not None: while result.nextRow(): field= result.stringByName("Field") if field.endswith("_priv"): self.schema_privilege_names.append(field)
def get_file_content(self, filename, as_admin=False, admin_password=None): cont = [] if as_admin: # TODO: Implement raise NotImplementedError else: try: f = open(filename, 'r') except OSError, e: if e.errno == errno.EACCES: raise PermissionDeniedError("Can't open file '%s'" % filename) raise e cont = f.read() f.close()
def async_refresh(self, callback): # Get the list of privileges supported by the version of MySQL Server we are connected to: if not self.schema_privilege_names: try: result = self.ctrl_be.exec_query("DESCRIBE mysql.db") except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the account used has rights to the MySQL grant tables.\n%s" % e) raise e if result is not None: while result.nextRow(): field= result.stringByName("Field") if field.endswith("_priv"): self.schema_privilege_names.append(field)
def _copy_file(self, source, dest, as_admin=False, admin_password=None): # not used externally if not as_admin: try: shutil.copy(source, dest) except OSError, e: if e.errno == errno.EACCES: raise PermissionDeniedError("Can't copy %s to %s" % (source, dest)) elif e.errno == errno.ENOENT: raise InvalidPathError("File not found: %s" % source) raise
def get_file_lines(self, path, skip, output_handler): try: f = open(path, 'r') skipped = 0 for line in f: if not skip or skipped == skip: output_handler(line) else: skipped = skipped + 1 f.close() except (IOError, OSError), e: if e.errno == errno.EACCES: raise PermissionDeniedError("Can't open file '%s'" % path) raise
def get_file_content(self, filename, as_admin=False, admin_password=None): # may raise IOError if self.ssh: if as_admin: #TODO raise Exception("Read file as admin not supported") else: try: return self.ssh.get_contents(filename) except IOError, exc: if exc.errno == errno.EACCES: raise PermissionDeniedError( "Permission denied attempting to read file %s" % filename)
def list_dir(self, path, include_size, output_handler): try: # This is needed on the SudoTail class if os.path.isfile(path): if include_size: stat_info = os.stat(path) stat_info.st_size line = "%i %s" % (stat_info.st_size, path) output_handler(line) else: output_handler(path) else: dlist = os.listdir(path) for item in dlist: line = "" item_path = os.path.join(path, item) stat_info = os.stat(item_path) item_stat = stat_info.st_mode if stat.S_ISDIR(item_stat): item += '/' if include_size: line = "%s %s" % (str(stat_info.st_size), item) else: line = item elif stat.S_ISREG(item_stat) or stat.S_ISLNK(item_stat): if include_size: line = "%s %s" % (str(stat_info.st_size), item) else: line = item if line: output_handler(line) except (IOError, OSError), e: if e.errno == errno.EACCES: raise PermissionDeniedError("Permission denied accessing %s" % path) raise
def listdir( self, path ): # base operation to build file_exists and remote file selector dirlist = [] try: _path = path dlist = os.listdir(_path) mod = "" for item in dlist: _path = os.path.join(path, item) item_stat = os.stat(_path) if stat.S_ISDIR(item_stat): dirlist.insert(0, item + '/') elif stat.S_ISREG(item_stat) or stat.S_ISLNK(item_stat): dirlist.append(item) except OSError, e: if e.errno == errno.EACCES: raise PermissionDeniedError("Permission denied accessing %s" % _path) elif e.errno == errno.ENOENT: raise InvalidPathError("Path not found: %s" % _path) raise
def save(self): if self.password != self.confirm_password: raise WBSecurityValidationError( "The new password and its confirmation don't match. Please re-enter them." ) #if not self.username: # raise WBSecurityValidationError("Username must not be blank") if not self.host: raise WBSecurityValidationError("Host name must not be blank") # check if username + host is duplicated if self.is_commited and (self.username != self._orig_username or self.host != self._orig_host): if (self.username, self.host) in self._owner.account_names: raise WBSecurityValidationError( "The '%s' account already exists and cannot be saved." % (self.formatted_name())) elif not self.is_commited: if self._owner.account_names.count((self.username, self.host)) > 1: raise WBSecurityValidationError( "The '%s' account already exists and cannot be saved." % (self.formatted_name())) fields = { "old_user": escape_sql_string(self._orig_username) if self._orig_username else self._orig_username, "old_host": escape_sql_string(self._orig_host) if self._orig_host else self._orig_host, "user": escape_sql_string(self.username) or "NULL", "host": escape_sql_string(self.host) or "", "password": escape_sql_string(self.password or self._orig_password or ""), "auth_plugin": escape_sql_string(self.auth_plugin) if self.auth_plugin else None, "auth_string": escape_sql_string(self.auth_string) if self.auth_string else None } if self.is_commited: assert self._orig_username is not None and self._orig_host is not None assignments = [] for priv in self._owner.global_privilege_names: if priv in self._global_privs: assignments.append("%s='%s'" % (priv, 'Y')) else: assignments.append("%s='%s'" % (priv, 'N')) for limit in ["max_questions", "max_updates", "max_connections" ] + (self._owner.has_max_user_connections and ["max_user_connections"] or []): assignments.append("%s='%s'" % (limit, getattr(self, limit))) if self._orig_username != self.username: assignments.append("User='******'" % escape_sql_string(self.username)) if self.auth_plugin: if self._orig_auth_string != self.auth_string: assignments.append("authentication_string='%s'" % escape_sql_string(self.auth_string)) else: if self._orig_host != self.host: assignments.append("Host='%s'" % escape_sql_string(self.host)) if self.password: assignments.append("Password=password('%s')" % escape_sql_string(self.password)) fields["assignments"] = ", ".join(assignments) query = UPDATE_ACCOUNT_QUERY % fields try: self._owner.ctrl_be.exec_sql(query) except QueryError, e: if e.error == 1142: raise PermissionDeniedError( "Error updating account %s@%s: Insufficient rights to perform operation" % (self.username, self.host)) else: raise Exception("Error updating account %s@%s: %s" % (self.username, self.host, e)) except Exception, e: raise Exception("Error updating account %s@%s: %s" % (self.username, self.host, e))
def save_file_content_and_backup(self, path, content, backup_extension, as_admin=False, admin_password=None): # Check if dir, where config file will be stored is writable dirname, filename = splitpath(path) if not as_admin and not self.is_dir_writable(dirname.strip(" \r\t\n")): raise PermissionDeniedError("Cannot write to directory %s" % dirname) if self.ssh is not None: ## Get temp dir for using as tmpdir tmpdir, status = self.process_ops.get_cmd_output("echo %temp%") if type(tmpdir) is unicode: tmpdir = tmpdir.encode("utf8") if type(tmpdir) is str: tmpdir = tmpdir.strip(" \r\t\n") if tmpdir[1] == ":": tmpdir = tmpdir[2:] else: dprint_ex( 1, "Temp directory path '" + tmpdir + " is not in expected form. The expected for is something like 'C:\\Windows\\Temp'" ) tmpdir = None dprint_ex(2, "Got temp dir", tmpdir) else: tmpdir = None if not tmpdir: tmpdir = dirname tmpfilename = tmpdir + r"\workbench-temp-file.ini" dprint_ex( 1, "Remotely writing contents to temporary file %s" % tmpfilename) dprint_ex(1, content) self.ssh.set_contents(tmpfilename, content) if backup_extension: dprint_ex(1, "Backing up %s" % path) backup_cmd = "copy /y " + quote_path_win( path) + " " + quote_path_win(path + backup_extension) msg, code = self.process_ops.get_cmd_output(backup_cmd) if code != 0: print backup_cmd, "->", msg raise RuntimeError("Error backing up file: %s" % msg) copy_to_dest = "copy /y " + quote_path_win( tmpfilename) + " " + quote_path_win(path) delete_tmp = "del " + quote_path_win(tmpfilename) dprint_ex(1, "Copying file to final destination: %s" % copy_to_dest) msg, code = self.process_ops.get_cmd_output(copy_to_dest) if code != 0: print copy_to_dest, "->", msg raise RuntimeError( "Error copying temporary file over destination file: %s\n%s to %s" % (msg, tmpfilename, path)) dprint_ex(1, "Deleting tmp file: %s" % delete_tmp) msg, code = self.process_ops.get_cmd_output(delete_tmp) if code != 0: print "Could not delete temporary file %s: %s" % (tmpfilename, msg) else: raise Exception("No SSH session active, cannot save file remotely")
dprint_ex(1, str(exc)) if tmp: tmp.close() raise else: target_dir = splitpath(filename)[0] if not os.path.exists(target_dir): dprint_ex(1, "Target directory %s does not exist" % target_dir) raise InvalidPathError("The directory %s does not exist" % target_dir) if not self.is_dir_writable(target_dir): dprint_ex(1, "Target directory %s is not writable" % target_dir) raise PermissionDeniedError("Cannot write to target directory") if os.path.exists(filename) and backup_extension: dprint_ex(1, "Target file %s exists, creating backup" % filename) # backup config file self._copy_file(filename, filename + backup_extension) try: f = open(filename, 'w') except OSError, err: if err.errno == errno.EACCES: raise PermissionDeniedError( "Could not open file %s for writing" % filename) raise err f.write(content) f.close()
class AdminSecurity(object): def __init__(self, ctrl_be): self.ctrl_be = ctrl_be self._accounts = [] self._schema_names = [] self._zombie_privs = {} # (user, host): [objects] self._account_info_cache = {} # A mapping with the form 'user@host' -> AdminAccount instance for that user self._schema_privileges_cache = {} self.has_plugin = False self.has_authentication_string = False self.has_max_user_connections = False self.has_password_expired = False # Supported schema specific privilege list: self.schema_privilege_names = [] # This list will be filled in self.async_refresh() with the column names # that represent specific privileges in the mysql.db table. These column # names are queried so that only the supported ones end up here. # Supported user global privilege list: self.global_privilege_names = [] # This list will be filled in self.async_refresh() with the column names # that represent specific privileges in the mysql.user table. These column # names are queried so that only the supported ones end up here. self.user_table_fields = [] # To be filled with all the fields in the mysql.user table. def get_valid_privileges(self): # self.global_privilege_names - column names from user table # PrivilegeInfo: map of user table's column name to privilege and its description privs = [] for name in self.global_privilege_names: (priv, desc) = PrivilegeInfo.get(name, (None, None)) if priv: privs.append(priv) return privs def async_refresh(self, callback): # Get the list of privileges supported by the version of MySQL Server we are connected to: if not self.schema_privilege_names: try: result = self.ctrl_be.exec_query("DESCRIBE mysql.db") except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the account used has rights to the MySQL grant tables.\n%s" % e) raise e if result is not None: while result.nextRow(): field= result.stringByName("Field") if field.endswith("_priv"): self.schema_privilege_names.append(field) if not self.user_table_fields: try: result = self.ctrl_be.exec_query("DESCRIBE mysql.user") except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the account used has rights to the MySQL grant tables.\n%s" % e) raise e if result is not None: while result.nextRow(): field= result.stringByName("Field") self.user_table_fields.append(field) if field.endswith("_priv"): self.global_privilege_names.append(field) elif field == "max_user_connections": self.has_max_user_connections = True elif field == "plugin": self.has_plugin = True elif field == "authentication_string": self.has_authentication_string = True elif field == "password_expired": self.has_password_expired = True
elif field == "max_user_connections": self.has_max_user_connections = True elif field == "plugin": self.has_plugin = True elif field == "authentication_string": self.has_authentication_string = True elif field == "password_expired": self.has_password_expired = True # get list of schema names schema_names = [] try: result = self.ctrl_be.exec_query(LIST_SCHEMAS_QUERY) except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the account used has rights to the MySQL grant tables.\n%s" % e) raise e except Exception, e: raise Exception("Error querying privilege information: %s" % e) if result is not None: while result.nextRow(): name = to_unicode(result.stringByName("Database")) schema_names.append(name) schema_names.sort() self._schema_names = schema_names # Get a list of the account names from the mysql.user table: accounts = [] try:
class AdminSecurity: def __init__(self, ctrl_be): self.ctrl_be = ctrl_be self._accounts = [] self._schema_names = [] self._account_info_cache = {} self._schema_privileges_cache = {} self.has_plugin = False self.has_authentication_string = False self.has_max_user_connections = False self.schema_privilege_names = [] self.global_privilege_names = [] self.user_table_fields = [] def get_valid_privileges(self): # self.global_privilege_names - column names from user table # PrivilegeInfo: map of user table's column name to privilege and its description privs = [] for name in self.global_privilege_names: (priv, desc) = PrivilegeInfo.get(name, (None, None)) if priv: privs.append(priv) return privs def async_refresh(self, callback): # get list of privileges that actually exist if not self.schema_privilege_names: try: result = self.ctrl_be.exec_query("DESCRIBE mysql.db") except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the used account has rights to the MySQL grant tables.\n%s"%e) raise e if result is not None: while result.nextRow(): field= result.stringByName("Field") if field.endswith("_priv"): self.schema_privilege_names.append(field) if not self.user_table_fields: try: result = self.ctrl_be.exec_query("DESCRIBE mysql.user") except QueryError, e: if e.error == 1142: raise PermissionDeniedError("Please make sure the used account has rights to the MySQL grant tables.\n%s"%e) raise e if result is not None: while result.nextRow(): field= result.stringByName("Field") self.user_table_fields.append(field) if field.endswith("_priv"): self.global_privilege_names.append(field) if field == "max_user_connections": self.has_max_user_connections = True if field == "plugin": self.has_plugin = True if field == "authentication_string": self.has_authentication_string = True