I have a function in python that change my account password. That is something like follows :
def f(account):
new_password = # Some random string generation
# Do something and send password change request to remote
account.password = new_password
account.save()
In the second line of above function I send a post request to change my password and then do some processing and finally save my new password. In the processing phase some error has occurred, but unfortunately my request has been sent to server. I have called the function in python shell and now my password has changed but I don't have it. Is it possible to get new_password variable from my function in python shell?
First of all, that is not valid Python code. Functions are not defined with function, but with def. (It seems you updated your question after reading this).
If indeed the function is called with an account object, then the caller will have access to it after the call. So account.password should have the password, unless account.save() wiped it out.
For instance, this could work:
def f(account):
new_password = # Some random string generation
# Do something and send password change request to remote
account.password = new_password
account.save()
account = Account() # do here whatever you do to get an account object
try: # Trap errors
f(account)
except:
print("Something went wrong...")
finally: # Whether an exception occurred or not, print the password
print("The password is:", account.password)
Again, this can only provide the password if account.save() did not destroy the value assigned to account.password.
If you can change the f function to your needs, then include the error handling inside that function and have it return the password:
def f(account):
new_password = # Some random string generation
# Do something and send password change request to remote
account.password = new_password
try: # Trap errors
account.save()
except:
print("Something went wrong...")
return new_password
account = Account() # do here whatever you do to get an account object
new_password = f(account) # now you will have the password returned
print("The password is:", new_password)
If however you already called the function and the program ended, then it is of course too late now. You must take the necessary precautions before running the code, and only run it when you are sure you can recover the password whatever happens.
Related
I am trying to retrieve a value from MongoDB and set a string to it in Python with MongoDB. Here is my user registration function:
def registerAccount():
registerUsername = input('Please input a username to be registered into our database.')
registerPassword = input('Please input a password to be entered into our database.')
passwordHash = sha256_crypt.hash(registerPassword)
regDetails = {
"username": registerUsername,
"passwordhash": passwordHash
}
db = client.pinnacle
users = db.users
users.insert(regDetails)
and here is my login function:
def login():
db = client.pinnacle
users = db.users
pwHash = users.find_one({"passwordhash"})
print(str(pwHash))
loginUsername = input('Please input username to be signed in.')
loginPassword = input('Please input password to be signed in.')
# pprint.pprint(users.find_one({"username": "1"}))
# example = users.find_one({"username": "1"})
pbkdf2_sha256.verify(loginPassword, pwHash)
Basically, I need to search the database for the username, and get the string right after the username which is passwordHash. Then I will set pwHash to that string which will be checked with PassLib. Help is appreciated. Thanks!
Also if anyone is interested you can see my full code here.
this happens whenever i select to login, even after not typing in username or password
The error is caused by this line below:
pwHash = users.find_one({"passwordhash"})
Where you should specify a filter of key/value pair, instead it's only specifying a key. You should remove the line above (and the print line right after it). See also pymongo find_one() method for more info.
Also, in the same function login(), you have a typo for key username.
user = users.find_one({"userName": loginUsername})
Note that it should be lowercase username to be consistent with how you're storing them elsewhere in the code.
Lastly, you should replace
pbkdf2_sha256.verify(loginPassword, user['passwordhash'])
with below method, as this is how you encrypt it in the registerAccount()
sha256_crypt.verify(loginPassword, user['passwordhash'])
Please consider adding error checks throughout your code. i.e. if users.find_one() returns None do XYZ.
I am trying to write a unit test in python that tests a username and password entry. I am using prompts for user input for both the username and password.
I have two separate functions that prompt the user for username and password. Both functions then check length. The password function also checks for exceptions, that were made by us, if the password length is zero. Are their ways to mock these exceptions?
I am struggling because I can get passed the username prompt but the pytest script holds after the username input. Is there a way to mock both username and password?
I am fairly new to python and I have looked through documentation but everything I have seen is usually for Python 3.x.x which we currently aren't implementing at this time. Any help would be much appreciated.
I think the init function is actually causing most of the headaches I am having. Is there a way around this?
class Login(object):
def __init__(self, args, env="test"):
created_token = self.login()
def login(self):
username = self.args.username
if len(username) == 0:
username = self._get_username()
password = self.args.password
if len(password) == 0:
password = self._get_password(username)
def _get_username(self):
return prompt('%s Username (%s): ' % (self.domain)
def _get_password(self):
if password is None:
password = prompt_sensitive('%s Password: ' % self.domain)
try:
except ParseError,e:
print "ParseError message"
except ClientError,e:
print "ClientError message"
You can use dependency injection to inject the prompt.
def password_function(input_func=None):
input_func = input_func or input
...
def test_password_function(self, ...):
fake_input = Mock()
...
result = password_function(fake_input)
This won't break existing code since the previous call signature is valid. e.g. password_function(). However if you don't have access to change the code then you can patch the input function.
import __builtin__
#mock.patch(__builtins__, 'input', return_value=...)
def test_password_function(self, mock_input):
I want to create a dictionary that stores all the inputs that are submitted. I am able to get one username and password and then store it but I want the program to continually ask for username and password and keep storing it in the dictionary. Eventually I want to write the loop that will check if certain passwords and usernames exist. I'm not sure but I think I would need a counter to allow continuous input from the user.
def login():
username = input ("Username: ")
password = input ("Password: ")
data = { }
data[username] = password
print (data)
login()
If you want to repeat something a bunch of times, you're probably looking for a for loop or while loop. In this instance you can change
login()
to
for i in range(100):
login()
this will ask for Username and Password 100 times! If you really want to ask for it forever you could do something like:
while True:
login()
Hope that helps!
When you use the answer by #Bovard, move the data = {} initialization outside the for or while loop. Otherwise, you'll end up always resetting data to an empty dictionary.
Either:
make data a global variable which login can access,
or let login call another function which gets user input,
or do the infinite/long loop inside login():
def login():
data = {}
while True:
username = input("Username: ")
password = input("Password: ")
data[username] = password
print(data)
login()
Good Day.
Im trying to write a python script that will take a captured password then compare it
to the system shadowed password.
Im using Ubuntu 12.10 for this test. and running the script as sudo.
def login(user, password):
"Check if user would be able to login using password"
try:
pw1 = spwd.getspnam(user)[1]
allus = spwd.getspall()
print pw1
# pw2 = crypt.crypt(password, pw1[:2])
pw2 = crypt.crypt(password, '\$6\$SALTsalt\$')
print pw2
return pw1 == pw2
except KeyError:
return 0 # no such user
Now the above returns
2 diferent passwords but i do get the one from the shadowed.
So my question is how do i encrypt the supplied password so i can compare it to the
one retreived. Any Help would be awsome
Edit addon
def login(user, password):
"Check if user would be able to login using password"
try:
pw1 = spwd.getspnam(user)[1]
allus = spwd.getspall()
# print allus
print pw1
# pw2 = crypt.crypt(password, pw1[:2])
# pw2 = crypt.crypt(password, '\$6\$SALTsalt\$')
pw2 =hashlib.new()
pw2.update(password)
pw2.digest()
print pw2
return pw1 == pw2
except KeyError:
return 0 # no such user
That also did not work
How does one impliment the haslib to get the hash to match system password
I've made an example on how to authenticate using shadowed passwords. I added some comments to let the code speak for itself.
Some extra info:
https://en.wikipedia.org/wiki/Passwd#Shadow_file
http://docs.python.org/2/library/spwd.html
http://docs.python.org/2/library/crypt.html
Also note (from the crypt module docs):
This module implements an interface to the crypt(3) routine, which is a one-way hash function based upon a modified DES algorithm; see the Unix man page for further details. Possible uses include allowing Python scripts to accept typed passwords from the user, or attempting to crack Unix passwords with a dictionary.
Notice that the behavior of this module depends on the actual implementation of the crypt(3) routine in the running system. Therefore, any extensions available on the current implementation will also be available on this module.
This is also why you cannot use hashlib without problems.
import crypt # Interface to crypt(3), to encrypt passwords.
import getpass # To get a password from user input.
import spwd # Shadow password database (to read /etc/shadow).
def login(user, password):
"""Tries to authenticate a user.
Returns True if the authentication succeeds, else the reason
(string) is returned."""
try:
enc_pwd = spwd.getspnam(user)[1]
if enc_pwd in ["NP", "!", "", None]:
return "user '%s' has no password set" % user
if enc_pwd in ["LK", "*"]:
return "account is locked"
if enc_pwd == "!!":
return "password has expired"
# Encryption happens here, the hash is stripped from the
# enc_pwd and the algorithm id and salt are used to encrypt
# the password.
if crypt.crypt(password, enc_pwd) == enc_pwd:
return True
else:
return "incorrect password"
except KeyError:
return "user '%s' not found" % user
return "unknown error"
if __name__ == "__main__":
username = raw_input("Username:")
password = getpass.getpass()
status = login(username, password)
if status == True:
print("Logged in!")
else:
print("Login failed, %s." % status)
I am trying to create a login.
I am not sure how to create/import a library of usernames and passwords; I am researching to find an answer at the moment but asked either way.
Match usernames with passwords (partially solved; need to add multiple usernames with matching passwords).
How to create a loop if password is incorrect? If incorrect password is entered the user needs to be prompted again to enter the password.
How to limit loop to certain number of attempts for password.
Below is what I have tried:
def check_password(user, password):
""" Return True if the user/pass combo is valid and False otherwise. """
# Code to lookup users and passwords goes here. Since the question
# was only about how to do a while loop, we have hardcoded usernames
# and passwords.
return user == "pi" and password == "123"
def login():
""" Prompt for username and password, repeatedly until it works.
Return True only if successful.
"""
try:
while True:
username = raw_input('username:')
password = raw_input('password:')
if check_password(username, password):
break
else:
print "Please try again"
print "Access granted"
return True
except:
return False
For testing: login().
This fixed lack of loop prompting if wrong password due to using return instead of print; and if instead of while.
def login():
#create login that knows all available user names and match to password ; if password is incorect returns try again and propmts for password again#
username = raw_input('username:')
if username !='pi':
#here is where I would need to import library of users and only accept those usernames; needs to be like 'pi' or 'bob' or 'tim'etc.
print'user not found'
username = raw_input('username')
password = raw_input('password:')
#how to match password with user? store in library ?
while password != '123':
print 'please try again' # You have to change the 'return' to 'print' here
password = raw_input('password')
return 'access granted'
#basically need to create loop saying 'try again' and prompting for password again; maybe smarter to ask limited number of
#times before returning 'you have reached limit of attempts#
if password == '123':
#again matching of passwords and users is required somehow
return 'access granted'
>>> login()
username:wronguser
user not found
usernamepi
password:wrongpass
please try again
password123
'access granted'
>>>
First attempt before updating thanks to Merigrim:
def login():
# Create login that knows all available user names and match to password;
# if password is incorect returns try again and propmts for password again#
username = raw_input('username:')
if username !='pi':
# Here is where I would need to import library of users and only
# accept those usernames; needs to be like 'pi' or 'bob' or 'tim'etc.
return 'user not found'
password = raw_input('password:')
# How to match password with user? store in library?
if password != '123':
return 'please try again'
password = raw_input('password:')
if password != '123':
return 'please try again'
# Basically need to create loop saying 'try again' and prompting
# for password again; maybe smarter to ask limited number of
# times before returning 'you have reached limit of attempts
elif password == '123':
# Again matching of passwords and users is required somehow
return 'access granted'
Here is how it currently works:
>>> login()
username:pi
password:123
'access granted'
>>> login()
username:pi
password:wrongpass
'please try again'
I need to create loop to prompt again for password.
What you want is the while statement.
Instead of nesting if-statements like this:
if password != '123':
return 'please try again'
password = raw_input('password:')
if password != '123':
return 'please try again'
elif password == '123':
return 'access granted'
You can do this:
while password != '123':
print 'please try again' # You have to change the 'return' to 'print' here
password = raw_input('password:')
return 'access granted'
This will continue prompting the user for a password until the right password is entered. If you want to become more familiar with the while statement, I suggest checking out some tutorials, like this one.
Please note that if you return something the function will exit there, so the user will never be prompted for a password. In the code above I changed the return to a print statement instead.
Here's another solution with the user name and password factored out, and an exception handler in case someone tries to abort the input.
Also, FYI it is best to take the user and password together so as not to let crackers know what is and is not a valid username.
def check_password(user, password):
""" Return True if the user/pass combo is valid and False otherwise. """
# Code to lookup users and passwords goes here. Since the question
# was only about how to do a while loop, we have hardcoded usernames
# and passwords.
return user == "pi" and password == "123"
def login():
""" Prompt for username and password, repeatedly until it works.
Return True only if successful.
"""
try:
while True:
username = raw_input('username:')
password = raw_input('password:')
if check_password(username, password):
break
else:
print "Please try again"
print "Access granted"
return True
except:
return False
# For testing
login()