2 /** External authentication via LDAP for FusionForge
3 * Copyright 2003, Roland Mas <lolando@debian.org>
4 * Copyright 2004, Roland Mas <roland@gnurandal.com>
5 * The Gforge Group, LLC <http://gforgegroup.com/>
6 * Copyright 2004, Christian Bayle <bayle@debian.org>
7 * Copyright 2009-2010, Alain Peyrat, Alcatel-Lucent
8 * Copyright 2009, Chris Dalzell, OpenGameForge.org
9 * Copyright 2011, Roland Mas
11 * This file is part of FusionForge. FusionForge is free software;
12 * you can redistribute it and/or modify it under the terms of the
13 * GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the Licence, or (at your option)
17 * FusionForge is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 require_once $GLOBALS['gfcommon'].'include/User.class.php';
29 class AuthLDAPPlugin extends ForgeAuthPlugin {
30 protected $saved_login;
31 protected $saved_password;
32 protected $saved_data;
34 function AuthLDAPPlugin() {
36 $this->ForgeAuthPlugin();
37 $this->name = "authldap";
38 $this->text = "LDAP authentication";
40 $this->_addHook('display_auth_form');
41 $this->_addHook("check_auth_session");
42 $this->_addHook("fetch_authenticated_user");
43 $this->_addHook("sync_account_info");
44 $this->_addHook("close_auth_session");
46 $this->ldap_conn = false;
47 $this->saved_login = '';
48 $this->saved_password = '';
49 $this->saved_data = array();
51 $this->declareConfigVars();
54 function syncAccountInfo($params) {
55 if (!$this->syncDataOn($params['event'])) {
58 $n = $params['username'];
59 $data = $this->saved_data;
62 $data = $this->fetchDataForUser($n);
66 error_log("No data to sync from LDAP for username ".$n);
70 $u = user_get_object_by_name($n);
73 // No user by that name yet, let's create it
79 $user_data['unix_name'] = $n;
80 $user_data['firstname'] = '';
81 $user_data['lastname'] = '';
82 if ($this->saved_password == '') {
83 $user_data['password1'] = 'INVALID';
85 $user_data['password1'] = $this->saved_password;
87 $user_data['password2'] = $user_data['password1'];
88 $user_data['email'] = '';
89 $user_data['mail_site'] = 1;
90 $user_data['mail_va'] = 0;
91 $user_data['language_id'] = 1;
92 $user_data['timezone'] = 'GMT';
93 $user_data['jabber_address'] = '';
94 $user_data['jabber_only'] = 0;
95 $user_data['theme_id'] = 1;
96 $user_data['unix_box'] = '';
97 $user_data['address'] = '';
98 $user_data['address2'] = '';
99 $user_data['phone'] = '';
100 $user_data['fax'] = '';
101 $user_data['title'] = '';
102 $user_data['ccode'] = 'US';
105 foreach (explode(',', forge_get_config('mapping', $this->name))
107 list ($fffield, $ldapfield) = explode('=',$map_entry);
108 if (array_key_exists($ldapfield, $data)) {
109 $user_data[$fffield] = $data[$ldapfield][0];
113 if (!$u->create ($user_data['unix_name'],
114 $user_data['firstname'],
115 $user_data['lastname'],
116 $user_data['password1'],
117 $user_data['password2'],
119 $user_data['mail_site'],
120 $user_data['mail_va'],
121 $user_data['language_id'],
122 $user_data['timezone'],
123 $user_data['jabber_address'],
124 $user_data['jabber_only'],
125 $user_data['theme_id'],
126 $user_data['unix_box'],
127 $user_data['address'],
128 $user_data['address2'],
137 if (!$u->setStatus ('A')) {
142 if ($u->getStatus() == 'D') {
145 if ($this->saved_password != ''
146 && !session_check_credentials_in_database($this->saved_login, $this->saved_password, false)) {
147 $u->setPasswd($this->saved_password);
150 $mapped_data = array(
151 'username' => $u->getUnixName(),
152 'md5_password' => '',
153 'unix_password' => '',
154 'firstname' => $u->getFirstName(),
155 'lastname' => $u->getLastName(),
156 'email' => $u->getEmail(),
157 'phone' => $u->getPhone()
160 foreach (explode(',', forge_get_config('mapping', $this->name))
162 list ($fffield, $ldapfield) = explode('=',$map_entry);
163 if (array_key_exists($ldapfield, $data)) {
164 $mapped_data[$fffield] = $data[$ldapfield][0];
168 $u->update($mapped_data['firstname'],
169 $mapped_data['lastname'],
172 $u->getMailingsPrefs('site'),
173 $u->getMailingsPrefs('va'),
180 $mapped_data['phone'],
183 $u->getCountryCode(),
185 $mapped_data['email']);
187 $u->setMD5Passwd ($mapped_data['md5_password']);
188 $u->setUnixPasswd ($mapped_data['unix_password']);
191 function displayAuthForm(&$params) {
192 if (!$this->isRequired() && !$this->isSufficient()) {
195 $return_to = $params['return_to'];
201 $result .= _('Cookies must be enabled past this point.');
204 $result .= '<form action="' . util_make_url('/plugins/authldap/post-login.php') . '" method="post">
205 <input type="hidden" name="form_key" value="' . form_generate_key() . '"/>
206 <input type="hidden" name="return_to" value="' . htmlspecialchars(stripslashes($return_to)) . '" />
208 $result .= _('LDAP Login name:');
209 $result .= '<br /><input type="text" name="form_loginname" value="' . htmlspecialchars(stripslashes($loginname)) . '" /></p><p>' . _('Password:') . '<br /><input type="password" name="form_pw" /></p><p><input type="submit" name="login" value="' . _('Login') . '" />
213 $params['html_snippets'][$this->name] = $result;
216 protected function declareConfigVars() {
217 parent::declareConfigVars();
219 forge_define_config_item('start_tls', $this->name, 'no');
220 forge_set_config_item_bool('start_tls', $this->name);
222 forge_define_config_item('ldap_server', $this->name, 'ldap.example.com');
223 forge_define_config_item('ldap_port', $this->name, 389);
224 forge_define_config_item('base_dn', $this->name, 'ou=users,dc=example,dc=com');
225 forge_define_config_item('skipped_users', $this->name, '');
226 forge_define_config_item('manager_dn', $this->name, '');
227 forge_define_config_item('manager_password', $this->name, '');
232 function fetchDataForUser($loginname) {
233 if (!$this->ConnectLdap()) {
237 if (forge_get_config('manager_dn', $this->name)) {
238 ldap_bind($this->ldap_conn,
239 forge_get_config('manager_dn', $this->name),
240 forge_get_config('ldap_password'));
242 ldap_bind($this->ldap_conn);
246 foreach (explode(',', forge_get_config('mapping', $this->name))
248 list ($fffield, $ldapfield) = explode('=',$map_entry);
249 if ($fffield == 'username') {
250 $fieldname = $ldapfield;
254 $res = ldap_search($this->ldap_conn, forge_get_config('base_dn', $this->name), "($fieldname=$loginname)");
255 if (!$res || ldap_count_entries($this->ldap_conn, $res) == 0) {
256 // No user by that name in LDAP directory
259 $info = ldap_get_entries($this->ldap_conn,$res);
264 function checkLDAPCredentials($loginname, $passwd) {
265 if (!$this->ConnectLdap()) {
266 // No connection to LDAP directory
267 if ($this->isRequired()) {
268 return FORGE_AUTH_AUTHORITATIVE_REJECT;
270 return FORGE_AUTH_NOT_AUTHORITATIVE;
274 $data = $this->fetchDataForUser($loginname);
276 return FORGE_AUTH_AUTHORITATIVE_REJECT;
279 if (@ldap_bind($this->ldap_conn, $data['dn'], $passwd)) {
281 $this->saved_data = $data;
282 $this->saved_password = $passwd;
283 return FORGE_AUTH_AUTHORITATIVE_ACCEPT;
285 // Probably invalid password
286 return FORGE_AUTH_AUTHORITATIVE_REJECT;
290 function ConnectLDAP() {
291 if ($this->ldap_conn) {
295 $server = forge_get_config('ldap_server', $this->name);
296 $port = forge_get_config('ldap_port', $this->name);
298 $conn = ldap_connect($server, $port);
300 $conn = ldap_connect($server);
303 if (forge_get_config('ldap_version')) {
304 debuglog("LDAP: ldap_set_option ($this->ldap_conn, LDAP_OPT_PROTOCOL_VERSION, ".forge_get_config('ldap_version').");");
305 if (!ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, forge_get_config('ldap_version'))) {
306 debuglog("LDAP: ldap_set_option() failed: ".ldap_error($this->ldap_conn));
311 if (forge_get_config('start_tls', $this->name)) {
312 if (!ldap_start_tls($conn)) {
317 // If the ldap server does not allow anonymous bind,
318 // then authentificate with the server.
319 if (forge_get_config('manager_dn', $this->name)) {
320 if (!@ldap_bind($conn, forge_get_config('manager_dn', $this->name),
321 forge_get_config('ldap_password'))) {
322 error_log("LDAP application bind failed.");
327 $this->ldap_conn = $conn;
332 function debuglog($msg) {
333 $fp = fopen("/tmp/ldap.log", "a+");
334 fwrite ($fp, $msg."\n");
340 // c-file-style: "bsd"