Subversion Repositories ALCASAR

Rev

Rev 776 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log

Rev Author Line No. Line
775 stephane 1
<?php
2
/*
3
This class handled of ldap configuration.
4
WARNING! This class can't says if the configuration is valid or not.
5
*/
6
 
7
class ldapConfig
8
{
9
	protected $_items = Array();
10
	protected $_tls = array();
11
	protected $instanceName;
12
 
13
	public function __construct($instanceName=null) {
14
		if ($instanceName!== null)
15
			$this->instanceName = $instanceName;
16
		// LDAP setting
779 stephane 17
		$this->_items['protocol']					= 'ldap';
775 stephane 18
		$this->_items['host']						= 'test';
779 stephane 19
		$this->_items['server']						= $this->_items['protocol'].'://'.$this->_items['host'];
775 stephane 20
		$this->_items['port']						= '389';//not use yet (689 = ldaps)
21
		$this->_items['identity']					= '';
22
		$this->_items['password']					= '';
23
		$this->_items['basedn']						= 'dc=example,dc=com';
779 stephane 24
		$this->_items['uid']						= 'uid';
25
		$this->_items['filter']						= "($this->_items['uid']=%{Stripped-User-Name:-%{User-Name}})";
775 stephane 26
		$this->_items['base_filter']				= '';
27
		$this->_items['ldap_connections_number']	= '5';
28
		$this->_items['timeout']					= '4';
29
		$this->_items['timelimit']					= '3';
30
		$this->_items['net_timeout'] 				= '1';
31
		// TLS setting related items
32
		$this->_tls['start_tls']					= 'no'; // if no all tls config are comments
33
		$this->_tls['cacertfile']					= '#';
34
		$this->_tls['cacertdir']					= '#';
35
		$this->_tls['certfile']						= '#';
36
		$this->_tls['keyfile']						= '#';
37
		$this->_tls['randfile']						= '#';
38
		$this->_tls['require_cert']					= '#';
39
		// others ldap setting (optional)
40
		$this->_items['default_profile']			= '#';
41
		$this->_items['profile_attribute']			= '#';
42
		$this->_items['access_attr']				= '#';
43
		// Mapping of RADIUS dictionary attributes to LDAP
44
		// directory attributes.
45
		$this->_items['dictionary_mapping']	= '${confdir}/ldap.attrmap';
46
		// for ldap like NOVEL
47
		$this->_items['password_attribute']			= '#';
48
		$this->_items['edir_account_policy_check']	= 'no';
49
		//  Group membership checking.  Disabled by default.
50
		$this->_items['groupname_attribute']		= '#';
51
		$this->_items['groupmembership_filter']		= '#';
52
		$this->_items['groupmembership_attribute']	= '#';
53
		$this->_items['compare_check_items']		= '#';
54
		$this->_items['do_xlat']					= '#';
55
		$this->_items['access_attr_used_for_allow']	= '#';
56
		// auth option
57
		$this->_items['set_auth_type']				= '#';
58
		// debug option
59
		$this->_items['ldap_debug']					= '#';
60
	}
61
 
62
	public function __get($attr){ // to get an $item
63
		if ($attr==='tls'){
64
			return $this->_tls;
65
		} elseif (array_key_exists($attr, $this->_items)){
66
			return $this->_items[$attr];
67
		} elseif (array_key_exists($attr, $this->_tls)){
68
			return $this->_tls[$attr];
69
		}
70
		// nothing else!
71
	}
72
	public function __set($attr, $value){// to set an $item
73
		if (array_key_exists($attr, $this->_items)){
779 stephane 74
			switch ($attr){
75
				case "protocol":
76
					$this->_items['protocol']	= $value;
77
					$this->_items['server']		= $this->_items['protocol'].'://'.$this->_items['host'];
78
					break;
79
				case "host":
80
					$this->_items['host']		= $value;
81
					$this->_items['server']		= $this->_items['protocol'].'://'.$this->_items['host'];
82
					break;
83
				case "server":
84
					// extract protocole & host
85
					$tmp = explode("://",$value,2);
86
					if (count($tmp) == 2){
87
						$this->_items['protocol'] = $tmp[0];
88
						$this->_items['host'] 	= $tmp[1];
89
					} else {
90
						$this->_items['protocol'] = 'ldap';
91
						$this->_items['host'] 	= $tmp[1];
92
					}
93
					$this->_items['server'] = $this->_items['protocol'].'://'.$this->_items['host'];
94
					break;
95
				case "uid":
96
					$this->_items['uid']		= $value;
97
					$this->_items['filter']		= "($this->_items['uid']=%{Stripped-User-Name:-%{User-Name}})";
98
					break;
99
				case "filter":
100
					// extract uid
101
					if (preg_match('`^[\(]([\sa-zA-Z0-9_-]*)=\%\{Stripped\-User\-Name:\-\%\{User-Name\}\}\)`',$value)){
102
						$this->_items['uid'] = preg_replace('`^[\(]([\sa-zA-Z0-9_-]*)=\%\{Stripped\-User\-Name:\-\%\{User-Name\}\}\)`','$1',$value);
103
					} else {
104
						$this->_items['uid'] = 'uid';
105
					}
106
					$this->_items['filter']		= "($this->_items['uid']=%{Stripped-User-Name:-%{User-Name}})";
107
					break;
108
				default:
109
					$this->_items[$attr] = $value;
110
			}
775 stephane 111
		} elseif (array_key_exists($attr, $this->_tls)){
112
			$this->_tls[$attr] = $value;
113
		}
114
	}
115
	public function load($confFile){
116
		// use here the parsing class
117
		require_once("configreader.php");
118
 
119
		$r = new configReader($confFile);
120
 
121
		/*
122
		loading only if the file containt only one ldap instance.
123
		If more instance are found, we use the default values instead.
124
		*/
125
		if (is_object($r->ldap)){
126
			$this->instanceName = $r->ldap->getInstanceName();
127
			$items = $r->ldap->getpair();
128
			foreach ($this->_items as $key => $value){
129
				if (array_key_exists($key, $items))
130
					$this->_items[$key] = $items[$key];
131
			}
132
			if (is_object($r->ldap->tls)){
133
				$tls = $r->ldap->tls->getpair();
134
				foreach ($this->_tls as $key => $value){
135
					if (array_key_exists($key, $tls))
136
						$this->_tls[$key] = $tls[$key];
137
				}
138
			}
139
		}
140
	}
141
	public function __toString() {
142
		return $this->save(null, true);
143
    }
144
	protected function _noComment($name, $value, $quote = false){
145
		if ($value !== '#'){
146
			if ($quote === true){
147
				return $name." = \"".$value."\"";
148
			} else {
149
				return $name." = ".$value;
150
			}
151
		}
152
	}
153
	public function save($savefile = null, $returnconfig = false){
154
	// make config file
155
	$config = "
156
	# Lightweight Directory Access Protocol (LDAP)
157
	#
158
	#  This module definition allows you to use LDAP for
159
	#  authorization and authentication.
160
	#
161
	#  See raddb/sites-available/default for reference to the
162
	#  ldap module in the authorize and authenticate sections.
163
	#
164
	#  However, LDAP can be used for authentication ONLY when the
165
	#  Access-Request packet contains a clear-text User-Password
166
	#  attribute.  LDAP authentication will NOT work for any other
167
	#  authentication method.
168
	#
169
	#  This means that LDAP servers don't understand EAP.  If you
170
	#  force \"Auth-Type = LDAP\", and then send the server a
171
	#  request containing EAP authentication, then authentication
172
	#  WILL NOT WORK.
173
	#
174
	#  The solution is to use the default configuration, which does
175
	#  work.
176
	#
177
	#  Setting \"Auth-Type = LDAP\" is ALMOST ALWAYS WRONG.  We
178
	#  really can't emphasize this enough.
179
	#	
180
	ldap ".$this->instanceName."{
181
		#
182
		#  Note that this needs to match the name in the LDAP
183
		#  server certificate, if you're using ldaps.
184
		server = \"".$this->_items['server']."\"
185
		identity = \"".$this->_items['identity']."\"
186
		password = ".$this->_items['password']."
187
		basedn = \"".$this->_items['basedn']."\"
188
		filter = \"".$this->_items['filter']."\"
189
		base_filter = \"".$this->_items['base_filter']."\"
190
 
191
		#  How many connections to keep open to the LDAP server.
192
		#  This saves time over opening a new LDAP socket for
193
		#  every authentication request.
194
		ldap_connections_number = ".$this->_items['ldap_connections_number']."
195
 
196
		# seconds to wait for LDAP query to finish. default: 20
197
		timeout = ".$this->_items['timeout']."
198
 
199
		#  seconds LDAP server has to process the query (server-side
200
		#  time limit). default: 20
201
		#
202
		#  LDAP_OPT_TIMELIMIT is set to this value.
203
		timelimit = ".$this->_items['timelimit']."
204
 
205
		#
206
		#  seconds to wait for response of the server. (network
207
		#   failures) default: 10
208
		#
209
		#  LDAP_OPT_NETWORK_TIMEOUT is set to this value.
210
		net_timeout = ".$this->_items['net_timeout']."
211
 
212
		#
213
		#  This subsection configures the tls related items
214
		#  that control how FreeRADIUS connects to an LDAP
215
		#  server.  It contains all of the \"tls_*\" configuration
216
		#  entries used in older versions of FreeRADIUS.  Those
217
		#  configuration entries can still be used, but we recommend
218
		#  using these.
219
		#
220
		tls {
221
			# Set this to 'yes' to use TLS encrypted connections
222
			# to the LDAP database by using the StartTLS extended
223
			# operation.
224
			#			
225
			# The StartTLS operation is supposed to be
226
			# used with normal ldap connections instead of
227
			# using ldaps (port 689) connections
228
			start_tls = ".$this->_tls['start_tls']."
229
 
230
			# cacertfile	= /path/to/cacert.pem
231
			# cacertdir		= /path/to/ca/dir/
232
			# certfile		= /path/to/radius.crt
233
			# keyfile		= /path/to/radius.key
234
			# randfile		= /path/to/rnd
235
			".$this->_noComment("cacertfile", $this->_tls['cacertfile'])."
236
			".$this->_noComment("cacertdir", $this->_tls['cacertdir'])."
237
			".$this->_noComment("certfile", $this->_tls['certfile'])."
238
			".$this->_noComment("keyfile", $this->_tls['keyfile'])."
239
			".$this->_noComment("randfile", $this->_tls['randfile'])."
240
			#  Certificate Verification requirements.  Can be:
241
			#    \"never\" (don't even bother trying)
242
			#    \"allow\" (try, but don't fail if the cerificate
243
			#		can't be verified)
244
			#    \"demand\" (fail if the certificate doesn't verify.)
245
			#
246
			#	The default is \"allow\"
247
			# require_cert	= \"demand\"
248
			".$this->_noComment("require_cert", $this->_tls['require_cert'], true)."
249
		}
250
 
251
		# default_profile = \"cn=radprofile,ou=dialup,o=My Org,c=UA\"
252
		# profile_attribute = \"radiusProfileDn\"
253
		# access_attr = \"dialupAccess\"
254
		".$this->_noComment("default_profile", $this->_items['default_profile'], true)."
255
		".$this->_noComment("profile_attribute", $this->_items['profile_attribute'], true)."
256
		".$this->_noComment("access_attr", $this->_items['access_attr'], true)."
257
		# Mapping of RADIUS dictionary attributes to LDAP
258
		# directory attributes.
259
		dictionary_mapping = ".$this->_items['dictionary_mapping']."
260
 
261
		#  Set password_attribute = nspmPassword to get the
262
		#  user's password from a Novell eDirectory
263
		#  backend. This will work ONLY IF FreeRADIUS has been
264
		#  built with the --with-edir configure option.
265
		#
266
		#  See also the following links:
267
		#
268
		#  http://www.novell.com/coolsolutions/appnote/16745.html
269
		#  https://secure-support.novell.com/KanisaPlatform/Publishing/558/3009668_f.SAL_Public.html
270
		#
271
		#  Novell may require TLS encrypted sessions before returning
272
		#  the user's password.
273
		#
274
		# password_attribute = userPassword
275
		".$this->_noComment("access_attr", $this->_items['access_attr'])."
276
		#  Un-comment the following to disable Novell
277
		#  eDirectory account policy check and intruder
278
		#  detection. This will work *only if* FreeRADIUS is
279
		#  configured to build with --with-edir option.
280
		#
281
		edir_account_policy_check = no
282
		".$this->_noComment("access_attr", $this->_items['access_attr'])."
283
		#
284
		#  Group membership checking.  Disabled by default.
285
		#
286
		# groupname_attribute = cn
287
		# groupmembership_filter = \"(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))\"
288
		# groupmembership_attribute = radiusGroupName
289
		".$this->_noComment("groupname_attribute", $this->_items['groupname_attribute'])."
290
		".$this->_noComment("groupmembership_filter", $this->_items['groupmembership_filter'], true)."
291
		".$this->_noComment("groupmembership_attribute", $this->_items['groupmembership_attribute'])."
292
		# compare_check_items = yes
293
		# do_xlat = yes
294
		# access_attr_used_for_allow = yes
295
		".$this->_noComment("compare_check_items", $this->_items['compare_check_items'])."
296
		".$this->_noComment("do_xlat", $this->_items['do_xlat'])."
297
		".$this->_noComment("access_attr_used_for_allow", $this->_items['access_attr_used_for_allow'])."
298
		#
299
		#  By default, if the packet contains a User-Password,
300
		#  and no other module is configured to handle the
301
		#  authentication, the LDAP module sets itself to do
302
		#  LDAP bind for authentication.
303
		#
304
		#  THIS WILL ONLY WORK FOR PAP AUTHENTICATION.
305
		#
306
		#  THIS WILL NOT WORK FOR CHAP, MS-CHAP, or 802.1x (EAP). 
307
		#
308
		#  You can disable this behavior by setting the following
309
		#  configuration entry to \"no\".
310
		#
311
		#  allowed values: {no, yes}
312
		# set_auth_type = yes
313
		# set_auth_type = no
314
		".$this->_noComment("set_auth_type", $this->_items['set_auth_type'])."
315
		#  ldap_debug: debug flag for LDAP SDK
316
		#  (see OpenLDAP documentation).  Set this to enable
317
		#  huge amounts of LDAP debugging on the screen.
318
		#  You should only use this if you are an LDAP expert.
319
		#
320
		#	default: 0x0000 (no debugging messages)
321
		#	Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS)
322
		#ldap_debug = 0x0028
323
		".$this->_noComment("ldap_debug", $this->_items['ldap_debug'])."
324
	}
325
	";
326
		if ($savefile !== null){
327
			// save config file
328
			if (is_file($savefile)){
329
				// save the file
330
				if (!is_writable($savefile))
331
					return false;
332
				$updatedFile = fopen( $savefile, 'w' );
333
				fwrite( $updatedFile, $config );
334
				fclose( $updatedFile );
335
			} else {
336
				// create a new file
337
				$newFile = fopen($savefile, 'w') or die("can't create file");
338
				fwrite( $newFile, $config );
339
				fclose( $newFile );
340
			}
341
		}	
342
		// test $returnconfig
343
		if (($returnconfig===true)||($returnconfig==="yes")){
344
			return $config;
345
		}else{
346
			return true;
347
		}
348
	}
349
}
350
?>