mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-24 19:52:54 +01:00
Added the ability to do hashed passwords.
This commit is contained in:
parent
8ae59844bf
commit
d174226c5c
29
src/User.py
29
src/User.py
@ -33,6 +33,7 @@
|
||||
Provides commands useful to users in general. This plugin is loaded by default.
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import string
|
||||
|
||||
import conf
|
||||
@ -50,14 +51,20 @@ class User(callbacks.Privmsg):
|
||||
return True
|
||||
|
||||
def register(self, irc, msg, args):
|
||||
"""<name> <password>
|
||||
"""[--hashed] <name> <password>
|
||||
|
||||
Registers <name> with the given password <password> and the current
|
||||
hostmask of the person registering. This command (and all other
|
||||
commands that include a password) must be sent to the bot privately,
|
||||
not in a channel.
|
||||
not in a channel. If --hashed is given, the password will be hashed
|
||||
on disk, rather than being stored in plaintext.
|
||||
"""
|
||||
(name, password) = privmsgs.getArgs(args, needed=2)
|
||||
(optlist, rest) = getopt.getopt(args, '', ['hashed'])
|
||||
(name, password) = privmsgs.getArgs(rest, needed=2)
|
||||
hashed = False
|
||||
for (option, arg) in optlist:
|
||||
if option == '--hashed':
|
||||
hashed = True
|
||||
if not self._checkNotChannel(irc, msg, password):
|
||||
return
|
||||
try:
|
||||
@ -77,7 +84,7 @@ class User(callbacks.Privmsg):
|
||||
pass
|
||||
(id, user) = ircdb.users.newUser()
|
||||
user.name = name
|
||||
user.setPassword(password)
|
||||
user.setPassword(password, hashed=hashed)
|
||||
user.addHostmask(msg.prefix)
|
||||
ircdb.users.setUser(id, user)
|
||||
irc.reply(msg, conf.replySuccess)
|
||||
@ -200,13 +207,19 @@ class User(callbacks.Privmsg):
|
||||
return
|
||||
|
||||
def setpassword(self, irc, msg, args):
|
||||
"""<name> <old password> <new password>
|
||||
"""[--hashed] <name> <old password> <new password>
|
||||
|
||||
Sets the new password for the user specified by <name> to
|
||||
<new password>. Obviously this message must be sent to the bot
|
||||
privately (not on a channel).
|
||||
privately (not in a channel). If --hashed is given, the password will
|
||||
be hashed on disk (rather than being stored in plaintext.
|
||||
"""
|
||||
(name, oldpassword, newpassword) = privmsgs.getArgs(args, 3)
|
||||
(optlist, rest) = getopt.getopt(args, '', ['hashed'])
|
||||
(name, oldpassword, newpassword) = privmsgs.getArgs(rest, 3)
|
||||
hashed = False
|
||||
for (option, arg) in optlist:
|
||||
if option == '--hashed':
|
||||
hashed = True
|
||||
if not self._checkNotChannel(irc, msg, oldpassword+newpassword):
|
||||
return
|
||||
try:
|
||||
@ -216,7 +229,7 @@ class User(callbacks.Privmsg):
|
||||
irc.error(msg, conf.replyNoUser)
|
||||
return
|
||||
if user.checkPassword(oldpassword):
|
||||
user.setPassword(newpassword)
|
||||
user.setPassword(newpassword, hashed=hashed)
|
||||
ircdb.users.setUser(id, user)
|
||||
irc.reply(msg, conf.replySuccess)
|
||||
else:
|
||||
|
20
src/ircdb.py
20
src/ircdb.py
@ -186,11 +186,12 @@ class UserCapabilitySet(CapabilitySet):
|
||||
class IrcUser(object):
|
||||
"""This class holds the capabilities and authentications for a user."""
|
||||
def __init__(self, ignore=False, password='', name='',
|
||||
capabilities=(), hostmasks=None, secure=False):
|
||||
capabilities=(), hostmasks=None, secure=False, hashed=False):
|
||||
self.auth = None # The (time, hostmask) a user authenticated under
|
||||
self.name = name # The name of the user.
|
||||
self.ignore = ignore # A boolean deciding if the person is ignored.
|
||||
self.secure = secure # A boolean describing if hostmasks *must* match.
|
||||
self.hashed = hashed # True if the password is hashed on disk.
|
||||
self.password = password # password (plaintext? hashed?)
|
||||
self.capabilities = UserCapabilitySet()
|
||||
for capability in capabilities:
|
||||
@ -201,10 +202,11 @@ class IrcUser(object):
|
||||
self.hostmasks = hostmasks
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(ignore=%s, password=%r, name=%r, '\
|
||||
return '%s(ignore=%s, password=%r, name=%r, hashed=%r, '\
|
||||
'capabilities=%r, hostmasks=%r, secure=%r)\n' %\
|
||||
(self.__class__.__name__, self.ignore, self.password,
|
||||
self.name, self.capabilities, self.hostmasks, self.secure)
|
||||
(self.__class__.__name__,
|
||||
self.ignore, self.password, self.name, self.hashed,
|
||||
self.capabilities, self.hostmasks, self.secure)
|
||||
|
||||
def addCapability(self, capability):
|
||||
"""Gives the user the given capability."""
|
||||
@ -224,12 +226,20 @@ class IrcUser(object):
|
||||
else:
|
||||
return self.capabilities.check(capability)
|
||||
|
||||
def setPassword(self, password):
|
||||
def setPassword(self, password, hashed=False):
|
||||
"""Sets the user's password."""
|
||||
if hashed or self.hashed:
|
||||
self.hashed = True
|
||||
self.password = utils.saltHash(password)
|
||||
else:
|
||||
self.password = password
|
||||
|
||||
def checkPassword(self, password):
|
||||
"""Checks the user's password."""
|
||||
if self.hashed:
|
||||
(salt, _) = self.password.split('|')
|
||||
return (self.password == utils.saltHash(password, salt=salt))
|
||||
else:
|
||||
return (self.password == password)
|
||||
|
||||
def checkHostmask(self, hostmask, useAuth=True):
|
||||
|
@ -412,7 +412,7 @@ def saltHash(password, salt=None, hash='sha'):
|
||||
hasher = md5.md5
|
||||
elif hash == 'sha':
|
||||
hasher = sha.sha
|
||||
return salt + hasher(salt + password).hexdigest()
|
||||
return '|'.join([salt, hasher(salt + password).hexdigest()])
|
||||
|
||||
class IterableMap(object):
|
||||
"""Define .iteritems() in a class and subclass this to get the other iters.
|
||||
|
@ -54,5 +54,15 @@ class UserTestCase(PluginTestCase, PluginDocumentation):
|
||||
self.assertError('changeusername foo bar')
|
||||
self.assertNotError('changeusername foo baz')
|
||||
|
||||
def testSetpassword(self):
|
||||
self.prefix = self.prefix1
|
||||
self.assertNotError('register foo bar')
|
||||
self.assertEqual(ircdb.users.getUser(self.prefix).password, 'bar')
|
||||
self.assertNotError('setpassword foo bar baz')
|
||||
self.assertEqual(ircdb.users.getUser(self.prefix).password, 'baz')
|
||||
self.assertNotError('setpassword --hashed foo baz biff')
|
||||
self.assertNotEqual(ircdb.users.getUser(self.prefix).password, 'biff')
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||
|
||||
|
@ -212,6 +212,13 @@ class IrcUserTestCase(unittest.TestCase):
|
||||
self.failUnless(u.checkPassword('foobar'))
|
||||
self.failIf(u.checkPassword('somethingelse'))
|
||||
|
||||
def testHashedPassword(self):
|
||||
u = ircdb.IrcUser()
|
||||
u.setPassword('foobar', hashed=True)
|
||||
self.failUnless(u.checkPassword('foobar'))
|
||||
self.failIf(u.checkPassword('somethingelse'))
|
||||
self.assertNotEqual(u.password, 'foobar')
|
||||
|
||||
def testHostmasks(self):
|
||||
prefix = 'foo!bar@baz'
|
||||
hostmasks = ['*!bar@baz', 'foo!*@*']
|
||||
|
@ -277,7 +277,8 @@ class UtilsTest(unittest.TestCase):
|
||||
|
||||
def testSaltHash(self):
|
||||
s = utils.saltHash('jemfinch')
|
||||
self.assertEqual(utils.saltHash('jemfinch', salt=s[:8]), s)
|
||||
(salt, hash) = s.split('|')
|
||||
self.assertEqual(utils.saltHash('jemfinch', salt=salt), s)
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user