Implement change registration
[cascardo/ipsilon.git] / ipsilon / login / authform.py
1 # Copyright (C) 2014 Ipsilon project Contributors, for license see COPYING
2
3 from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
4     LoginManagerInstaller
5 from ipsilon.util.plugin import PluginObject
6 from ipsilon.util.user import UserSession
7 from ipsilon.util import config as pconfig
8 from string import Template
9 import cherrypy
10 import subprocess
11
12
13 class Form(LoginFormBase):
14
15     def POST(self, *args, **kwargs):
16         us = UserSession()
17         us.remote_login()
18         user = us.get_user()
19         if not user.is_anonymous:
20             return self.lm.auth_successful(self.trans, user.name, 'password')
21         else:
22             try:
23                 error = cherrypy.request.headers['EXTERNAL_AUTH_ERROR']
24             except KeyError:
25                 error = "Unknown error using external authentication"
26                 cherrypy.log.error("Error: %s" % error)
27             return self.lm.auth_failed(self.trans)
28
29
30 class LoginManager(LoginManagerBase):
31
32     def __init__(self, *args, **kwargs):
33         super(LoginManager, self).__init__(*args, **kwargs)
34         self.name = 'form'
35         self.path = 'form'
36         self.page = None
37         self.service_name = 'form'
38         self.description = """
39 Form based login Manager. Relies on mod_intercept_form_submit plugin for
40  actual authentication. """
41         self.new_config(
42             self.name,
43             pconfig.String(
44                 'username text',
45                 'Text used to ask for the username at login time.',
46                 'Username'),
47             pconfig.String(
48                 'password text',
49                 'Text used to ask for the password at login time.',
50                 'Password'),
51             pconfig.String(
52                 'help text',
53                 'Text used to guide the user at login time.',
54                 'Insert your Username and Password and then submit.')
55         )
56
57     @property
58     def help_text(self):
59         return self.get_config_value('help text')
60
61     @property
62     def username_text(self):
63         return self.get_config_value('username text')
64
65     @property
66     def password_text(self):
67         return self.get_config_value('password text')
68
69     def get_tree(self, site):
70         self.page = Form(site, self, 'login/form')
71         return self.page
72
73
74 CONF_TEMPLATE = """
75 LoadModule intercept_form_submit_module modules/mod_intercept_form_submit.so
76 LoadModule authnz_pam_module modules/mod_authnz_pam.so
77
78 <Location /${instance}/login/form>
79   InterceptFormPAMService ${service}
80   InterceptFormLogin login_name
81   InterceptFormPassword login_password
82   # InterceptFormLoginSkip admin
83   # InterceptFormClearRemoteUserForSkipped on
84   InterceptFormPasswordRedact on
85 </Location>
86 """
87
88
89 class Installer(LoginManagerInstaller):
90
91     def __init__(self, *pargs):
92         super(Installer, self).__init__()
93         self.name = 'form'
94         self.pargs = pargs
95
96     def install_args(self, group):
97         group.add_argument('--form', choices=['yes', 'no'], default='no',
98                            help='Configure External Form authentication')
99         group.add_argument('--form-service', action='store', default='remote',
100                            help='PAM service name to use for authentication')
101
102     def configure(self, opts, changes):
103         if opts['form'] != 'yes':
104             return
105
106         confopts = {'instance': opts['instance'],
107                     'service': opts['form_service']}
108
109         tmpl = Template(CONF_TEMPLATE)
110         hunk = tmpl.substitute(**confopts)
111         with open(opts['httpd_conf'], 'a') as httpd_conf:
112             httpd_conf.write(hunk)
113
114         # Add configuration data to database
115         po = PluginObject(*self.pargs)
116         po.name = 'form'
117         po.wipe_data()
118         po.wipe_config_values()
119
120         # Update global config to add login plugin
121         po.is_enabled = True
122         po.save_enabled_state()
123
124         # for selinux enabled platforms, ignore if it fails just report
125         try:
126             subprocess.call(['/usr/sbin/setsebool', '-P',
127                              'httpd_mod_auth_pam=on'])
128         except Exception:  # pylint: disable=broad-except
129             pass