Remove unused option from the FAS login plugin
[cascardo/ipsilon.git] / ipsilon / login / authform.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014  Simo Sorce <simo@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (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 General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 from ipsilon.login.common import LoginPageBase, LoginManagerBase
21 from ipsilon.login.common import FACILITY
22 from ipsilon.util.plugin import PluginObject
23 from ipsilon.util.user import UserSession
24 from string import Template
25 import cherrypy
26 import subprocess
27
28
29 class Form(LoginPageBase):
30
31     def GET(self, *args, **kwargs):
32         context = self.create_tmpl_context()
33         # pylint: disable=star-args
34         return self._template('login/pam.html', **context)
35
36     def POST(self, *args, **kwargs):
37         us = UserSession()
38         us.remote_login()
39         user = us.get_user()
40         if not user.is_anonymous:
41             return self.lm.auth_successful(user.name)
42         else:
43             try:
44                 error = cherrypy.request.headers['EXTERNAL_AUTH_ERROR']
45             except KeyError:
46                 error = "Unknown error using external authentication"
47                 cherrypy.log.error("Error: %s" % error)
48             return self.lm.auth_failed()
49
50     def root(self, *args, **kwargs):
51         op = getattr(self, cherrypy.request.method, self.GET)
52         if callable(op):
53             return op(*args, **kwargs)
54
55     def create_tmpl_context(self, **kwargs):
56         next_url = None
57         if self.lm.next_login is not None:
58             next_url = self.lm.next_login.path
59
60         context = {
61             "title": 'Login',
62             "action": '%s/login/form' % self.basepath,
63             "service_name": self.lm.service_name,
64             "username_text": self.lm.username_text,
65             "password_text": self.lm.password_text,
66             "description": self.lm.help_text,
67             "next_url": next_url,
68         }
69         context.update(kwargs)
70         return context
71
72
73 class LoginManager(LoginManagerBase):
74
75     def __init__(self, *args, **kwargs):
76         super(LoginManager, self).__init__(*args, **kwargs)
77         self.name = 'form'
78         self.path = 'form'
79         self.page = None
80         self.description = """
81 Form based login Manager. Relies on mod_intercept_form_submit plugin for
82  actual authentication. """
83         self._options = {
84             'service name': [
85                 """ The name of the PAM service used to authenticate. """,
86                 'string',
87                 'remote'
88             ],
89             'help text': [
90                 """ The text shown to guide the user at login time. """,
91                 'string',
92                 'Insert your Username and Password and then submit.'
93             ],
94             'username text': [
95                 """ The text shown to ask for the username in the form. """,
96                 'string',
97                 'Username'
98             ],
99             'password text': [
100                 """ The text shown to ask for the password in the form. """,
101                 'string',
102                 'Password'
103             ],
104         }
105
106     @property
107     def service_name(self):
108         return self.get_config_value('service name')
109
110     @property
111     def help_text(self):
112         return self.get_config_value('help text')
113
114     @property
115     def username_text(self):
116         return self.get_config_value('username text')
117
118     @property
119     def password_text(self):
120         return self.get_config_value('password text')
121
122     def get_tree(self, site):
123         self.page = Form(site, self)
124         return self.page
125
126
127 CONF_TEMPLATE = """
128 LoadModule intercept_form_submit_module modules/mod_intercept_form_submit.so
129 LoadModule authnz_pam_module modules/mod_authnz_pam.so
130
131 <Location /${instance}/login/form>
132   InterceptFormPAMService ${service}
133   InterceptFormLogin login_name
134   InterceptFormPassword login_password
135   # InterceptFormLoginSkip admin
136   # InterceptFormClearRemoteUserForSkipped on
137   InterceptFormPasswordRedact on
138 </Location>
139 """
140
141
142 class Installer(object):
143
144     def __init__(self):
145         self.name = 'form'
146         self.ptype = 'login'
147
148     def install_args(self, group):
149         group.add_argument('--form', choices=['yes', 'no'], default='no',
150                            help='Configure External Form authentication')
151         group.add_argument('--form-service', action='store', default='remote',
152                            help='PAM service name to use for authentication')
153
154     def configure(self, opts):
155         if opts['form'] != 'yes':
156             return
157
158         confopts = {'instance': opts['instance'],
159                     'service': opts['form_service']}
160
161         tmpl = Template(CONF_TEMPLATE)
162         hunk = tmpl.substitute(**confopts)  # pylint: disable=star-args
163         with open(opts['httpd_conf'], 'a') as httpd_conf:
164             httpd_conf.write(hunk)
165
166         # Add configuration data to database
167         po = PluginObject()
168         po.name = 'form'
169         po.wipe_data()
170         po.wipe_config_values(FACILITY)
171
172         # Update global config, put 'krb' always first
173         po.name = 'global'
174         globalconf = po.get_plugin_config(FACILITY)
175         if 'order' in globalconf:
176             order = globalconf['order'].split(',')
177         else:
178             order = []
179         order.append('form')
180         globalconf['order'] = ','.join(order)
181         po.set_config(globalconf)
182         po.save_plugin_config(FACILITY)
183
184         # for selinux enabled platforms, ignore if it fails just report
185         try:
186             subprocess.call(['/usr/sbin/setsebool', '-P',
187                              'httpd_mod_auth_pam=on'])
188         except Exception:  # pylint: disable=broad-except
189             pass