2828import base64
2929import json
3030import socket
31- import urlparse
32- import urllib
31+ from urllib . parse import urlparse , urlencode , parse_qs
32+ import requests
3333from Crypto .Cipher import AES
3434from Crypto .Hash import SHA
3535from Crypto import Random
@@ -53,17 +53,17 @@ def login(request):
5353 # Put together an url-encoded dict of parameters we're getting back,
5454 # including a small nonce at the beginning to make sure it doesn't
5555 # encrypt the same way every time.
56- s = "t=%s&%s" % (int (time .time ()), urllib . urlencode ({'r' : request .GET ['next' ]}))
56+ s = "t=%s&%s" % (int (time .time ()), urlencode ({'r' : request .GET ['next' ]}))
5757 # Now encrypt it
5858 r = Random .new ()
5959 iv = r .read (16 )
60- encryptor = AES .new (SHA .new (settings .SECRET_KEY ).digest ()[:16 ], AES .MODE_CBC , iv )
60+ encryptor = AES .new (SHA .new (settings .SECRET_KEY . encode ( 'ascii' ) ).digest ()[:16 ], AES .MODE_CBC , iv )
6161 cipher = encryptor .encrypt (s + ' ' * (16 - (len (s ) % 16 ))) # pad to 16 bytes
6262
6363 return HttpResponseRedirect ("%s?d=%s$%s" % (
6464 settings .PGAUTH_REDIRECT ,
65- base64 .b64encode (iv , "-_" ),
66- base64 .b64encode (cipher , "-_" ),
65+ base64 .b64encode (iv , b "-_"). decode ( 'utf8' ),
66+ base64 .b64encode (cipher , b "-_"). decode ( 'utf8' ),
6767 ))
6868 else :
6969 return HttpResponseRedirect (settings .PGAUTH_REDIRECT )
@@ -80,7 +80,7 @@ def logout(request):
8080# Receive an authentication response from the main website and try
8181# to log the user in.
8282def auth_receive (request ):
83- if request .GET . get ( 's' , '' ) == ' logout' :
83+ if 's' in request .GET and request . GET [ 's' ] == " logout" :
8484 # This was a logout request
8585 return HttpResponseRedirect ('/' )
8686
@@ -93,11 +93,11 @@ def auth_receive(request):
9393 decryptor = AES .new (base64 .b64decode (settings .PGAUTH_KEY ),
9494 AES .MODE_CBC ,
9595 base64 .b64decode (str (request .GET ['i' ]), "-_" ))
96- s = decryptor .decrypt (base64 .b64decode (str (request .GET ['d' ]), "-_" )).rstrip (' ' )
96+ s = decryptor .decrypt (base64 .b64decode (str (request .GET ['d' ]), "-_" )).rstrip (b' ' ). decode ( 'utf8 ' )
9797
9898 # Now un-urlencode it
9999 try :
100- data = urlparse . parse_qs (s , strict_parsing = True )
100+ data = parse_qs (s , strict_parsing = True )
101101 except ValueError :
102102 return HttpResponse ("Invalid encrypted data received." , status = 400 )
103103
@@ -134,7 +134,7 @@ def auth_receive(request):
134134
135135This is almost certainly caused by some legacy data in our database.
136136Please send an email to [email protected] , indicating the username 137- and email address from above, and we'll manually marge the two accounts
137+ and email address from above, and we'll manually merge the two accounts
138138for you.
139139
140140We apologize for the inconvenience.
@@ -158,12 +158,12 @@ def auth_receive(request):
158158 # redirect the user.
159159 if 'd' in data :
160160 (ivs , datas ) = data ['d' ][0 ].split ('$' )
161- decryptor = AES .new (SHA .new (settings .SECRET_KEY ).digest ()[:16 ],
161+ decryptor = AES .new (SHA .new (settings .SECRET_KEY . encode ( 'ascii' ) ).digest ()[:16 ],
162162 AES .MODE_CBC ,
163- base64 .b64decode (ivs , "-_" ))
164- s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (' ' )
163+ base64 .b64decode (ivs , b "-_" ))
164+ s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b' ' ). decode ( 'utf8 ' )
165165 try :
166- rdata = urlparse . parse_qs (s , strict_parsing = True )
166+ rdata = parse_qs (s , strict_parsing = True )
167167 except ValueError :
168168 return HttpResponse ("Invalid encrypted data received." , status = 400 )
169169 if 'r' in rdata :
@@ -191,18 +191,45 @@ def user_search(searchterm=None, userid=None):
191191 else :
192192 q = {'s' : searchterm }
193193
194- u = urllib .urlopen ('%ssearch/?%s' % (
195- settings .PGAUTH_REDIRECT ,
196- urllib .urlencode (q ),
197- ))
198- (ivs , datas ) = u .read ().split ('&' )
199- u .close ()
194+ r = requests .get ('{0}search/' .format (settings .PGAUTH_REDIRECT ),
195+ params = q ,
196+ )
197+ if r .status_code != 200 :
198+ return []
199+
200+ (ivs , datas ) = r .text .encode ('utf8' ).split (b'&' )
200201
201202 # Decryption time
202203 decryptor = AES .new (base64 .b64decode (settings .PGAUTH_KEY ),
203204 AES .MODE_CBC ,
204205 base64 .b64decode (ivs , "-_" ))
205- s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (' ' )
206+ s = decryptor .decrypt (base64 .b64decode (datas , "-_" )).rstrip (b' ' ). decode ( 'utf8 ' )
206207 j = json .loads (s )
207208
208209 return j
210+
211+
212+ # Import a user into the local authentication system. Will initially
213+ # make a search for it, and if anything other than one entry is returned
214+ # the import will fail.
215+ # Import is only supported based on userid - so a search should normally
216+ # be done first. This will result in multiple calls to the upstream
217+ # server, but they are cheap...
218+ # The call to this function should normally be wrapped in a transaction,
219+ # and this function itself will make no attempt to do anything about that.
220+ def user_import (uid ):
221+ u = user_search (userid = uid )
222+ if len (u ) != 1 :
223+ raise Exception ("Internal error, duplicate or no user found" )
224+
225+ u = u [0 ]
226+
227+ if User .objects .filter (username = u ['u' ]).exists ():
228+ raise Exception ("User already exists" )
229+
230+ User (username = u ['u' ],
231+ first_name = u ['f' ],
232+ last_name = u ['l' ],
233+ email = u ['e' ],
234+ password = 'setbypluginnotsha1' ,
235+ ).save ()
0 commit comments