Beispiel #1
0
def cmd_authenticator_status(args):
    account = args.account.lower().strip()
    secrets_file = UserDataFile('authenticator/{}.json'.format(account))
    sa = None

    wa = BetterMWA(account)

    if secrets_file.exists():
        sa = SteamAuthenticator(secrets_file.read_json(), backend=wa)

    try:
        wa.bcli_login(sa_instance=sa)
    except (KeyboardInterrupt, EOFError):
        print("Login interrupted")
        return 1  # error

    if sa is None:
        sa = SteamAuthenticator(backend=wa)

    status = sa.status()

    print("----- Status ------------")
    mode = status['steamguard_scheme']

    if mode == 0:
        print("Steam Guard mode: disabled/insecure")
    elif mode == 1:
        print("Steam Guard mode: enabled (email)")
    elif mode == 2:
        print("Steam Guard mode: enabled (authenticator)")
    else:
        print("Steam Guard mode: unknown ({})".format(mode))

    print("Authenticator enabled:", "Yes" if status['state'] == 1 else "No")
    print("Authenticator allowed:", "Yes" if status['state'] else "No")
    print("Email verified:", "Yes" if status['email_validated'] else "No")
    print("External allowed:",
          "Yes" if status['allow_external_authenticator'] else "No")

    if status['state'] == 1:
        print("----- Token details -----")
        print("Token GID:", status['token_gid'])
        print("Created at:", fmt_datetime(status['time_created']))
        print("Device identifier:", status['device_identifier'])
        print("Classified agent:", status['classified_agent'])
        print("Revocation attempts remaining:",
              status['revocation_attempts_remaining'])
