diff options
Diffstat (limited to 'django/srpproject')
-rw-r--r-- | django/srpproject/srp/backends.py | 3 | ||||
-rw-r--r-- | django/srpproject/srp/views.py | 72 | ||||
-rw-r--r-- | django/srpproject/urls.py | 2 |
3 files changed, 55 insertions, 22 deletions
diff --git a/django/srpproject/srp/backends.py b/django/srpproject/srp/backends.py index 1f13173..8882973 100644 --- a/django/srpproject/srp/backends.py +++ b/django/srpproject/srp/backends.py @@ -19,6 +19,3 @@ class SRPBackend: return SRPUser.objects.get(pk=user_id) except SRPUser.DoesNotExist: return None - - - diff --git a/django/srpproject/srp/views.py b/django/srpproject/srp/views.py index 38d5503..8529fa9 100644 --- a/django/srpproject/srp/views.py +++ b/django/srpproject/srp/views.py @@ -2,7 +2,7 @@ from django.http import HttpResponse -from srp import models +from django.contrib.auth.models import User ### ### General methods @@ -41,7 +41,7 @@ def register_page(request): # Step 1. A client submits a username. If the username is available, we generate a salt, store it, and return it. # Otherwise, we return an error. def register_salt(request): - if models.SRPUser.objects.filter(username=request.POST["I"]).count() > 0: + if User.objects.filter(username=request.POST["I"]).count() > 0: return HttpResponse("<error>Username already in use</error>", mimetype="text/xml") request.session["srp_name"] = request.POST["I"] request.session["srp_salt"] = generate_salt() @@ -50,7 +50,8 @@ def register_salt(request): # Step 2. The client creates the password verifier and sends it to the server, along with a username. def register_user(request): from django.contrib import auth - models.SRPUser(salt=request.session["srp_salt"], username=request.session["srp_name"], verifier=request.POST["v"]).save() + from srp.models import SRPUser + SRPUser(salt=request.session["srp_salt"], username=request.session["srp_name"], verifier=request.POST["v"]).save() del request.session["srp_salt"] del request.session["srp_name"] return HttpResponse("<ok/>", mimetype="text/xml"); @@ -65,6 +66,7 @@ def register_user(request): # The server responds with the salt and public ephemeral key, B def handshake(request): import random, hashlib + from srp.models import SRPUser randomgen = random.SystemRandom() request.session["srp_I"] = request.POST["I"] A = int(request.POST["A"], 16) @@ -72,15 +74,28 @@ def handshake(request): g = 2 N = 125617018995153554710546479714086468244499594888726646874671447258204721048803 k = 88846390364205216646376352624313659232912717719075174937149043299744712465496 + upgrade = False if A % N == 0: return HttpResponse("<error>Invalid ephemeral key.</error>", mimetype="text/xml") else: try: - user = models.SRPUser.objects.get(username=request.session["srp_I"]) - salt = user.salt - v = int(user.verifier, 16) + user = User.objects.get(username=request.session["srp_I"]) + try: + user = user.srpuser + salt = user.salt + v = int(user.verifier, 16) + # The auth.User exists, but the SRPUser does not + # We need to create an SRPUser to correspond to that auth.User + # Initially, the verifier will be based on the known hash of the password + except SRPUser.DoesNotExist: + salt = generate_salt() + algo, dsalt, hashpass = user.password.split("$") + upgrade = True + x = int(hashlib.sha256(salt + hashlib.sha256(user.username + ":" + hashpass).hexdigest()).hexdigest(), 16) + v = pow(2, x, N) + # We don't want to leak that the username doesn't exist. Make up a fake salt and verifier. - except models.SRPUser.DoesNotExist: + except User.DoesNotExist: salt, x = generate_fake_salt(request.POST["I"]) v = pow(g, x, N) @@ -91,31 +106,26 @@ def handshake(request): u = int(hashlib.sha256("%s%s" % (hex(A)[2:-1],hex(B)[2:-1])).hexdigest(), 16) if B % N != 0 and u % N != 0: break - response = "<r s='%s' B='%s' />" % (salt, hex(B)[2:-1]) # Ideally, we could return this response and then calculate M concurrently with the user # Unfortunately, django isn't designed to do computations after responding. # Maybe someone will find a way. S = pow(A*pow(v,u,N), b, N) request.session["srp_S"] = hex(S)[2:-1] Mstr = "%s%s%s" % (hex(A)[2:-1],hex(B)[2:-1],hex(S)[2:-1]) - response = "<r s='%s' B='%s' />" % (salt, hex(B)[2:-1]) request.session["srp_M"] = hashlib.sha256(Mstr).hexdigest() + response = "<r s='%s' B='%s'%s />" % (salt, hex(B)[2:-1], " a='%s' d='%s'" % (algo, dsalt) if upgrade else "") return HttpResponse(response, mimetype="text/xml") # Step 2: The client sends its proof of S. The server confirms, and sends its proof of S. def verify(request): import hashlib from django.contrib.auth import login, authenticate - try: - user = authenticate(username=request.session["srp_I"], M=(request.POST["M"], request.session["srp_M"])) - if user: - response = "<M>%s</M>" % hashlib.sha256("%s%s%s" % (request.session["srp_A"], request.session["srp_M"], request.session["srp_S"])).hexdigest() - login(request, user) - else: - response = "<error>Invalid username or password.</error>" - except models.SRPUser.DoesNotExist: - # This should only happen when authentication is successful with SRP, but the user isn't in the auth table. - response = "<error>Authentication failed. This is likely a server problem.</error>" + user = authenticate(username=request.session["srp_I"], M=(request.POST["M"], request.session["srp_M"])) + if user: + response = "<M>%s</M>" % hashlib.sha256("%s%s%s" % (request.session["srp_A"], request.session["srp_M"], request.session["srp_S"])).hexdigest() + login(request, user) + else: + response = "<error>Invalid username or password.</error>" try: del request.session["srp_I"] @@ -125,3 +135,27 @@ def verify(request): except KeyError: pass return HttpResponse(response, mimetype="text/xml") + +def upgrade_auth(request): + import hashlib + if request.POST["M"] == request.session["srp_M"]: + response = "<M>%s</M>" % hashlib.sha256("%s%s%s" % (request.session["srp_A"], request.session["srp_M"], request.session["srp_S"])).hexdigest() + request.session["srp_preauth"] = True + else: + response = "<error>Invalid username or password.</error>" + return HttpResponse(response, mimetype="text/xml") + +def upgrade_add_verifier(request): + from srp.models import SRPUser + from django.contrib.auth.models import User + import hashlib + salt = generate_salt() + x = int(hashlib.sha256(salt + hashlib.sha256("%s:%s" % (request.session["srp_I"], request.POST["p"])).hexdigest()).hexdigest(), 16) + user = User.objects.get(username=request.session["srp_I"]) + srpuser = SRPUser() + srpuser.__dict__.update(user.__dict__) + srpuser.verifier = hex(pow(2, x, 125617018995153554710546479714086468244499594888726646874671447258204721048803))[2:-1] + srpuser.salt = salt + srpuser.password = "" + srpuser.save() + return HttpResponse("<ok/>", mimetype="text/xml") diff --git a/django/srpproject/urls.py b/django/srpproject/urls.py index a2da712..550676e 100644 --- a/django/srpproject/urls.py +++ b/django/srpproject/urls.py @@ -21,4 +21,6 @@ urlpatterns = patterns('', (r'^srp/authenticate/$', views.verify), (r'^srp/login/$', views.login_page), (r'^srp/register/$', views.register_page), + (r'^srp/upgrade/authenticate/$', views.upgrade_auth), + (r'^srp/upgrade/verifier/$', views.upgrade_add_verifier), ) |