#!/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
  #
  #############################################################################
"""smbios-passwd"""



# import arranged alphabetically
import gettext
import locale
import os
import sys
import traceback

# the following vars are all substituted on install
# this bin isnt byte-compiled, so this is ok
pythondir="/usr/lib/python3.7/site-packages"
clidir="/usr/share/smbios-utils"
# end vars

# import all local modules after this.
sys.path.insert(0,pythondir)
sys.path.insert(0,clidir)

import cli
from libsmbios_c import smi, localedir, GETTEXT_PACKAGE
from libsmbios_c.trace_decorator import traceLog, getLog
from libsmbios_c import system_info as sysinfo

__VERSION__="2.4.2"

locale.setlocale(locale.LC_ALL, '')
gettext.install(GETTEXT_PACKAGE, localedir)

moduleLog = getLog()
verboseLog = getLog(prefix="verbose.")

class CmdlineError(Exception): pass

def command_parse():
    parser = cli.OptionParser(usage=__doc__, version=__VERSION__)
    parser.add_option('--info', action="store_const", const="info", dest="action", default=None, help= _("Show password information"))
    cli.addStdOptions(parser, passwordOpts=True, securityKeyOpt=False)
    return parser.parse_args()

def info(options):
    format_strings = ( 
        ("DELL_SMI_PASSWORD_FMT_SCANCODE", _("Keyboard Scancodes")),
        ("DELL_SMI_PASSWORD_FMT_ASCII", _("ASCII")),
        )

    for label, tag in ( 
            (_("User password"), "DELL_SMI_PASSWORD_USER"), 
            (_("Admin password"), "DELL_SMI_PASSWORD_ADMIN"), 
            (_("Owner password"), "DELL_SMI_PASSWORD_OWNER")):
        whichpass = getattr(smi, tag)
        sys.stdout.write("%s\n" % label)
        fmt = smi.password_format(whichpass)
        for i in format_strings:
            if fmt == getattr(smi, i[0]):
                sys.stdout.write("\tPassword stored as: %s\n" % i[1])

        sys.stdout.write("\tPassword MAX length: %s\n" % smi.password_max_len(whichpass))

        passToTry = options.password_ascii
        if fmt == smi.DELL_SMI_PASSWORD_FMT_SCANCODE:
            passToTry = options.password_scancode

        if smi.is_password_present(whichpass):
            sys.stdout.write("\tinstalled\n");
        else:
            sys.stdout.write("\tNOT installed\n");
            continue

        if smi.password_verify(whichpass, passToTry):
            sys.stdout.write("\tPassword entered MATCHED\n")
            sys.stdout.write("\tSECURITY KEY: 0x%04x\n" % smi.get_security_key(passToTry))
        else:
            sys.stdout.write("\tPassword did not match\n")


def main():
    exit_code = 0
    (options, args) = command_parse()
    cli.setup_std_options(options)

    try:
        # first check we can actuall run SMIs (perms, etc)
        s = smi.DellSmi()  # we dont actually do anything with this
    
        if options.action == "info":
            info(options)

    except (smi.SmiCreateError,) 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 )
        
    return exit_code

if __name__ == "__main__":
    sys.exit( main() )


#message reference:
#
#            cerr << "BIOS Password encoding has been detected as SCAN CODE format." << endl;
#            cerr << "Automatically changing password from ASCII coding to en_US scancode format." << endl;
#            cerr << "Use the --rawpassword option to disable this, for example, if you have " << endl;
#            cerr << "another language keyboard, then manually convert the ASCII password to" << endl;
#            cerr << "scan code format." << endl;
#
#        cerr << endl;
#        cerr << "An Error occurred, cannot continue. The Error message is: " << endl;
#        cerr << "    " << e.what() << endl;
#        cerr << endl;
#        cerr << "Could not verify password. Common problems are:" << endl;
#        cerr << "    -- Insufficient permissions to perform operation." << endl;
#        cerr << "       Try running as a more privileged account." << endl;
#        cerr << "          Linux  : run as 'root' user" << endl;
#        cerr << "          Windows: run as 'administrator' user" << endl;
#        cerr << endl;
#        cerr << "    -- dcdbas device driver not loaded." << endl;
#        cerr << "       Try loading the dcdbas driver" << endl;
#        cerr << "          Linux  : modprobe dcdbas" << endl;
#        cerr << "          Windows: dcdbas driver not yet available." << endl;

