/
githubmirror
/
libsmbios
Обзор
Документация
Войти
/
githubmirror
/
libsmbios
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/bin/smbios-token-ctl
475 строк
18 KB
Marcin Mielniczuk
Don't abort dumping tokens after a failure.
02 июн 2019, 22:20
02 июн 2019, 22:20
43a9be1
Код
Авторство
О чём код?
#!/usr/bin/python3 # vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:tw=0 ############################################################################# # # Copyright (c) 2005 Dell Computer Corporation # Dual Licenced under GNU GPL and OSL # Contributor: (c) 2019 Marcin Mielniczuk <marmistrz dot dev at zoho dot eu> # ############################################################################# """smbios-token-ctl""" # import arranged alphabetically import csv import gettext import locale import fnmatch from optparse import OptionParser import os import io import string import sys import traceback # the following vars are all substituted on install # this bin isnt byte-compiled, so this is ok pythondir=os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "..", "python") clidir=os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "..", "py-cli") # end vars # import all local modules after this. sys.path.insert(0,pythondir) sys.path.insert(0,clidir) import cli from libsmbios_c import smbios_token, localedir, GETTEXT_PACKAGE, pkgdatadir from libsmbios_c.trace_decorator import traceLog, getLog from libsmbios_c import system_info as sysinfo __VERSION__=sysinfo.get_library_version_string() locale.setlocale(locale.LC_ALL, '') gettext.install(GETTEXT_PACKAGE, localedir) moduleLog = getLog() verboseLog = getLog(prefix="verbose.") TOKENLIST_CSV=os.path.join(pkgdatadir, "token_list.csv") TOKENBLACKLIST_CSV=os.path.join(pkgdatadir, "token_blacklist.csv") class CmdlineError(Exception): pass class BlacklistedToken(Exception): pass def command_parse(): parser = cli.OptionParser(usage=__doc__, version=__VERSION__) parser.add_option("-d", '--dump-tokens', action="store_const", dest="action", help= _("Action: dump token table"), const="dump-tokens", default="dump-tokens") parser.add_option('--dump-tokens-csv', action="store_const", dest="action", help= _("Action: dump token table in CSV format"), const="dump-tokens-csv") parser.add_option('--import-token-settings-csv', action="store_const", dest="action", help= _("Action: Restore token settings from CSV table dump"), const="import-tokens-csv") parser.add_option('--is-string', action="store_const", dest="action", help=_("Action: return true if specified token is a string."), const="is-string") parser.add_option('--is-bool', action="store_const", dest="action", help=_("Action: return true if specified token is a bool."), const="is-bool") parser.add_option('--is-active', action="store_const", dest="action", help=_("Action: return true if specified bool token is active."), const="is-active") parser.add_option('--get-string', action="store_const", dest="action", help=_("Action: get string token value."), const="get-string") parser.add_option('--activate', action="store_const", dest="action", help=_("Action: activate specified bool token."), const="activate") parser.add_option('--set-string', action="store_const", dest="action", help=_("Action: set string token value."), const="set-string") parser.add_option("-i", '--token-id', "--token", action="store", dest="token_id", help=_("Filter only token with ID."), default=None) parser.add_option("-n", '--token-name', action="store", dest="token_name", help=_("Filter only token with name."), default=None) parser.add_option("-s", '--token-setting', action="store", dest="token_setting", help=_("Filter only token with setting."), default=None) parser.add_option('--token-csv', action="append", type="string", dest="token_csv", help=_("path to the token.csv file."), default=[TOKENLIST_CSV,]) parser.add_option('--token-blacklist-csv', action="append", dest="token_blacklist_csv", help=_("Path to token blacklist file."), default=[TOKENBLACKLIST_CSV]) cli.addStdOptions(parser) return parser.parse_args() class translatedToken(object): id = "" name = _("unknown") setting = _("unknown") description = _("unknown") spec = _("unknown") def __init__(self, tokenObj): self.id = tokenObj.getId() class TokenTranslator(object): def __init__(self, *args, **kargs): self.tokens={} self.blacklist_tokens={} self.honorBlacklist=kargs.get('honorBlacklist',1) self.addToList(csv.DictReader(filter(lambda row: row[0]!='#', io.StringIO(INTERNAL_BLACKLIST))), self.blacklist_tokens) for csvfile in kargs.get('csvblacklist',[]): try: csvdict = csv.DictReader(filter(lambda row: row[0]!='#', open(csvfile, "r"))) self.addToList(csvdict, self.blacklist_tokens) except IOError as e: pass def __call__(self, tokenObj): retval = translatedToken(tokenObj) if self.tokens.get(retval.id) is not None: retval.name = self.tokens[retval.id]["Attribute Name"] retval.setting = self.tokens[retval.id]["Attribute Setting"] retval.description = self.tokens[retval.id]["Description"] retval.spec = self.tokens[retval.id]["Spec"] if self.blacklist_tokens.get(retval.id) and self.honorBlacklist: raise BlacklistedToken(self.blacklist_tokens[retval.id]['Reason']) return retval def addToList(self, csvdict, whichlist): for line in csvdict: try: val = int(line["Token Value"],16) line["Token Value"] = "0x%04x" % val whichlist[val] = line except Exception as e: sys.stderr.write("="*79 + "\n") sys.stderr.write(_("Ignoring parsing error in CSV file:") ) traceback.print_exc() sys.stderr.write("="*79 + "\n") class TokenTranslatorCsv(TokenTranslator): def utf8_decode_gen(self, dictiter): for d in dictiter: for k,v in d.items(): if v is not None and isinstance(v, str): d[k] = str(v, 'utf-8') yield d def __init__(self, *args, **kargs): super(TokenTranslatorCsv,self).__init__(self, *args, **kargs) for csvfile in kargs.get('csvlist', []): try: csvdict = csv.DictReader( filter(lambda row: row[0]!='#', open(csvfile, "r"))) self.addToList(csvdict, self.tokens) except IOError as e: sys.stderr.write(_("Skipping '%s' due to IOError.\n") % cvsfile) sys.stderr.write(_("The error message was: %s") % e) continue def tokenInfo(tokenObj, action): exit_code=1 type = _("<weird unknown type>") value = _("<unknown value>") if tokenObj.isBool(): if action == "is-bool": exit_code = 0 type="bool" value="false" if tokenObj.isActive(): if action == "is-active": exit_code = 0 value="true" elif tokenObj.isString(): if action == "is-string": exit_code = 0 type = "string" value = tokenObj.getString() return (exit_code, type, value) def shouldSkipToken(token, options): skip = 0 if options.token_id is not None: skip = 1 if token.id == options.token_id: skip=0 if options.token_name is not None: skip = 1 if fnmatch.fnmatch(token.name.lower(), options.token_name.lower()): skip=0 if options.token_setting is not None: skip = 1 if token.setting == options.token_setting: skip=0 return skip def dumpTokens(tokenTable, tokenXlator, options): for token in tokenTable: try: translatedToken = tokenXlator(token) except BlacklistedToken as e: #sys.stdout.write( "="*80 + "\n" ) #print "Not dumping blacklisted token 0x%04x. Reason: %s" % (token.getId(), str(e)) continue if shouldSkipToken(translatedToken, options): continue sys.stdout.write( "="*80 + "\n" ) print(_(" Token: 0x%04x - %s (%s)") % (translatedToken.id, translatedToken.name, translatedToken.setting)) try: (e, type, value) = tokenInfo(token, "dump-tokens") print(_(" value: %s = %s") % (type, cli.makePrintable(value))) except RuntimeError as e: pass except smbios_token.TokenManipulationFailure as e: print(f" value: token query failed: {e}") desc = _(" Desc: ") sys.stdout.write(desc) cli.wrap(translatedToken.description, indent=len(desc), first_line_start=len(desc)) print() def dumpTokensCsv(tokenTable, tokenXlator, options): # make sure not to localize the string below: sys.stdout.write("ID,Type,Value,Name,Setting\n") w = csv.writer( sys.stdout ) for token in tokenTable: try: translatedToken = tokenXlator(token) except BlacklistedToken as e: #sys.stdout.write( "="*80 + "\n" ) #print "Not dumping blacklisted token 0x%04x. Reason: %s" % (token.getId(), str(e)) continue if shouldSkipToken(translatedToken, options): continue (e, type, value) = tokenInfo(token, "dump-tokens") w.writerow(("0x%04x" % translatedToken.id,type,cli.makePrintable(value),translatedToken.name, translatedToken.setting)) sys.stdout.flush() def importTokensCsv(tokenTable, tokenXlator, options, args): retval=True print(_("Importing token values from '%s'") % args[0]) csvdict = csv.DictReader(CommentedFile(open(args[0], "rb"))) for line in csvdict: try: id = int(line["ID"], 0) type=line["Type"] value=line["Value"] except KeyError as e: print(_("File format error. The first line should list the column names. Could not find the %s column") % str(e)) print(_("Cannot continue, exiting.")) retval=False break try: token = tokenTable[id] translatedToken = tokenXlator(token) if shouldSkipToken(translatedToken, options): continue if translatedToken.name == _("unknown") or translatedToken.setting == _("unknown"): print(_("Not importing token that is unknown: 0x%04x") % id) retval=False continue if translatedToken.name != line["Name"]: print(_("INFO: token 0x%04x settings file name does not match my DB. Applying setting anyways.") % id) print(_("\tsettings file: %s") % line["Name"]) print(_("\tDB name : %s") % translatedToken.name) if translatedToken.setting != line["Setting"]: print(_("INFO: token 0x%04x settings file setting-name does not match my DB. Applying setting anyways.") % id) print(_("\tsettings file: %s") % line["Setting"]) print(_("\tDB name : %s") % translatedToken.setting) if type == "bool": if not token.isBool(): print(_("SKIPPING: TYPE MISMATCH. Settings file says token 0x%04x should be bool, but it doesnt pass bool check.") % (id)) retval=False continue elif value == "true": if not token.isActive(): print(_("Importing setting for token (active): 0x%04x") % id) token.activate() else: print(_("Token already correct (bool, active): 0x%04x") % id) elif value == "false": if token.isActive(): print(_("Info: Cannot de-activate tokens, can only activate the contrapositive. (0x%04x == false)") % id) else: print(_("Token already correct (bool, inactive): 0x%04x") % id) else: print(_("UNEXPECTED VALUE: Bool token should only ever have values of 'true' or 'false', but token 0x%04x tries to set value '%s'") % (id, value)) continue elif type == "string": if not token.isString(): print(_("SKIPPING: TYPE MISMATCH. Settings file says token 0x%04x should be string, but it doesnt pass string check.") % (id)) retval=False continue if token.getString() != value: print(_("Importing setting for token (string): 0x%04x") % id) token.setString(value) else: print(_("Token already correct (string=='%s'): 0x%04x") % (value, id)) except IndexError as e: print(_("Not importing token which is inapplicable to this system: 0x%04x") % (id)) retval=False continue except BlacklistedToken as e: print(_("Not importing blacklisted token 0x%04x. Reason: %s") % (token.getId(), str(e))) retval=False continue except Exception as e: sys.stderr.write("="*79 + "\n") sys.stderr.write(_("Ignoring parsing error in CSV file:") ) traceback.print_exc() sys.stderr.write("="*79 + "\n") retval=False continue return retval def getTokenObj(tokenTable, tokenXlator, options): # optimization if options.token_id: return tokenTable[options.token_id] if options.token_name is None or options.token_setting is None: raise CmdlineError(_("require token-id or token name/setting pair.")) for token in tokenTable: try: translatedToken = tokenXlator(token) if shouldSkipToken(translatedToken, options): continue return token except BlacklistedToken as e: pass raise CmdlineError(_("token not found. Name(%s) Setting(%s).") % ( options.token_name, options.token_setting)) def main(): exit_code = 0 (options, args) = command_parse() cli.setup_std_options(options) if options.token_id: options.token_id = int(options.token_id, 0) try: tokenXlator = TokenTranslatorCsv(csvlist=options.token_csv, csvblacklist=options.token_blacklist_csv) tokenTable = smbios_token.TokenTable() if options.action == "dump-tokens": dumpTokens(tokenTable, tokenXlator, options) return exit_code if options.action == "dump-tokens-csv": dumpTokensCsv(tokenTable, tokenXlator, options) return exit_code if options.action == "import-tokens-csv": exit_code = not importTokensCsv(tokenTable, tokenXlator, options, args) return exit_code tokenObj = getTokenObj(tokenTable, tokenXlator, options) tokenObj.tryPassword(options.password_ascii, options.password_scancode) if options.action in ("set-string", "activate"): (exit_code, type, value) = tokenInfo(tokenObj, options.action) print(_("Original Value")) print(_(" token: 0x%04x") % tokenObj.getId()) print(_(" type: %s") % type) print(_(" value: %s") % cli.makePrintable(value)) if options.action == "set-string": (exit_code, type, value) = tokenInfo(tokenObj, "dump-tokens") print(_("Setting string value ...")) tokenObj.setString(args[0]) print(_("New value")) if options.action == "activate": (exit_code, type, value) = tokenInfo(tokenObj, "dump-tokens") print(_("Activating token...")) tokenObj.activate() print(_("New value")) if options.action in ("set-string", "activate", "is-bool", "is-string", "is-active", "get-string"): (exit_code, type, value) = tokenInfo(tokenObj, options.action) print(_(" type: %s") % type) print(_(" value: %s") % cli.makePrintable(value)) except (smbios_token.TokenTableParseError, ) as e: exit_code=3 moduleLog.info( _("ERROR: Could not parse system SMBIOS table.") ) verboseLog.info( _("The smbios library returned this error:") ) verboseLog.info( str(e) ) moduleLog.info( cli.standardFailMessage ) except (smbios_token.TokenManipulationFailure,) as e: exit_code=4 moduleLog.info( _("ERROR: Could not manipulate system token.") ) verboseLog.info( _("The token library returned this error:") ) verboseLog.info( str(e) ) moduleLog.info( cli.standardFailMessage ) except StopIteration: pass return exit_code INTERNAL_BLACKLIST = \ """\ "Token Value","Reason" # blacklist: # - raid shadow copy (0x00CD, 0x00CE, 0x00CF, 0x00D0) 0x00CD,"Manufacturing use." 0x00CE,"Manufacturing use." 0x00CF,"Manufacturing use." 0x00D0,"Manufacturing use." # - sata controller shadow copy ( 0x013a 0x013b 0x013c 0x013d 0x01FF) 0x013A,"Manufacturing use." 0x013B,"Manufacturing use." 0x013C,"Manufacturing use." 0x013D,"Manufacturing use." 0x01FF,"Manufacturing use." # - management driver (0x0058, 0x0059) 0x0058,"Management driver use." 0x0059,"Management driver use." 0x8004,"dangerous - hard system power down." # - absolute security rom (0x0175, 0x0176) 0x0175,"dangerous - permanent write once" 0x0176,"dangerous - permanent write once" # - manufacturing mode (0x4026, 0x4027) 0x4026,"Manufacturing mode." 0x4027,"Manufacturing mode." # - cmos location for post (0x9000, 0x9001) 0x9000,"Manufacturing use." 0x9001,"Manufacturing use." # - TPM os enable/disable (0xa0002, 0xa003) 0xa002,"Manufacturing use." 0xa003,"Manufacturing use." """ if __name__ == "__main__": sys.exit( main() )