Beispiel #2
0
class clientLoginWindow(Toplevel):
    #Initialize
    def __init__(self, parent, colorDic, conn, rootClassRef):
        #Declare class variables
        self.authWindow = None
        self.colorDic = colorDic
        self.conn = conn
        self.parent = parent
        self.rootClassRef = rootClassRef
        #Initialize window's frame
        Toplevel.__init__(self)
        #Window title
        self.windowTitle = Label(self, text="New Account")
        self.windowTitle.configure(font=("Segoe UI", 12),
                                   bg=self.colorDic["windowTitleBackground"],
                                   fg=self.colorDic["windowTitleForeground"],
                                   width="350",
                                   pady=10)
        self.windowTitle.pack()
        #Steam logo image
        self.img = ImageTk.PhotoImage(file="images/gui/steam_logo.png")
        self.steamLogo = Label(self,
                               bg=self.colorDic["appBackground"],
                               image=self.img)
        self.steamLogo.pack(anchor="w", padx=35, pady=25)
        #Login item's frame
        self.loginHolder = Frame(self, bg=self.colorDic["appBackground"])
        self.loginHolder.pack(anchor="w", padx=45, pady=25)
        self.labelHolder = Frame(self.loginHolder,
                                 bg=self.colorDic["appBackground"])
        self.labelHolder.pack(side="left")
        self.entryHolder = Frame(self.loginHolder,
                                 bg=self.colorDic["appBackground"])
        self.entryHolder.pack(side="left")
        #Account name and password text
        self.userNameLabel = Label(self.labelHolder,
                                   text="Account Name",
                                   bg=self.colorDic["appBackground"],
                                   fg=self.colorDic["infoLabelForeground"],
                                   font=("Segoe UI", 12))
        self.userNameLabel.pack(padx=5, pady=5, anchor="e")
        self.passwordLabel = Label(self.labelHolder,
                                   text="Password",
                                   bg=self.colorDic["appBackground"],
                                   fg=self.colorDic["infoLabelForeground"],
                                   font=("Segoe UI", 12))
        self.passwordLabel.pack(padx=5, pady=5, anchor="e")
        #Account name and password entry boxes
        self.userNameEntry = Entry(self.entryHolder, width=45)
        self.userNameEntry.pack(padx=5, pady=5)
        self.userNameEntry.focus()
        self.passwordEntry = Entry(self.entryHolder, width=45, show="*")
        self.passwordEntry.pack(padx=5, pady=5)
        #Button holding frame, login button and cancel button
        self.buttonHolder = Frame(self, bg=self.colorDic["appBackground"])
        self.buttonHolder.pack(pady=15)
        self.loginButton = Button(self.buttonHolder,
                                  text="Login to Steam",
                                  font=("Segoe UI", 12),
                                  relief="flat",
                                  cursor="hand2",
                                  command=self.login_account)
        self.loginButton.configure(fg=self.colorDic["actionButtonForeground"],
                                   bg=self.colorDic["actionButtonBackground"])
        self.loginButton.pack(padx=30, ipady=10, ipadx=10, side="left")
        self.cancelButton = Button(self.buttonHolder,
                                   text="Cancel",
                                   font=("Segoe UI", 12),
                                   relief="flat",
                                   cursor="hand2",
                                   command=self.destroy)
        self.cancelButton.configure(fg=self.colorDic["cancelButtonForeground"],
                                    bg=self.colorDic["cancelButtonBackground"])
        self.cancelButton.pack(padx=30, ipady=10, ipadx=10, side="left")

    #Login and add guard method
    def login_account(self):
        #Login to steam with provided credentials
        self.userObject = clientData(self.userNameEntry.get(),
                                     self.passwordEntry.get(), None, None)
        self.userObject.login()
        #If password is invalid
        if self.userObject.loginResult == EResult.InvalidPassword:
            #Show error stating password is incorrect
            self.rootClassRef.show_message(
                None, "error", "Your password is incorrect. Please try again.")
        else:
            #If email code is required
            if self.userObject.loginResult in (EResult.AccountLogonDenied,
                                               EResult.InvalidLoginAuthCode):
                self.authWindow = promptFor2FA(self.parent, self.colorDic,
                                               True, self.rootClassRef)
            #If 2FA code is required
            elif self.userObject.loginResult in (
                    EResult.AccountLoginDeniedNeedTwoFactor,
                    EResult.TwoFactorCodeMismatch):
                self.authWindow = promptFor2FA(self.parent, self.colorDic,
                                               False, self.rootClassRef)
            #If email or 2FA code was required
            if self.authWindow:
                #Start 2FA prompt window
                self.authWindow.geometry("400x250")
                self.authWindow.resizable(0, 0)
                self.authWindow.configure(bg=self.colorDic["appBackground"])
                guiController(self.authWindow).center()
                self.authWindow.wait_window()
                #If auth code was set
                if self.authWindow.guardCode:
                    #If auth code was sent to email
                    if self.authWindow.isEmail:
                        self.userObject = clientData(self.userNameEntry.get(),
                                                     self.passwordEntry.get(),
                                                     self.authWindow.guardCode,
                                                     None)
                    else:
                        #If auth code was sent to mobile
                        self.userObject = clientData(self.userNameEntry.get(),
                                                     self.passwordEntry.get(),
                                                     None,
                                                     self.authWindow.guardCode)
                    self.userObject.login()
            #If login and code is correct
            if self.userObject.loginResult == EResult.OK:
                self.steamGuardController = SteamAuthenticator(
                    medium=self.userObject.client)
                if self.steamGuardController.status(
                )['steamguard_scheme'] != 2:
                    #If account has a phone number
                    if self.steamGuardController.has_phone_number():
                        #Add steam guard
                        self.steamGuardController.add()
                        #Start 2FA prompt window to get phone confirmation
                        self.authWindow = promptFor2FA(self.parent,
                                                       self.colorDic, False,
                                                       self.rootClassRef)
                        self.authWindow.geometry("400x250")
                        self.authWindow.resizable(0, 0)
                        self.authWindow.configure(
                            bg=self.colorDic["appBackground"])
                        guiController(self.authWindow).center()
                        self.authWindow.title("Steam Guardian - Mobile")
                        self.authWindow.windowTitle.configure(
                            text="Enter Text Sent to Phone")
                        self.authWindow.wait_window()
                        #If phone code is set
                        if self.authWindow.guardCode:
                            try:
                                self.steamGuardController.finalize(
                                    self.authWindow.guardCode)
                            except:
                                #If phone code is incorrect show an error
                                self.rootClassRef.show_message(
                                    None, "error",
                                    "Couldn't confirm your phone. Code is incorrect!"
                                )
                            else:
                                #Update data and gui
                                self.conn.create_user(
                                    str(
                                        json.dumps(self.steamGuardController.
                                                   secrets)),
                                    str(self.userObject.client.user.steam_id),
                                    self.userNameEntry.get(),
                                    self.passwordEntry.get())
                                self.rootClassRef.update_guard()
                        #We destroy our window here because Steam loves to rate limit if you retry too fast
                        self.destroy()
                    else:
                        #If account doesn't have phone number show an error
                        self.rootClassRef.show_message(
                            None, "error",
                            "Your account is missing a phone number to confirm.\nPlease add one and try again!"
                        )
                        webbrowser.open(
                            "https://store.steampowered.com/phone/manage")
                else:
                    #If account already has 2FA (email is fine) show an error
                    self.rootClassRef.show_message(
                        None, "error",
                        "Your account already has Steam Guard Mobile.\nPlease disable it and try again."
                    )
            else:
                #If steam guard code was incorrect.
                self.rootClassRef.show_message(None, "error",
                                               "Login or code was incorrect.")
