Update Copyright header point to COPYING file
[cascardo/ipsilon.git] / ipsilon / login / authpam.py
1 # Copyright (C) 2013 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 import config as pconfig
7 import pam
8 import subprocess
9
10
11 class Pam(LoginFormBase):
12
13     def _authenticate(self, username, password):
14         if self.lm.service_name:
15             ok = pam.authenticate(username, password, self.lm.service_name)
16         else:
17             ok = pam.authenticate(username, password)
18
19         if ok:
20             self.log("User %s successfully authenticated." % username)
21             return username
22
23         self.log("User %s failed authentication." % username)
24         return None
25
26     def POST(self, *args, **kwargs):
27         username = kwargs.get("login_name")
28         password = kwargs.get("login_password")
29         user = None
30         error = None
31
32         if username and password:
33             user = self._authenticate(username, password)
34             if user:
35                 return self.lm.auth_successful(self.trans, user, 'password')
36             else:
37                 error = "Authentication failed"
38                 self.error(error)
39         else:
40             error = "Username or password is missing"
41             self.error("Error: " + error)
42
43         context = self.create_tmpl_context(
44             username=username,
45             error=error,
46             error_password=not password,
47             error_username=not username
48         )
49         self.lm.set_auth_error()
50         return self._template('login/form.html', **context)
51
52
53 class LoginManager(LoginManagerBase):
54
55     def __init__(self, *args, **kwargs):
56         super(LoginManager, self).__init__(*args, **kwargs)
57         self.name = 'pam'
58         self.path = 'pam'
59         self.page = None
60         self.description = """
61 Form based login Manager that uses the system's PAM infrastructure
62 for authentication. """
63         self.new_config(
64             self.name,
65             pconfig.String(
66                 'service name',
67                 'The name of the PAM service used to authenticate.',
68                 'remote'),
69             pconfig.String(
70                 'username text',
71                 'Text used to ask for the username at login time.',
72                 'Username'),
73             pconfig.String(
74                 'password text',
75                 'Text used to ask for the password at login time.',
76                 'Password'),
77             pconfig.String(
78                 'help text',
79                 'Text used to guide the user at login time.',
80                 'Provide your Username and Password')
81         )
82
83     @property
84     def service_name(self):
85         return self.get_config_value('service name')
86
87     @property
88     def help_text(self):
89         return self.get_config_value('help text')
90
91     @property
92     def username_text(self):
93         return self.get_config_value('username text')
94
95     @property
96     def password_text(self):
97         return self.get_config_value('password text')
98
99     def get_tree(self, site):
100         self.page = Pam(site, self, 'login/pam')
101         return self.page
102
103
104 class Installer(LoginManagerInstaller):
105
106     def __init__(self, *pargs):
107         super(Installer, self).__init__()
108         self.name = 'pam'
109         self.pargs = pargs
110
111     def install_args(self, group):
112         group.add_argument('--pam', choices=['yes', 'no'], default='no',
113                            help='Configure PAM authentication')
114         group.add_argument('--pam-service', action='store', default='remote',
115                            help='PAM service name to use for authentication')
116
117     def configure(self, opts):
118         if opts['pam'] != 'yes':
119             return
120
121         # Add configuration data to database
122         po = PluginObject(*self.pargs)
123         po.name = 'pam'
124         po.wipe_data()
125         po.wipe_config_values()
126         config = {'service name': opts['pam_service']}
127         po.save_plugin_config(config)
128
129         # Update global config to add login plugin
130         po.is_enabled = True
131         po.save_enabled_state()
132
133         # for selinux enabled platforms, ignore if it fails just report
134         try:
135             subprocess.call(['/usr/sbin/setsebool', '-P',
136                              'httpd_mod_auth_pam=on',
137                              'httpd_tmp_exec=on'])
138         except Exception:  # pylint: disable=broad-except
139             pass