PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/gail/main.py

http://google-apps-improved-login.googlecode.com/
Python | 250 lines | 249 code | 1 blank | 0 comment | 1 complexity | 9f0298e00e69d70f915aaaa21c13cf3e MD5 | raw file
  1. from google.appengine.ext import webapp
  2. from google.appengine.ext.webapp.util import run_wsgi_app
  3. import wsgiref.handlers
  4. import gdata.alt.appengine
  5. import os
  6. import gdata.apps.service
  7. import ds_settings
  8. import utils
  9. import time
  10. from random import randint
  11. import ds_templates
  12. import gdata.tlslite.utils.keyfactory
  13. from base64 import b64encode
  14. import filestore
  15. class ShowLogin(webapp.RequestHandler):
  16. def get(self):
  17. domain = os.environ['AUTH_DOMAIN']
  18. if self.request.get('SAMLRequest') == '':
  19. utils.gailRedirect(self, 'https://mail.google.com/a/' + domain)
  20. return
  21. requestdata = utils.unpackSAMLRequest(self, self.request.get('SAMLRequest'))
  22. age = int(requestdata['requestage'])
  23. if (age < 0) or (age > 590): # is our SAMLRequest old or invalid?
  24. utils.gailRedirect(self, 'https://mail.google.com/a/' + domain)
  25. template_values = {
  26. #we want to refresh 10 sec before SAMLRequest expires
  27. 'refresh': int(590 - age),
  28. 'samlrequest': self.request.get('SAMLRequest'),
  29. 'relaystate': self.request.get('RelayState'),
  30. 'message': self.request.get('Error'),
  31. 'message_color': 'red',
  32. 'domain': domain,
  33. 'appspot_domain': os.environ['APPLICATION_ID']+'.appspot.com'
  34. }
  35. self.response.out.write(ds_templates.templateRender('login.html', template_values))
  36. class DoLogin(webapp.RequestHandler):
  37. def post(self):
  38. becomeattempt = False
  39. loginvalue = str(self.request.get('username'))
  40. if os.environ['HTTP_REFERER']:
  41. orig_url = os.environ['HTTP_REFERER']
  42. else:
  43. orig_url = str(os.environ['PATH_INFO'])+'?'+str(os.environ['QUERY_STRING'])
  44. if orig_url.find('&Error') != -1:
  45. orig_url = orig_url[0:orig_url.find('&Error')]
  46. if loginvalue.find('+') != -1:
  47. username = loginvalue[0:(loginvalue.find('+'))]
  48. loginuser = loginvalue[(loginvalue.find('+') + 1):]
  49. becomeattempt = True
  50. else:
  51. username = loginvalue
  52. password = str(self.request.get('password'))
  53. domain = os.environ['AUTH_DOMAIN']
  54. apps = gdata.apps.service.AppsService(email=username+'@'+domain, domain=domain, password=password)
  55. gdata.alt.appengine.run_on_appengine(apps, store_tokens=True, single_user_mode=True)
  56. try:
  57. apps.ProgrammaticLogin()
  58. except gdata.service.BadAuthentication:
  59. utils.gailRedirect(self, orig_url + '&Error=Unknown%20Username%20or%20Password')
  60. except gdata.service.CaptchaRequired:
  61. utils.gailRedirect(self, orig_url + '&Error=Your%20account%20is%20locked.%20%3Ca%20href%3D%22https%3A//www.google.com/a/'+domain+'/UnlockCaptcha%22%3EClick%20here%20to%20unlock%20it.%3C/a%3E')
  62. except:
  63. utils.gailRedirect(self, orig_url + '&Error=Unknown%20Error.%20Please%20Try%20Again.')
  64. if becomeattempt:
  65. if utils.userCanBecomeUser(apps, username, loginuser):
  66. username = loginuser
  67. else:
  68. utils.gailRedirect(self, orig_url + '&Error=Unknown%20Username%20or%20Password')
  69. self.response.out.write(utils.createAutoPostResponse(self, self.request.get('SAMLRequest'), username))
  70. class ShowPassword(webapp.RequestHandler):
  71. def get(self):
  72. template_values = {
  73. 'domain': os.environ['AUTH_DOMAIN'],
  74. 'message': self.request.get('Message'),
  75. 'message_color': self.request.get('message_color'),
  76. 'appspot_domain': os.environ['APPLICATION_ID']+'.appspot.com'
  77. }
  78. self.response.out.write(ds_templates.templateRender('password.html', template_values))
  79. class DoPassword(webapp.RequestHandler):
  80. def post(self):
  81. domain = ds_settings.getSetting('domain')
  82. if os.environ['HTTP_REFERER']:
  83. orig_url = os.environ['HTTP_REFERER']
  84. if orig_url.find('?') != -1:
  85. orig_url = orig_url[0:orig_url.find('?')]
  86. else:
  87. orig_url = '/password'
  88. username = str(self.request.get('username'))
  89. cpassword = str(self.request.get('cpassword'))
  90. npassword1 = str(self.request.get('npassword1'))
  91. npassword2 = str(self.request.get('npassword2'))
  92. if npassword1 != npassword2:
  93. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Your%20Passwords%20Do%20Not%20Match')
  94. if len(npassword1) < 6:
  95. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Your%20New%20Password%20Is%20To%20Short')
  96. apps = gdata.apps.service.AppsService(email=username+'@'+domain, domain=domain, password=cpassword)
  97. gdata.alt.appengine.run_on_appengine(apps, store_tokens=True, single_user_mode=True)
  98. try:
  99. apps.ProgrammaticLogin()
  100. except gdata.service.BadAuthentication:
  101. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Unknown%20Username%20or%20Password')
  102. except gdata.service.CaptchaRequired:
  103. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Your%20account%20is%20locked.%20%3Ca%20href%3D%22https%3A//www.google.com/a/'+domain+'/UnlockCaptcha%22%3EClick%20here%20to%20unlock%20it.%3C/a%3E')
  104. except:
  105. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Unknown%20Error%20Confirming%20Password')
  106. apps2 = gdata.apps.service.AppsService(email=ds_settings.getSetting('adminuser')+'@'+domain, domain=domain, password=ds_settings.getSetting('adminpass'))
  107. gdata.alt.appengine.run_on_appengine(apps2, store_tokens=True, single_user_mode=True)
  108. try:
  109. apps2.ProgrammaticLogin()
  110. except:
  111. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Unknown%20Error%20Changing%20Password.%20Please%20Report%This%To%Your%Administrator')
  112. user = apps2.RetrieveUser(username)
  113. user.login.password = npassword1
  114. try:
  115. apps2.UpdateUser(username, user)
  116. except gdata.apps.service.AppsForYourDomainException , e:
  117. if e[0]['body'].find('InvalidPassword'):
  118. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Your%20New%20Password%20Is%20Invalid.%20Try%20A%20Longer%20Password.')
  119. else:
  120. utils.gailRedirect(self, orig_url + '?message_color=red&Message=Unknown%20Error%20Attempting%20To%20Change%20Password.%20Please%20Report%20This%20To%20Your%20Administrator')
  121. utils.gailRedirect(self, orig_url + '?message_color=green&Message=Your%20password%20was%20changed%20successfully.')
  122. class DoGailAdmin(webapp.RequestHandler):
  123. def get(self):
  124. template_values = {}
  125. template_values['appspot_domain'] = os.environ['APPLICATION_ID']+'.appspot.com'
  126. template_values['domain'] = os.environ['AUTH_DOMAIN']
  127. template_values['adminuser'] = ds_settings.getSetting('adminuser')
  128. template_values['adminsbecomeusers'] = ds_settings.getSetting('adminsbecomeusers')
  129. template_values['usersbecomeusers'] = ds_settings.getSetting('usersbecomeusers')
  130. template_values['adminpass'] = '*****'
  131. privkey = ds_settings.getSetting('privkey')
  132. if privkey != None:
  133. gailpubkey = utils.getPubkey(self, privkey)
  134. else:
  135. gailpubkey = 'failed'
  136. googlepubkey = utils.GetGooglePubKey(self)
  137. if gailpubkey == 'failed':
  138. template_values['keymatch'] = 'GAIL has no keys!'
  139. elif googlepubkey == 'failed':
  140. template_values['keymatch'] = 'Failed to get Google Public Key'
  141. elif gailpubkey == googlepubkey:
  142. template_values['keymatch'] = 'Yes'
  143. else:
  144. template_values['keymatch'] = 'No'
  145. self.response.out.write(ds_templates.templateRender('gailadmin.html', template_values))
  146. def post(self):
  147. for name in self.request.arguments():
  148. if name == 'adminpass':
  149. if len(self.request.get(name)) < 6:
  150. continue;
  151. if name == 'Save':
  152. continue;
  153. value = self.request.get(name)
  154. ds_settings.setSetting(name, value)
  155. utils.gailRedirect(self, '/gailadmin')
  156. class DoPrivKey(webapp.RequestHandler):
  157. def get(self):
  158. privkey = utils.generatePrivkey(self)
  159. ds_settings.setSetting('privkey', privkey)
  160. privkey_ver = time.strftime('%y-%m-%d-%H-%M-%S')
  161. ds_settings.setSetting('privkey_ver', privkey_ver)
  162. utils.gailRedirect(self, '/gailadmin')
  163. class DoPubKey(webapp.RequestHandler):
  164. def get(self):
  165. privkey = ds_settings.getSetting('privkey')
  166. privkey_ver = ds_settings.getSetting('privkey_ver')
  167. pubkey = utils.getPubkey(self, privkey)
  168. self.response.headers['Content-Type'] = 'application/x-x509-user-cert'
  169. self.response.headers['Content-Disposition'] = 'attachment; filename="'+privkey_ver+'.der"'
  170. self.response.out.write(pubkey)
  171. class DoUpdateGoogleSSO(webapp.RequestHandler):
  172. def get(self):
  173. privkey = ds_settings.getSetting('privkey')
  174. pubkey = utils.getPubkey(self, privkey)
  175. gailUrl = 'https://'+os.environ['APPLICATION_ID']+'.appspot.com/'
  176. utils.putGoogleSSO(gailUrl, pubkey)
  177. utils.gailRedirect(self, '/gailadmin')
  178. class DoEditTemplates(webapp.RequestHandler):
  179. def get(self):
  180. template_values = {}
  181. template_values['appspot_domain'] = os.environ['APPLICATION_ID']+'.appspot.com'
  182. template_values['domain'] = os.environ['AUTH_DOMAIN']
  183. template_values['login_template_data'] = ds_templates.getTemplate('login.html')
  184. template_values['password_template_data'] = ds_templates.getTemplate('password.html')
  185. template_values['filelist'] = filestore.getFileList()
  186. self.response.out.write(ds_templates.templateRender('edit-templates.html', template_values))
  187. def post(self):
  188. login_template_data = str(self.request.get('login-html'))
  189. if str(self.request.get('resetloginpage')) == 'on':
  190. login_template_data = open('templates/login.html').read()
  191. ds_templates.updateTemplate('login.html', login_template_data)
  192. password_template_data = str(self.request.get('password-html'))
  193. if str(self.request.get('resetpasswordpage')) == 'on':
  194. password_template_data = open('templates/password.html').read()
  195. ds_templates.updateTemplate('password.html', password_template_data)
  196. utils.gailRedirect(self, '/edittemplates')
  197. class PutDynamicFile(webapp.RequestHandler):
  198. def post(self):
  199. file_data = self.request.get('file')
  200. file_name = self.request.body_file.vars['file'].filename
  201. if len(file_name) > 12:
  202. return
  203. allowedchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_'
  204. for i in file_name[:]:
  205. if allowedchars.find(i) == -1:
  206. return
  207. file_type = self.request.body_file.vars['file'].headers['content-type']
  208. filestore.setFile(file_name, file_type, file_data)
  209. utils.gailRedirect(self, '/edittemplates')
  210. class DelDynamicFile(webapp.RequestHandler):
  211. def get(self):
  212. file_name = os.environ['PATH_INFO'][11:]
  213. if len(file_name) > 15:
  214. return
  215. allowedchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_'
  216. for i in file_name[:]:
  217. if allowedchars.find(i) == -1:
  218. return
  219. file = filestore.delFile(file_name)
  220. utils.gailRedirect(self, '/edittemplates')
  221. application = webapp.WSGIApplication([('/password', ShowPassword),
  222. ('/dopassword', DoPassword),
  223. ('/dologin', DoLogin),
  224. ('/', ShowLogin),
  225. ('/gailadmin', DoGailAdmin),
  226. ('/newprivkey', DoPrivKey),
  227. ('/getpubkey', DoPubKey),
  228. ('/updategooglesso', DoUpdateGoogleSSO),
  229. ('/edittemplates', DoEditTemplates),
  230. ('/upload-dfile', PutDynamicFile),
  231. ('/del-dfile/.*', DelDynamicFile)],
  232. debug=True)
  233. def main():
  234. run_wsgi_app(application)
  235. if __name__ == "__main__":
  236. main()