Beispiel #3
0
def cmd_authenticator_add(args):
    account = args.account.lower().strip()
    secrets_file = UserDataFile('authenticator/{}.json'.format(account))
    sa = None

    if secrets_file.exists():
        if not args.force:
            print(
                "There is already an authenticator for that account. Use --force to overwrite"
            )
            return 1  # error
        sa = SteamAuthenticator(secrets_file.read_json())

    print("To add an authenticator, first we need to login to Steam")
    print("Account name:", account)

    wa = BetterMWA(account)
    try:
        wa.bcli_login(sa_instance=sa)
    except (KeyboardInterrupt, EOFError):
        print("Login interrupted")
        return 1  # error

    print("Login successful. Checking pre-conditions...")

    sa = SteamAuthenticator(backend=wa)

    status = sa.status()
    _LOG.debug("Authenticator status: %s", status)

    if not status['email_validated']:
        print("Account needs a verified email address")
        return 1  # error

    if status['state'] == 1:
        print("This account already has an authenticator.")
        print("You need to remove it first, before proceeding")
        return 1  # error

    if not status['authenticator_allowed']:
        print("This account is now allowed to have authenticator")
        return 1  # error

    # check phone number, and add one if its missing
    if not sa.has_phone_number():
        print("No phone number on this account. This is required.")

        if pmt_confirmation("Do you want to add a phone number?",
                            default_yes=True):
            print("Phone number need to include country code and no spaces.")

            while True:
                phnum = pmt_input("Enter phone number:",
                                  regex=r'^(\+|00)[0-9]+$')

                resp = sa.validate_phone_number(phnum)
                _LOG.debug("Phone number validation for %r: %s", phnum, resp)

                if not resp.get('is_valid', False):
                    print("That number is not valid for Steam.")
                    continue

                if not sa.add_phone_number(phnum):
                    print("Failed to add phone number!")
                    continue

                print("Phone number added. Confirmation SMS sent.")

                while not sa.confirm_phone_number(
                        pmt_input("Enter SMS code:", regex='^[0-9]+$')):
                    print("Code was incorrect. Try again.")

                break
        else:
            # user declined adding a phone number, we cant proceed
            return 1  # error

    # being adding authenticator setup
    sa.add()

    _LOG.debug("Authenticator secrets obtained. Saving to disk")

    secrets_file.write_json(sa.secrets)

    # Setup Steam app in conjuction
    if pmt_confirmation("Do you want to use Steam app too?",
                        default_yes=False):
        print("Great! Go and setup Steam Guard in your app.")
        print("Once completed, generate a code and enter it below.")

        showed_fail_info = False
        fail_counter = 0

        while True:
            code = pmt_input(
                "Steam Guard code:",
                regex='^[23456789BCDFGHJKMNPQRTVWXYbcdfghjkmnpqrtvwxy]{5}$')

            # code match
            if sa.get_code() == code.upper():
                break  # success
            # code do not match
            else:
                fail_counter += 1

                if fail_counter >= 3 and not showed_fail_info:
                    showed_fail_info = True
                    print("The codes do not match. This can be caused by:")
                    print("* The code was not entered correctly")
                    print("* Your system time is not synchronized")
                    print("* Steam has made changes to their backend")

                if not pmt_confirmation("Code mismatch. Try again?",
                                        default_yes=True):
                    _LOG.debug("Removing secrets file")
                    secrets_file.remove()
                    return 1  # failed, exit

    # only setup steamctl 2fa
    else:
        print(
            "Authenticator secrets obtained. SMS code for finalization sent.")

        while True:
            code = pmt_input("Enter SMS code:", regex='^[0-9]+$')
            try:
                sa.finalize(code)
            except SteamAuthenticatorError as exp:
                print("Finalization error: %s", exp)
                continue
            else:
                break

    # finish line
    print("Authenticator added successfully!")
    print("Get a code: {} authenticator code {}".format(__appname__, account))
    print("Or QR code: {} authenticator qrcode {}".format(
        __appname__, account))