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'),
175 $u->getJabberAddress(),
180 $mapped_data['phone'],
183 $u->getCountryCode(),
184 $mapped_data['email']);
186 $u->setMD5Passwd ($mapped_data['md5_password']);
187 $u->setUnixPasswd ($mapped_data['unix_password']);
190 function displayAuthForm(&$params) {
191 if (!$this->isRequired() && !$this->isSufficient()) {
194 $return_to = $params['return_to'];
200 $result .= _('Cookies must be enabled past this point.');
203 $result .= '<form action="' . util_make_url('/plugins/authldap/post-login.php') . '" method="post">
204 <input type="hidden" name="form_key" value="' . form_generate_key() . '"/>
205 <input type="hidden" name="return_to" value="' . htmlspecialchars(stripslashes($return_to)) . '" />
207 $result .= _('LDAP Login name:');
208 $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') . '" />
212 $params['html_snippets'][$this->name] = $result;
215 protected function declareConfigVars() {
216 parent::declareConfigVars();
218 forge_define_config_item('start_tls', $this->name, 'no');
219 forge_set_config_item_bool('start_tls', $this->name);
221 forge_define_config_item('ldap_server', $this->name, 'ldap.example.com');
222 forge_define_config_item('ldap_port', $this->name, 389);
223 forge_define_config_item('base_dn', $this->name, 'ou=users,dc=example,dc=com');
224 forge_define_config_item('skipped_users', $this->name, '');
225 forge_define_config_item('manager_dn', $this->name, '');
226 forge_define_config_item('manager_password', $this->name, '');
231 function fetchDataForUser($loginname) {
232 if (!$this->ConnectLdap()) {
236 if (forge_get_config('manager_dn', $this->name)) {
237 ldap_bind($this->ldap_conn,
238 forge_get_config('manager_dn', $this->name),
239 forge_get_config('ldap_password'));
241 ldap_bind($this->ldap_conn);
245 foreach (explode(',', forge_get_config('mapping', $this->name))
247 list ($fffield, $ldapfield) = explode('=',$map_entry);
248 if ($fffield == 'username') {
249 $fieldname = $ldapfield;
253 $res = ldap_search($this->ldap_conn, forge_get_config('base_dn', $this->name), "($fieldname=$loginname)");
254 if (!$res || ldap_count_entries($this->ldap_conn, $res) == 0) {
255 // No user by that name in LDAP directory
258 $info = ldap_get_entries($this->ldap_conn,$res);
263 function checkLDAPCredentials($loginname, $passwd) {
264 if (!$this->ConnectLdap()) {
265 // No connection to LDAP directory
266 if ($this->isRequired()) {
267 return FORGE_AUTH_AUTHORITATIVE_REJECT;
269 return FORGE_AUTH_NOT_AUTHORITATIVE;
273 $data = fetchDataForUser($loginname);
275 return FORGE_AUTH_AUTHORITATIVE_REJECT;
278 if (@ldap_bind($this->ldap_conn, $data['dn'], $passwd)) {
280 $this->saved_data = $data;
281 $this->saved_password = $passwd;
282 return FORGE_AUTH_AUTHORITATIVE_ACCEPT;
284 // Probably invalid password
285 return FORGE_AUTH_AUTHORITATIVE_REJECT;
289 function ConnectLDAP() {
290 if ($this->ldap_conn) {
294 $server = forge_get_config('ldap_server', $this->name);
295 $port = forge_get_config('ldap_port', $this->name);
297 $conn = ldap_connect($server, $port);
299 $conn = ldap_connect($server);
302 if (forge_get_config('ldap_version')) {
303 debuglog("LDAP: ldap_set_option ($this->ldap_conn, LDAP_OPT_PROTOCOL_VERSION, ".forge_get_config('ldap_version').");");
304 if (!ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, forge_get_config('ldap_version'))) {
305 debuglog("LDAP: ldap_set_option() failed: ".ldap_error($this->ldap_conn));
310 if (forge_get_config('start_tls', $this->name)) {
311 if (!ldap_start_tls($conn)) {
316 // If the ldap server does not allow anonymous bind,
317 // then authentificate with the server.
318 if (forge_get_config('manager_dn', $this->name)) {
319 if (!@ldap_bind($conn, forge_get_config('manager_dn', $this->name),
320 forge_get_config('ldap_password'))) {
321 error_log("LDAP application bind failed.");
326 $this->ldap_conn = $conn;
331 function debuglog($msg) {
332 $fp = fopen("/tmp/ldap.log", "a+");
333 fwrite ($fp, $msg."\n");
339 // c-file-style: "bsd"