You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
5.0 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Laurent Mignon
  5. # Copyright 2014 'ACSONE SA/NV'
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. from openerp import SUPERUSER_ID
  22. from openerp.addons.web import http
  23. from openerp.addons.web.controllers import main
  24. from openerp.modules.registry import RegistryManager
  25. from .. import utils
  26. import random
  27. import logging
  28. import openerp.tools.config as config
  29. _logger = logging.getLogger(__name__)
  30. class Session(main.Session):
  31. _cp_path = "/web/session"
  32. _REQUIRED_ATTRIBUTES = ['HTTP_REMOTE_USER']
  33. _OPTIONAL_ATTRIBUTES = []
  34. def _get_db(self, db):
  35. if db is not None and len(db) > 0:
  36. return db
  37. db = config['db_name']
  38. if db is None or len(db) == 0:
  39. _logger.error("No db found for SSO. Specify one in the URL using parameter "
  40. "db=? or provide a default one in the configuration")
  41. raise http.AuthenticationError()
  42. def _get_user_id_from_attributes(self, res_users, cr, attrs):
  43. login = attrs.get('HTTP_REMOTE_USER', None)
  44. user_ids = res_users.search(cr, SUPERUSER_ID, [('login', '=', login), ('active', '=', True)])
  45. assert len(user_ids) < 2
  46. if user_ids:
  47. return user_ids[0]
  48. return None
  49. def _get_attributes_form_header(self, req):
  50. attrs = {}
  51. all_attrs = self._REQUIRED_ATTRIBUTES + self._OPTIONAL_ATTRIBUTES
  52. headers = req.httprequest.headers.environ
  53. for attr in all_attrs:
  54. value = headers.get(attr, None)
  55. if value is not None:
  56. attrs[attr] = value
  57. attrs_found = set(attrs.keys())
  58. attrs_missing = set(all_attrs) - attrs_found
  59. if len(attrs_found) > 0:
  60. _logger.debug("Fields '%s' not found in http headers\n %s", attrs_missing, headers)
  61. missings = set(self._REQUIRED_ATTRIBUTES) - attrs_found
  62. if len(missings) > 0:
  63. _logger.error("Required fields '%s' not found in http headers\n %s", missings, headers)
  64. return attrs
  65. def _bind_http_remote_user(self, req, db_name):
  66. db_name = self._get_db(db_name)
  67. try:
  68. registry = RegistryManager.get(db_name)
  69. with registry.cursor() as cr:
  70. modules = registry.get('ir.module.module')
  71. installed = modules.search_count(cr, SUPERUSER_ID, ['&',
  72. ('name', '=', 'auth_from_http_remote_user'),
  73. ('state', '=', 'installed')]) == 1
  74. if not installed:
  75. return
  76. config = registry.get('auth_from_http_remote_user.config.settings')
  77. # get parameters for SSO
  78. default_login_page_disabled = config.is_default_login_page_disabled(cr, SUPERUSER_ID, None)
  79. # get the user
  80. res_users = registry.get('res.users')
  81. attrs = self._get_attributes_form_header(req)
  82. user_id = self._get_user_id_from_attributes(res_users, cr, attrs)
  83. if user_id is None:
  84. if default_login_page_disabled:
  85. raise http.AuthenticationError()
  86. return
  87. # generate a specific key for authentication
  88. key = randomString(utils.KEY_LENGTH, '0123456789abcdef')
  89. res_users.write(cr, SUPERUSER_ID, [user_id], {'sso_key': key})
  90. login = res_users.browse(cr, SUPERUSER_ID, user_id).login
  91. req.session.bind(db_name, user_id, login, key)
  92. except http.AuthenticationError, e:
  93. raise e
  94. except Exception, e:
  95. _logger.error("Error binding Http Remote User session", exc_info=True)
  96. raise e
  97. @http.jsonrequest
  98. def get_http_remote_user_session_info(self, req, db):
  99. if not req.session._login:
  100. self._bind_http_remote_user(req, db)
  101. return self.session_info(req)
  102. randrange = random.SystemRandom().randrange
  103. def randomString(length, chrs):
  104. """Produce a string of length random bytes, chosen from chrs."""
  105. n = len(chrs)
  106. return ''.join([chrs[randrange(n)] for _ in xrange(length)])