2018-06-01 17:10:45 +01:00
< ? php
###################################
2021-03-13 14:11:38 +00:00
function open_ldap_connection ( $ldap_bind = TRUE ) {
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
global $log_prefix , $LDAP , $SENT_HEADERS , $LDAP_DEBUG , $LDAP_VERBOSE_CONNECTION_LOGS ;
2018-06-01 17:10:45 +01:00
2020-11-28 18:00:01 +00:00
if ( $LDAP [ 'ignore_cert_errors' ] == TRUE ) { putenv ( 'LDAPTLS_REQCERT=never' ); }
2020-01-10 12:01:31 +00:00
$ldap_connection = @ ldap_connect ( $LDAP [ 'uri' ]);
2018-06-01 17:10:45 +01:00
if ( ! $ldap_connection ) {
2023-01-10 10:51:18 +01:00
print " Problem: Can't connect to the LDAP server at { $LDAP [ 'uri' ] } " ;
die ( " Can't connect to the LDAP server at { $LDAP [ 'uri' ] } " );
2018-06-01 17:10:45 +01:00
exit ( 1 );
}
ldap_set_option ( $ldap_connection , LDAP_OPT_PROTOCOL_VERSION , 3 );
2020-11-28 18:00:01 +00:00
if ( $LDAP_VERBOSE_CONNECTION_LOGS == TRUE ) { ldap_set_option ( NULL , LDAP_OPT_DEBUG_LEVEL , 7 ); }
2018-06-01 17:10:45 +01:00
2018-06-04 15:20:53 +01:00
if ( ! preg_match ( " /^ldaps:/ " , $LDAP [ 'uri' ])) {
2020-01-10 12:01:31 +00:00
$tls_result = @ ldap_start_tls ( $ldap_connection );
2018-06-04 15:20:53 +01:00
if ( $tls_result != TRUE ) {
2023-01-10 10:51:18 +01:00
if ( ! preg_match ( '/^ldap:\/\/127\.0\.0\.([0-9]+)(:[0-9]+)$/' , $LDAP [ 'uri' ])) { error_log ( " $log_prefix Failed to start STARTTLS connection to { $LDAP [ 'uri' ] } : " . ldap_error ( $ldap_connection ), 0 ); }
2018-06-04 15:20:53 +01:00
if ( $LDAP [ " require_starttls " ] == TRUE ) {
2023-01-10 10:51:18 +01:00
print " <div style='position: fixed;bottom: 0;width: 100%;' class='alert alert-danger'>Fatal: Couldn't create a secure connection to { $LDAP [ 'uri' ] } and LDAP_REQUIRE_STARTTLS is TRUE.</div> " ;
2018-06-04 15:20:53 +01:00
exit ( 0 );
}
else {
2021-03-15 02:30:56 -07:00
if ( $SENT_HEADERS == TRUE and ! preg_match ( '/^ldap:\/\/localhost(:[0-9]+)?$/' , $LDAP [ 'uri' ]) and ! preg_match ( '/^ldap:\/\/127\.0\.0\.([0-9]+)(:[0-9]+)$/' , $LDAP [ 'uri' ])) {
2023-01-10 10:51:18 +01:00
print " <div style='position: fixed;bottom: 0px;width: 100%;height: 20px;border-bottom:solid 20px yellow;'>WARNING: Insecure LDAP connection to { $LDAP [ 'uri' ] } </div> " ;
2020-01-10 12:01:31 +00:00
}
2018-06-04 15:20:53 +01:00
ldap_close ( $ldap_connection );
2020-01-10 12:01:31 +00:00
$ldap_connection = @ ldap_connect ( $LDAP [ 'uri' ]);
2018-06-04 15:20:53 +01:00
ldap_set_option ( $ldap_connection , LDAP_OPT_PROTOCOL_VERSION , 3 );
}
}
2020-11-28 18:00:01 +00:00
else {
if ( $LDAP_DEBUG == TRUE ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Start STARTTLS connection to { $LDAP [ 'uri' ] } " , 0 );
2020-11-28 18:00:01 +00:00
}
2021-03-13 14:11:38 +00:00
$LDAP [ 'connection_type' ] = " StartTLS " ;
2020-05-01 17:14:04 +01:00
}
2020-11-28 18:00:01 +00:00
2018-06-04 15:20:53 +01:00
}
2021-03-13 14:11:38 +00:00
else {
if ( $LDAP_DEBUG == TRUE ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Using an LDAPS encrypted connection to { $LDAP [ 'uri' ] } " , 0 );
2021-03-13 14:11:38 +00:00
}
$LDAP [ 'connection_type' ] = 'LDAPS' ;
}
2018-06-04 15:20:53 +01:00
2021-03-13 14:11:38 +00:00
if ( $ldap_bind == TRUE ) {
2018-06-01 17:10:45 +01:00
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Attempting to bind to { $LDAP [ 'uri' ] } as { $LDAP [ 'admin_bind_dn' ] } " , 0 ); }
2021-03-13 14:11:38 +00:00
$bind_result = @ ldap_bind ( $ldap_connection , $LDAP [ 'admin_bind_dn' ], $LDAP [ 'admin_bind_pwd' ]);
2020-05-01 17:14:04 +01:00
2021-03-13 14:11:38 +00:00
if ( $bind_result != TRUE ) {
2020-05-06 17:19:20 +01:00
2023-01-10 10:51:18 +01:00
$this_error = " Failed to bind to { $LDAP [ 'uri' ] } as { $LDAP [ 'admin_bind_dn' ] } " ;
if ( $LDAP_DEBUG == TRUE ) { $this_error .= " with password { $LDAP [ 'admin_bind_pwd' ] } " ; }
2021-03-13 14:11:38 +00:00
$this_error .= " : " . ldap_error ( $ldap_connection );
2023-01-10 10:51:18 +01:00
print " Problem: Failed to bind as { $LDAP [ 'admin_bind_dn' ] } " ;
2021-03-13 14:11:38 +00:00
error_log ( " $log_prefix $this_error " , 0 );
exit ( 1 );
}
elseif ( $LDAP_DEBUG == TRUE ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Bound successfully as { $LDAP [ 'admin_bind_dn' ] } " , 0 );
2021-03-13 14:11:38 +00:00
}
2020-05-01 17:14:04 +01:00
2018-06-01 17:10:45 +01:00
}
return $ldap_connection ;
}
###################################
2023-07-20 16:23:52 +01:00
function ldap_auth_username ( $ldap_connection , $username , $password ) {
2018-06-01 17:10:45 +01:00
# Search for the DN for the given username. If found, try binding with the DN and user's password.
# If the binding succeeds, return the DN.
2023-07-20 16:23:52 +01:00
global $log_prefix , $LDAP , $SITE_LOGIN_LDAP_ATTRIBUTE , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2023-07-20 16:23:52 +01:00
$ldap_search_query = " { $SITE_LOGIN_LDAP_ATTRIBUTE } = " . ldap_escape ( $username , " " , LDAP_ESCAPE_FILTER );
2021-03-13 14:11:38 +00:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Running LDAP search for: $ldap_search_query " ); }
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
$ldap_search = @ ldap_search ( $ldap_connection , $LDAP [ 'user_dn' ], $ldap_search_query );
2020-05-01 17:14:04 +01:00
2018-06-01 17:10:45 +01:00
if ( ! $ldap_search ) {
2021-03-13 14:11:38 +00:00
error_log ( " $log_prefix Couldn't search for $ldap_search_query : " . ldap_error ( $ldap_connection ), 0 );
2018-06-01 17:10:45 +01:00
return FALSE ;
}
2021-03-13 14:11:38 +00:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
if ( ! $result ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Couldn't get LDAP entries for { $username } : " . ldap_error ( $ldap_connection ), 0 );
2021-03-13 14:11:38 +00:00
return FALSE ;
}
if ( $LDAP_DEBUG == TRUE ) {
error_log ( " $log_prefix LDAP search returned " . $result [ " count " ] . " records for $ldap_search_query " , 0 );
for ( $i = 1 ; $i == $result [ " count " ]; $i ++ ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix " . " Entry { $i } : " . $result [ $i - 1 ][ 'dn' ], 0 );
2021-03-13 14:11:38 +00:00
}
}
2020-05-01 17:14:04 +01:00
2018-06-01 17:10:45 +01:00
if ( $result [ " count " ] == 1 ) {
2021-03-13 14:11:38 +00:00
$this_dn = $result [ 0 ][ 'dn' ];
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Attempting authenticate as $username by binding with { $this_dn } " , 0 ); }
2021-03-13 14:11:38 +00:00
$auth_ldap_connection = open_ldap_connection ( FALSE );
2023-07-20 16:23:52 +01:00
$can_bind = @ ldap_bind ( $auth_ldap_connection , $result [ 0 ][ 'dn' ], $password );
2018-06-01 17:10:45 +01:00
if ( $can_bind ) {
preg_match ( " / { $LDAP [ 'account_attribute' ] } =(.*?),/ " , $result [ 0 ][ 'dn' ], $dn_match );
2023-07-20 16:23:52 +01:00
$account_id = $dn_match [ 1 ];
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Able to bind as { $username } : dn is { $result [ 0 ][ 'dn' ] } and account ID is { $account_id } " , 0 ); }
2021-03-13 14:11:38 +00:00
ldap_close ( $auth_ldap_connection );
2023-07-20 16:23:52 +01:00
return $account_id ;
2018-06-01 17:10:45 +01:00
}
else {
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Unable to bind as { $username } : " . ldap_error ( $auth_ldap_connection ), 0 ); }
2021-03-13 14:11:38 +00:00
ldap_close ( $auth_ldap_connection );
2018-06-01 17:10:45 +01:00
return FALSE ;
}
}
2021-03-13 14:11:38 +00:00
elseif ( $result [ " count " ] > 1 ) {
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix There was more than one entry for { $ldap_search_query } so it wasn't possible to determine which user to log in as. " ); }
2021-03-13 14:11:38 +00:00
}
2018-06-01 17:10:45 +01:00
}
###################################
function ldap_setup_auth ( $ldap_connection , $password ) {
#For the initial setup we need to make sure that whoever's running it has the default admin user
#credentials as passed in ADMIN_BIND_*
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Initial setup: opening another LDAP connection to test authentication as { $LDAP [ 'admin_bind_dn' ] } . " , 0 ); }
2018-06-01 17:10:45 +01:00
$auth_ldap_connection = open_ldap_connection ();
$can_bind = @ ldap_bind ( $auth_ldap_connection , $LDAP [ 'admin_bind_dn' ], $password );
ldap_close ( $auth_ldap_connection );
2020-05-01 17:14:04 +01:00
if ( $can_bind ) {
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix Initial setup: able to authenticate as { $LDAP [ 'admin_bind_dn' ] } . " , 0 ); }
2020-05-01 17:14:04 +01:00
return TRUE ;
}
else {
2023-01-10 10:51:18 +01:00
$this_error = " Initial setup: Unable to authenticate as { $LDAP [ 'admin_bind_dn' ] } " ;
2020-05-01 17:14:04 +01:00
if ( $LDAP_DEBUG == TRUE ) { $this_error .= " with password $password " ; }
2020-05-06 17:19:20 +01:00
$this_error .= " . The password used to authenticate for /setup should be the same as set by LDAP_ADMIN_BIND_PWD. " ;
$this_error .= ldap_error ( $ldap_connection );
2020-05-01 17:14:04 +01:00
error_log ( " $log_prefix $this_error " , 0 );
return FALSE ;
}
2018-06-01 17:10:45 +01:00
}
2020-08-03 17:35:13 +01:00
#################################
function generate_salt ( $length ) {
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./' ;
2022-10-10 13:55:14 +01:00
mt_srand ( intval ( microtime ()) * 1000000 );
2020-08-03 17:35:13 +01:00
$salt = '' ;
while ( strlen ( $salt ) < $length ) {
$salt .= substr ( $permitted_chars , ( rand () % strlen ( $permitted_chars )), 1 );
}
return $salt ;
}
2018-06-01 17:10:45 +01:00
##################################
function ldap_hashed_password ( $password ) {
2020-08-03 17:35:13 +01:00
global $PASSWORD_HASH , $log_prefix ;
2020-05-22 11:03:23 +01:00
2020-08-03 17:35:13 +01:00
$check_algos = array (
" SHA512CRYPT " => " CRYPT_SHA512 " ,
" SHA256CRYPT " => " CRYPT_SHA256 " ,
# "BLOWFISH" => "CRYPT_BLOWFISH",
# "EXT_DES" => "CRYPT_EXT_DES",
" MD5CRYPT " => " CRYPT_MD5 "
);
2020-05-22 11:03:23 +01:00
2020-08-03 17:35:13 +01:00
$remaining_algos = array (
" SSHA " ,
" SHA " ,
" SMD5 " ,
" MD5 " ,
2022-11-24 14:58:13 +01:00
" ARGON2 " ,
2020-08-03 17:35:13 +01:00
" CRYPT " ,
" CLEAR "
);
2020-05-22 11:03:23 +01:00
2020-08-03 17:35:13 +01:00
$available_algos = array ();
foreach ( $check_algos as $algo_name => $algo_function ) {
if ( defined ( $algo_function ) and constant ( $algo_function ) != 0 ) {
array_push ( $available_algos , $algo_name );
}
else {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix password hashing - the system doesn't support { $algo_name } " , 0 );
2020-08-03 17:35:13 +01:00
}
}
$available_algos = array_merge ( $available_algos , $remaining_algos );
if ( isset ( $PASSWORD_HASH )) {
if ( ! in_array ( $PASSWORD_HASH , $available_algos )) {
$hash_algo = $available_algos [ 0 ];
2021-07-22 09:12:55 +01:00
error_log ( " $log_prefix LDAP password: the chosen hash method ( $PASSWORD_HASH ) wasn't available " , 0 );
2020-08-03 17:35:13 +01:00
}
else {
$hash_algo = $PASSWORD_HASH ;
}
}
else {
$hash_algo = $available_algos [ 0 ];
}
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix LDAP password: using ' { $hash_algo } ' as the hashing method " , 0 );
2020-08-03 17:35:13 +01:00
switch ( $hash_algo ) {
case 'SHA512CRYPT' :
$hashed_pwd = '{CRYPT}' . crypt ( $password , '$6$' . generate_salt ( 8 ));
break ;
case 'SHA256CRYPT' :
$hashed_pwd = '{CRYPT}' . crypt ( $password , '$5$' . generate_salt ( 8 ));
break ;
# Blowfish & EXT_DES didn't work
# case 'BLOWFISH':
# $hashed_pwd = '{CRYPT}' . crypt($password, '$2a$12$' . generate_salt(13));
# break;
# case 'EXT_DES':
# $hashed_pwd = '{CRYPT}' . crypt($password, '_' . generate_salt(8));
# break;
case 'MD5CRYPT' :
$hashed_pwd = '{CRYPT}' . crypt ( $password , '$1$' . generate_salt ( 9 ));
break ;
2020-05-22 11:03:23 +01:00
case 'SMD5' :
2020-08-03 17:35:13 +01:00
$salt = generate_salt ( 8 );
$hashed_pwd = '{SMD5}' . base64_encode ( md5 ( $password . $salt , TRUE ) . $salt );
break ;
case 'MD5' :
$hashed_pwd = '{MD5}' . base64_encode ( md5 ( $password , TRUE ));
break ;
2020-05-22 11:03:23 +01:00
case 'SHA' :
2020-08-03 17:35:13 +01:00
$hashed_pwd = '{SHA}' . base64_encode ( sha1 ( $password , TRUE ));
break ;
2020-05-22 11:03:23 +01:00
case 'SSHA' :
2020-08-03 17:35:13 +01:00
$salt = generate_salt ( 8 );
$hashed_pwd = '{SSHA}' . base64_encode ( sha1 ( $password . $salt , TRUE ) . $salt );
break ;
2020-05-22 11:03:23 +01:00
2022-11-24 14:58:13 +01:00
case 'ARGON2' :
$hashed_pwd = '{ARGON2}' . password_hash ( $password , PASSWORD_ARGON2ID , [ 'memory_cost' => 2048 , 'time_cost' => 4 , 'threads' => 3 ]);
break ;
2020-05-22 11:03:23 +01:00
case 'CRYPT' :
2020-08-03 17:35:13 +01:00
$salt = generate_salt ( 2 );
$hashed_pwd = '{CRYPT}' . crypt ( $password , $salt );
break ;
case 'CLEAR' :
2021-07-22 09:12:55 +01:00
error_log ( " $log_prefix password hashing - WARNING - Saving password in cleartext. This is extremely bad practice and should never ever be done in a production environment. " , 0 );
2020-08-03 17:35:13 +01:00
$hashed_pwd = $password ;
break ;
2020-05-22 11:03:23 +01:00
}
2021-07-22 09:12:55 +01:00
error_log ( " $log_prefix password update - algo $hash_algo | pwd $hashed_pwd " , 0 );
2020-08-03 17:35:13 +01:00
2018-06-01 17:10:45 +01:00
return $hashed_pwd ;
}
##################################
function ldap_get_user_list ( $ldap_connection , $start = 0 , $entries = NULL , $sort = " asc " , $sort_key = NULL , $filters = NULL , $fields = NULL ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2023-01-10 10:51:18 +01:00
if ( ! isset ( $fields )) { $fields = array_unique ( array ( " { $LDAP [ 'account_attribute' ] } " , " givenname " , " sn " , " mail " )); }
2020-01-10 12:01:31 +00:00
2018-06-01 17:10:45 +01:00
if ( ! isset ( $sort_key )) { $sort_key = $LDAP [ 'account_attribute' ]; }
2023-01-10 10:51:18 +01:00
$this_filter = " (&( { $LDAP [ 'account_attribute' ] } =*) $filters ) " ;
2018-06-01 17:10:45 +01:00
2023-01-10 10:51:18 +01:00
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'user_dn' ] } " , $this_filter , $fields );
2020-05-06 17:19:20 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP returned { $result [ 'count' ] } users for { $LDAP [ 'user_dn' ] } when using this filter: $this_filter " , 0 ); }
2018-06-01 17:10:45 +01:00
$records = array ();
foreach ( $result as $record ) {
if ( isset ( $record [ $sort_key ][ 0 ])) {
$add_these = array ();
foreach ( $fields as $this_attr ) {
2022-04-12 15:43:21 +01:00
if ( $this_attr !== $sort_key and isset ( $record [ $this_attr ])) { $add_these [ $this_attr ] = $record [ $this_attr ][ 0 ]; }
2018-06-01 17:10:45 +01:00
}
$records [ $record [ $sort_key ][ 0 ]] = $add_these ;
}
}
if ( $sort == " asc " ) { ksort ( $records ); } else { krsort ( $records ); }
return ( array_slice ( $records , $start , $entries ));
}
##################################
2021-03-13 14:11:38 +00:00
function fetch_id_stored_in_ldap ( $ldap_connection , $type = " uid " ) {
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2023-01-10 10:51:18 +01:00
$filter = " (&(objectclass=device)(cn=last { $type } )) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'base_dn' ] } " , $filter , array ( 'serialNumber' ));
2021-03-13 14:11:38 +00:00
$result = ldap_get_entries ( $ldap_connection , $ldap_search );
2021-07-22 09:12:55 +01:00
if ( isset ( $result [ 0 ][ 'serialnumber' ][ 0 ]) and is_numeric ( $result [ 0 ][ 'serialnumber' ][ 0 ])){
return $result [ 0 ][ 'serialnumber' ][ 0 ];
2021-03-13 14:11:38 +00:00
}
else {
return FALSE ;
}
}
##################################
2018-06-01 17:10:45 +01:00
function ldap_get_highest_id ( $ldap_connection , $type = " uid " ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG , $min_uid , $min_gid ;
2018-06-01 17:10:45 +01:00
if ( $type == " uid " ) {
$this_id = $min_uid ;
$record_base_dn = $LDAP [ 'user_dn' ];
2023-01-10 10:51:18 +01:00
$record_filter = " ( { $LDAP [ 'account_attribute' ] } =*) " ;
2021-03-13 14:11:38 +00:00
$record_attribute = " uidnumber " ;
2018-06-01 17:10:45 +01:00
}
else {
$type = " gid " ;
$this_id = $min_gid ;
$record_base_dn = $LDAP [ 'group_dn' ];
$record_filter = " (objectClass=posixGroup) " ;
2021-03-13 14:11:38 +00:00
$record_attribute = " gidnumber " ;
2018-06-01 17:10:45 +01:00
}
2021-03-13 14:11:38 +00:00
$fetched_id = fetch_id_stored_in_ldap ( $ldap_connection , $type );
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
if ( $fetched_id != FALSE ) {
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
return ( $fetched_id );
2018-06-01 17:10:45 +01:00
}
else {
2021-03-13 14:11:38 +00:00
error_log ( " $log_prefix cn=lastGID doesn't exist so the highest $type is determined by searching through all the LDAP records. " , 0 );
$ldap_search = @ ldap_search ( $ldap_connection , $record_base_dn , $record_filter , array ( $record_attribute ));
2018-06-01 17:10:45 +01:00
$result = ldap_get_entries ( $ldap_connection , $ldap_search );
foreach ( $result as $record ) {
if ( isset ( $record [ $record_attribute ][ 0 ])) {
if ( $record [ $record_attribute ][ 0 ] > $this_id ) { $this_id = $record [ $record_attribute ][ 0 ]; }
}
}
}
return ( $this_id );
}
##################################
function ldap_get_group_list ( $ldap_connection , $start = 0 , $entries = NULL , $sort = " asc " , $filters = NULL ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2020-05-01 17:14:04 +01:00
$this_filter = " (&(objectclass=*) $filters ) " ;
2023-01-10 10:51:18 +01:00
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $this_filter );
2018-06-01 17:10:45 +01:00
2020-05-06 17:19:20 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP returned { $result [ 'count' ] } groups for { $LDAP [ 'group_dn' ] } when using this filter: $this_filter " , 0 ); }
2018-06-01 17:10:45 +01:00
$records = array ();
foreach ( $result as $record ) {
2021-10-05 15:55:22 +02:00
if ( isset ( $record [ $LDAP [ 'group_attribute' ]][ 0 ])) {
2018-06-01 17:10:45 +01:00
2021-10-05 15:55:22 +02:00
array_push ( $records , $record [ $LDAP [ 'group_attribute' ]][ 0 ]);
2018-06-01 17:10:45 +01:00
}
}
if ( $sort == " asc " ) { sort ( $records ); } else { rsort ( $records ); }
return ( array_slice ( $records , $start , $entries ));
}
2020-11-28 18:00:01 +00:00
##################################
2022-04-12 15:43:21 +01:00
function ldap_get_group_entry ( $ldap_connection , $group_name ) {
2020-11-28 18:00:01 +00:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
if ( isset ( $group_name )) {
2023-01-10 10:51:18 +01:00
$ldap_search_query = " ( { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " ) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query );
2020-11-28 18:00:01 +00:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2022-04-12 15:43:21 +01:00
if ( $result [ 'count' ] > 0 ) {
return $result ;
}
else {
return FALSE ;
2020-11-28 18:00:01 +00:00
}
}
return FALSE ;
}
2018-06-01 17:10:45 +01:00
##################################
function ldap_get_group_members ( $ldap_connection , $group_name , $start = 0 , $entries = NULL , $sort = " asc " ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$rfc2307bis_available = ldap_detect_rfc2307bis ( $ldap_connection );
2020-12-24 18:24:41 +00:00
2023-01-10 10:51:18 +01:00
$ldap_search_query = " ( { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " ) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query , array ( $LDAP [ 'group_membership_attribute' ]));
2018-06-01 17:10:45 +01:00
2020-05-06 17:19:20 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2022-04-12 15:43:21 +01:00
if ( $result ) { $result_count = $result [ 'count' ]; } else { $result_count = 0 ; }
2018-06-01 17:10:45 +01:00
$records = array ();
2020-05-06 17:19:20 +01:00
if ( $result_count > 0 ) {
foreach ( $result [ 0 ][ $LDAP [ 'group_membership_attribute' ]] as $key => $value ) {
if ( $key !== 'count' and ! empty ( $value )) {
$this_member = preg_replace ( " /^.*?=(.*?),.*/ " , " $ 1 " , $value );
array_push ( $records , $this_member );
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix { $value } is a member " , 0 ); }
2020-05-06 17:19:20 +01:00
}
2018-06-01 17:10:45 +01:00
}
2020-05-06 17:19:20 +01:00
$actual_result_count = count ( $records );
2023-01-10 10:51:18 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP returned $actual_result_count members of { $group_name } when using this search: $ldap_search_query and this filter: { $LDAP [ 'group_membership_attribute' ] } " , 0 ); }
2018-06-01 17:10:45 +01:00
2020-05-06 17:19:20 +01:00
if ( $actual_result_count > 0 ) {
if ( $sort == " asc " ) { sort ( $records ); } else { rsort ( $records ); }
return ( array_slice ( $records , $start , $entries ));
}
else {
return array ();
}
2018-06-01 17:10:45 +01:00
2020-05-06 17:19:20 +01:00
}
else {
return array ();
}
2018-06-01 17:10:45 +01:00
}
##################################
function ldap_is_group_member ( $ldap_connection , $group_name , $username ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$rfc2307bis_available = ldap_detect_rfc2307bis ( $ldap_connection );
2020-12-24 18:24:41 +00:00
2023-01-10 10:51:18 +01:00
$ldap_search_query = " ( { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " ) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query );
2018-06-01 17:10:45 +01:00
2021-07-22 09:12:55 +01:00
if ( $ldap_search ) {
$result = ldap_get_entries ( $ldap_connection , $ldap_search );
2018-06-01 17:10:45 +01:00
2021-07-22 09:12:55 +01:00
if ( $LDAP [ 'group_membership_uses_uid' ] == FALSE ) {
2023-01-10 10:51:18 +01:00
$username = " { $LDAP [ 'account_attribute' ] } = $username , { $LDAP [ 'user_dn' ] } " ;
2021-07-22 09:12:55 +01:00
}
2023-01-10 10:51:18 +01:00
if ( preg_grep ( " /^ { $username } $ /i " , $result [ 0 ][ $LDAP [ 'group_membership_attribute' ]])) {
2021-07-22 09:12:55 +01:00
return TRUE ;
}
else {
return FALSE ;
}
2018-06-01 17:10:45 +01:00
}
else {
2022-04-12 15:43:21 +01:00
return FALSE ;
2018-06-01 17:10:45 +01:00
}
}
2020-12-24 18:24:41 +00:00
##################################
function ldap_user_group_membership ( $ldap_connection , $username ) {
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2022-04-12 15:43:21 +01:00
$rfc2307bis_available = ldap_detect_rfc2307bis ( $ldap_connection );
2020-12-24 18:24:41 +00:00
if ( $LDAP [ 'group_membership_uses_uid' ] == FALSE ) {
2023-01-10 10:51:18 +01:00
$username = " { $LDAP [ 'account_attribute' ] } = $username , { $LDAP [ 'user_dn' ] } " ;
2020-12-24 18:24:41 +00:00
}
2023-01-10 10:51:18 +01:00
$ldap_search_query = " (&(objectClass=posixGroup)( { $LDAP [ 'group_membership_attribute' ] } = { $username } )) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query , array ( $LDAP [ 'group_attribute' ]));
2020-12-24 18:24:41 +00:00
$result = ldap_get_entries ( $ldap_connection , $ldap_search );
$groups = array ();
foreach ( $result as $record ) {
2021-10-05 15:55:22 +02:00
if ( isset ( $record [ $LDAP [ 'group_attribute' ]][ 0 ])) {
array_push ( $groups , $record [ $LDAP [ 'group_attribute' ]][ 0 ]);
2020-12-24 18:24:41 +00:00
}
}
sort ( $groups );
return $groups ;
}
2018-06-01 17:10:45 +01:00
##################################
2022-04-12 15:43:21 +01:00
function ldap_new_group ( $ldap_connection , $group_name , $initial_member = " " , $extra_attributes = array ()) {
2018-06-01 17:10:45 +01:00
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$rfc2307bis_available = ldap_detect_rfc2307bis ( $ldap_connection );
2020-12-24 18:24:41 +00:00
2018-06-01 17:10:45 +01:00
if ( isset ( $group_name )) {
2022-04-12 15:43:21 +01:00
$new_group = ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER );
$initial_member = ldap_escape ( $initial_member , " " , LDAP_ESCAPE_FILTER );
$update_gid_store = FALSE ;
2021-07-22 09:12:55 +01:00
2023-01-10 10:51:18 +01:00
$ldap_search_query = " ( { $LDAP [ 'group_attribute' ] } = $new_group , { $LDAP [ 'group_dn' ] } ) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query );
2022-04-12 15:43:21 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
if ( $result [ 'count' ] == 0 ) {
2018-06-01 17:10:45 +01:00
2023-01-10 10:51:18 +01:00
if ( $LDAP [ 'group_membership_uses_uid' ] == FALSE and $initial_member != " " ) { $initial_member = " { $LDAP [ 'account_attribute' ] } = $initial_member , { $LDAP [ 'user_dn' ] } " ; }
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$new_group_array = array ( 'objectClass' => $LDAP [ 'group_objectclasses' ],
'cn' => $new_group ,
$LDAP [ 'group_membership_attribute' ] => $initial_member
);
2021-07-22 09:12:55 +01:00
2022-04-12 15:43:21 +01:00
$new_group_array = array_merge ( $new_group_array , $extra_attributes );
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
if ( ! isset ( $new_group_array [ " gidnumber " ][ 0 ]) or ! is_numeric ( $new_group_array [ " gidnumber " ][ 0 ])) {
$highest_gid = ldap_get_highest_id ( $ldap_connection , 'gid' );
$new_gid = $highest_gid + 1 ;
$new_group_array [ " gidnumber " ] = $new_gid ;
$update_gid_store = TRUE ;
}
2020-05-06 17:19:20 +01:00
2023-01-10 10:51:18 +01:00
$group_dn = " cn= $new_group , { $LDAP [ 'group_dn' ] } " ;
2020-05-06 17:19:20 +01:00
2022-04-12 15:43:21 +01:00
$add_group = @ ldap_add ( $ldap_connection , $group_dn , $new_group_array );
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( ! $add_group ) {
2023-01-10 10:51:18 +01:00
$this_error = " $log_prefix LDAP: unable to add new group ( { $group_dn } ): " . ldap_error ( $ldap_connection );
2022-04-12 15:43:21 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix DEBUG add_group array: " . strip_tags ( print_r ( $new_group_array , true )), 0 ); }
error_log ( $this_error , 0 );
2021-03-13 14:11:38 +00:00
}
else {
2022-04-12 15:43:21 +01:00
error_log ( " $log_prefix Added new group $group_name " , 0 );
if ( $update_gid_store == TRUE ) {
$this_gid = fetch_id_stored_in_ldap ( $ldap_connection , " gid " );
if ( $this_gid != FALSE ) {
2023-01-10 10:51:18 +01:00
$update_gid = @ ldap_mod_replace ( $ldap_connection , " cn=lastGID, { $LDAP [ 'base_dn' ] } " , array ( 'serialNumber' => $new_gid ));
2022-04-12 15:43:21 +01:00
if ( $update_gid ) {
error_log ( " $log_prefix Updated cn=lastGID with $new_gid " , 0 );
}
else {
error_log ( " $log_prefix Unable to update cn=lastGID to $new_gid - this could cause groups to share the same GID. " , 0 );
}
}
}
return TRUE ;
2021-03-13 14:11:38 +00:00
}
2022-04-12 15:43:21 +01:00
2018-06-01 17:10:45 +01:00
}
2022-04-12 15:43:21 +01:00
else {
error_log ( " $log_prefix Create group; group $group_name already exists. " , 0 );
}
}
else {
error_log ( " $log_prefix Create group; group name wasn't set. " , 0 );
}
return FALSE ;
}
##################################
function ldap_update_group_attributes ( $ldap_connection , $group_name , $extra_attributes ) {
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
if ( isset ( $group_name ) and ( count ( $extra_attributes ) > 0 )) {
$group_name = ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER );
2023-01-10 10:51:18 +01:00
$group_dn = " { $LDAP [ 'group_attribute' ] } = $group_name , { $LDAP [ 'group_dn' ] } " ;
2022-04-12 15:43:21 +01:00
$update_group = @ ldap_mod_replace ( $ldap_connection , $group_dn , $extra_attributes );
if ( ! $update_group ) {
2023-01-10 10:51:18 +01:00
$this_error = " $log_prefix LDAP: unable to update group attributes for group ( { $group_dn } ): " . ldap_error ( $ldap_connection );
2022-04-12 15:43:21 +01:00
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix DEBUG update group attributes array: " . print_r ( $extra_attributes , true ), 0 ); }
error_log ( $this_error , 0 );
return FALSE ;
2018-06-01 17:10:45 +01:00
}
else {
2022-04-12 15:43:21 +01:00
error_log ( " $log_prefix Updated group attributes for $group_name " , 0 );
return TRUE ;
2018-06-01 17:10:45 +01:00
}
}
else {
2022-04-12 15:43:21 +01:00
error_log ( " $log_prefix Update group attributes; group name wasn't set. " , 0 );
return FALSE ;
2018-06-01 17:10:45 +01:00
}
}
##################################
function ldap_delete_group ( $ldap_connection , $group_name ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
if ( isset ( $group_name )) {
2023-01-10 10:51:18 +01:00
$delete_query = " { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " , { $LDAP [ 'group_dn' ] } " ;
2020-05-06 17:19:20 +01:00
$delete = @ ldap_delete ( $ldap_connection , $delete_query );
2018-06-01 17:10:45 +01:00
if ( $delete ) {
error_log ( " $log_prefix Deleted group $group_name " , 0 );
return TRUE ;
}
else {
2020-05-06 17:19:20 +01:00
error_log ( " $log_prefix Couldn't delete group $group_name " . ldap_error ( $ldap_connection ) , 0 );
2018-06-01 17:10:45 +01:00
return FALSE ;
}
}
}
##################################
function ldap_get_gid_of_group ( $ldap_connection , $group_name ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
if ( isset ( $group_name )) {
2023-01-10 10:51:18 +01:00
$ldap_search_query = " ( { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " ) " ;
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query , array ( " gidNumber " ));
2020-05-06 17:19:20 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2018-06-01 17:10:45 +01:00
if ( isset ( $result [ 0 ][ 'gidnumber' ][ 0 ]) and is_numeric ( $result [ 0 ][ 'gidnumber' ][ 0 ])) {
return $result [ 0 ][ 'gidnumber' ][ 0 ];
}
}
return FALSE ;
}
2022-10-10 13:55:14 +01:00
##################################
function ldap_get_group_name_from_gid ( $ldap_connection , $gid ) {
global $log_prefix , $LDAP , $LDAP_DEBUG ;
if ( isset ( $gid )) {
$ldap_search_query = " (gidnumber= " . ldap_escape ( $gid , " " , LDAP_ESCAPE_FILTER ) . " ) " ;
2023-01-10 10:51:18 +01:00
$ldap_search = @ ldap_search ( $ldap_connection , " { $LDAP [ 'group_dn' ] } " , $ldap_search_query , array ( " cn " ));
2022-10-10 13:55:14 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
if ( isset ( $result [ 0 ][ 'cn' ][ 0 ])) {
return $result [ 0 ][ 'cn' ][ 0 ];
}
}
return FALSE ;
}
2018-06-01 17:10:45 +01:00
##################################
2022-04-12 15:43:21 +01:00
function ldap_complete_attribute_array ( $default_attributes , $additional_attributes ) {
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( isset ( $additional_attributes )) {
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
$user_attribute_r = explode ( " , " , $additional_attributes );
$to_merge = array ();
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
foreach ( $user_attribute_r as $this_attr ) {
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
$this_r = array ();
$kv = explode ( " : " , $this_attr );
$attr_name = strtolower ( filter_var ( $kv [ 0 ], FILTER_SANITIZE_FULL_SPECIAL_CHARS ));
$this_r [ 'inputtype' ] = " singleinput " ;
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( substr ( $attr_name , - 1 ) == '+' ) {
$this_r [ 'inputtype' ] = " multipleinput " ;
$attr_name = rtrim ( $attr_name , '+' );
}
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( substr ( $attr_name , - 1 ) == '^' ) {
$this_r [ 'inputtype' ] = " binary " ;
$attr_name = rtrim ( $attr_name , '^' );
}
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( preg_match ( '/^[a-zA-Z0-9\-]+$/' , $attr_name ) == 1 ) {
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( isset ( $kv [ 1 ]) and $kv [ 1 ] != " " ) {
$this_r [ 'label' ] = filter_var ( $kv [ 1 ], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
}
else {
$this_r [ 'label' ] = $attr_name ;
}
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
if ( isset ( $kv [ 2 ]) and $kv [ 2 ] != " " ) {
$this_r [ 'default' ] = filter_var ( $kv [ 2 ], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
}
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
$to_merge [ $attr_name ] = $this_r ;
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
}
}
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
$attribute_r = array_merge ( $default_attributes , $to_merge );
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
return ( $attribute_r );
2021-03-13 14:11:38 +00:00
2022-04-12 15:43:21 +01:00
}
else {
return ( $default_attributes );
}
2021-03-13 14:11:38 +00:00
}
##################################
function ldap_new_account ( $ldap_connection , $account_r ) {
2018-06-01 17:10:45 +01:00
2021-07-22 09:12:55 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG , $DEFAULT_USER_SHELL , $DEFAULT_USER_GROUP ;
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
if ( isset ( $account_r [ 'givenname' ][ 0 ])
and isset ( $account_r [ 'sn' ][ 0 ])
and isset ( $account_r [ 'cn' ][ 0 ])
and isset ( $account_r [ 'uid' ][ 0 ])
2021-07-22 09:12:55 +01:00
and isset ( $account_r [ $LDAP [ 'account_attribute' ]])
2022-04-12 15:43:21 +01:00
and isset ( $account_r [ 'password' ][ 0 ])) {
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$account_identifier = $account_r [ $LDAP [ 'account_attribute' ]][ 0 ];
$user_dn = $LDAP [ 'user_dn' ];
2023-01-10 10:51:18 +01:00
$ldap_search_query = " ( { $LDAP [ 'account_attribute' ] } = " . ldap_escape ( $account_identifier , " " , LDAP_ESCAPE_FILTER ) . " , $user_dn ) " ;
2022-04-12 15:43:21 +01:00
$ldap_search = @ ldap_search ( $ldap_connection , $user_dn , $ldap_search_query );
2021-07-22 09:12:55 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2018-06-01 17:10:45 +01:00
2021-07-22 09:12:55 +01:00
if ( $result [ 'count' ] == 0 ) {
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$hashed_pass = ldap_hashed_password ( $account_r [ 'password' ][ 0 ]);
2021-07-22 09:12:55 +01:00
unset ( $account_r [ 'password' ]);
2021-03-13 14:11:38 +00:00
2021-07-22 09:12:55 +01:00
$objectclasses = $LDAP [ 'account_objectclasses' ];
2021-03-13 14:11:38 +00:00
2021-07-22 09:12:55 +01:00
$account_attributes = array ( 'objectclass' => $objectclasses ,
'userpassword' => $hashed_pass ,
);
2018-06-01 17:10:45 +01:00
2021-07-22 09:12:55 +01:00
$account_attributes = array_merge ( $account_r , $account_attributes );
2021-03-13 14:11:38 +00:00
2022-10-10 13:55:14 +01:00
if ( ! isset ( $account_attributes [ 'uidnumber' ][ 0 ]) or ! is_numeric ( $account_attributes [ 'uidnumber' ][ 0 ])) {
2021-07-22 09:12:55 +01:00
$highest_uid = ldap_get_highest_id ( $ldap_connection , 'uid' );
2022-10-10 13:55:14 +01:00
$account_attributes [ 'uidnumber' ][ 0 ] = $highest_uid + 1 ;
2021-07-22 09:12:55 +01:00
}
2018-06-01 17:10:45 +01:00
2022-10-10 13:55:14 +01:00
if ( ! isset ( $account_attributes [ 'gidnumber' ][ 0 ]) or ! is_numeric ( $account_attributes [ 'gidnumber' ][ 0 ])) {
2021-07-22 09:12:55 +01:00
$default_gid = ldap_get_gid_of_group ( $ldap_connection , $DEFAULT_USER_GROUP );
if ( ! is_numeric ( $default_gid )) {
$group_add = ldap_new_group ( $ldap_connection , $account_identifier , $account_identifier );
2022-10-10 13:55:14 +01:00
$account_attributes [ 'gidnumber' ][ 0 ] = ldap_get_gid_of_group ( $ldap_connection , $account_identifier );
2021-07-22 09:12:55 +01:00
}
else {
2022-10-10 13:55:14 +01:00
$account_attributes [ 'gidnumber' ][ 0 ] = $default_gid ;
2021-07-22 09:12:55 +01:00
$add_to_group = $DEFAULT_USER_GROUP ;
}
}
2022-10-10 13:55:14 +01:00
else {
$add_to_group = ldap_get_group_name_from_gid ( $ldap_connection , $account_attributes [ 'gidnumber' ][ 0 ]);
if ( ! $add_to_group ) { $add_to_group = $DEFAULT_USER_GROUP ; }
}
2021-03-13 14:11:38 +00:00
2021-07-22 09:12:55 +01:00
if ( empty ( $account_attributes [ 'loginshell' ])) { $account_attributes [ 'loginshell' ] = $DEFAULT_USER_SHELL ; }
2022-04-12 15:43:21 +01:00
if ( empty ( $account_attributes [ 'homedirectory' ])) { $account_attributes [ 'homedirectory' ] = " /home/ " . $account_r [ 'uid' ][ 0 ]; }
2021-07-22 09:12:55 +01:00
$add_account = @ ldap_add ( $ldap_connection ,
2023-01-10 10:51:18 +01:00
" { $LDAP [ 'account_attribute' ] } = $account_identifier , { $LDAP [ 'user_dn' ] } " ,
2021-07-22 09:12:55 +01:00
$account_attributes
);
if ( $add_account ) {
error_log ( " $log_prefix Created new account: $account_identifier " , 0 );
ldap_add_member_to_group ( $ldap_connection , $add_to_group , $account_identifier );
$this_uid = fetch_id_stored_in_ldap ( $ldap_connection , " uid " );
2022-10-10 13:55:14 +01:00
$new_uid = $account_attributes [ 'uidnumber' ][ 0 ];
2021-07-22 09:12:55 +01:00
if ( $this_uid != FALSE ) {
2023-01-10 10:51:18 +01:00
$update_uid = @ ldap_mod_replace ( $ldap_connection , " cn=lastUID, { $LDAP [ 'base_dn' ] } " , array ( 'serialNumber' => $new_uid ));
2021-07-22 09:12:55 +01:00
if ( $update_uid ) {
error_log ( " $log_prefix Create account; Updated cn=lastUID with $new_uid " , 0 );
}
else {
error_log ( " $log_prefix Unable to update cn=lastUID to $new_uid - this could cause user accounts to share the same UID. " , 0 );
}
}
return TRUE ;
2021-03-13 14:11:38 +00:00
}
else {
2021-07-22 09:12:55 +01:00
ldap_get_option ( $ldap_connection , LDAP_OPT_DIAGNOSTIC_MESSAGE , $detailed_err );
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Create account; couldn't create the account for { $account_identifier } : " . ldap_error ( $ldap_connection ) . " -- " . $detailed_err , 0 );
2021-03-13 14:11:38 +00:00
}
2021-07-22 09:12:55 +01:00
}
2022-04-12 15:43:21 +01:00
2018-06-01 17:10:45 +01:00
else {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Create account; Account for { $account_identifier } already exists " , 0 );
2018-06-01 17:10:45 +01:00
}
}
else {
2021-07-22 09:12:55 +01:00
error_log ( " $log_prefix Create account; missing parameters " , 0 );
2018-06-01 17:10:45 +01:00
}
2021-07-22 09:12:55 +01:00
return FALSE ;
2018-06-01 17:10:45 +01:00
}
##################################
function ldap_delete_account ( $ldap_connection , $username ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
if ( isset ( $username )) {
2023-01-10 10:51:18 +01:00
$delete_query = " { $LDAP [ 'account_attribute' ] } = " . ldap_escape ( $username , " " , LDAP_ESCAPE_FILTER ) . " , { $LDAP [ 'user_dn' ] } " ;
2020-05-06 17:19:20 +01:00
$delete = @ ldap_delete ( $ldap_connection , $delete_query );
2018-06-01 17:10:45 +01:00
if ( $delete ) {
error_log ( " $log_prefix Deleted account for $username " , 0 );
return TRUE ;
}
else {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Couldn't delete account for { $username } : " . ldap_error ( $ldap_connection ), 0 );
2018-06-01 17:10:45 +01:00
return FALSE ;
}
}
}
##################################
function ldap_add_member_to_group ( $ldap_connection , $group_name , $username ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
2022-04-12 15:43:21 +01:00
$rfc2307bis_available = ldap_detect_rfc2307bis ( $ldap_connection );
2020-12-24 18:24:41 +00:00
2023-01-10 10:51:18 +01:00
$group_dn = " { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " , { $LDAP [ 'group_dn' ] } " ;
2018-06-01 17:10:45 +01:00
if ( $LDAP [ 'group_membership_uses_uid' ] == FALSE ) {
2023-01-10 10:51:18 +01:00
$username = " { $LDAP [ 'account_attribute' ] } = $username , { $LDAP [ 'user_dn' ] } " ;
2018-06-01 17:10:45 +01:00
}
$group_update = array ( $LDAP [ 'group_membership_attribute' ] => $username );
2020-05-06 17:19:20 +01:00
$update = @ ldap_mod_add ( $ldap_connection , $group_dn , $group_update );
2018-06-01 17:10:45 +01:00
if ( $update ) {
2021-03-13 14:11:38 +00:00
error_log ( " $log_prefix Added $username to group ' $group_name ' " , 0 );
2018-06-01 17:10:45 +01:00
return TRUE ;
}
else {
2021-03-13 14:11:38 +00:00
ldap_get_option ( $ldap_connection , LDAP_OPT_DIAGNOSTIC_MESSAGE , $detailed_err );
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Couldn't add $username to group ' { $group_name } ': " . ldap_error ( $ldap_connection ) . " -- " . $detailed_err , 0 );
2018-06-01 17:10:45 +01:00
return FALSE ;
}
}
##################################
function ldap_delete_member_from_group ( $ldap_connection , $group_name , $username ) {
2021-03-13 14:11:38 +00:00
global $log_prefix , $LDAP , $LDAP_DEBUG , $USER_ID ;
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
if ( $group_name == $LDAP [ 'admins_group' ] and $username == $USER_ID ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Won't remove { $username } from { $group_name } because you're logged in as { $username } and { $group_name } is the admin group. " , 0 );
2021-03-13 14:11:38 +00:00
return FALSE ;
}
else {
2022-04-12 15:43:21 +01:00
$rfc2307bis_available = ldap_detect_rfc2307bis ( $ldap_connection );
2020-12-24 18:24:41 +00:00
2023-01-10 10:51:18 +01:00
$group_dn = " { $LDAP [ 'group_attribute' ] } = " . ldap_escape ( $group_name , " " , LDAP_ESCAPE_FILTER ) . " , { $LDAP [ 'group_dn' ] } " ;
2018-06-01 17:10:45 +01:00
2021-07-22 09:12:55 +01:00
if ( $LDAP [ 'group_membership_uses_uid' ] == FALSE and $username != " " ) {
2023-01-10 10:51:18 +01:00
$username = " { $LDAP [ 'account_attribute' ] } = $username , { $LDAP [ 'user_dn' ] } " ;
2021-03-13 14:11:38 +00:00
}
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
$group_update = array ( $LDAP [ 'group_membership_attribute' ] => $username );
$update = @ ldap_mod_del ( $ldap_connection , $group_dn , $group_update );
2018-06-01 17:10:45 +01:00
2021-03-13 14:11:38 +00:00
if ( $update ) {
2021-07-22 09:12:55 +01:00
error_log ( " $log_prefix Removed ' $username ' from $group_name " , 0 );
2021-03-13 14:11:38 +00:00
return TRUE ;
}
else {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Couldn't remove ' $username ' from { $group_name } : " . ldap_error ( $ldap_connection ), 0 );
2021-03-13 14:11:38 +00:00
return FALSE ;
}
2018-06-01 17:10:45 +01:00
}
}
##################################
function ldap_change_password ( $ldap_connection , $username , $new_password ) {
2020-05-01 17:14:04 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2018-06-01 17:10:45 +01:00
#Find DN of user
2023-01-10 10:51:18 +01:00
$ldap_search_query = " { $LDAP [ 'account_attribute' ] } = " . ldap_escape ( $username , " " , LDAP_ESCAPE_FILTER );
2021-03-13 14:11:38 +00:00
$ldap_search = @ ldap_search ( $ldap_connection , $LDAP [ 'user_dn' ], $ldap_search_query );
2018-06-01 17:10:45 +01:00
if ( $ldap_search ) {
2020-05-06 17:19:20 +01:00
$result = @ ldap_get_entries ( $ldap_connection , $ldap_search );
2018-06-01 17:10:45 +01:00
if ( $result [ " count " ] == 1 ) {
$this_dn = $result [ 0 ][ 'dn' ];
}
else {
error_log ( " $log_prefix Couldn't find the DN for user $username " );
return FALSE ;
}
}
else {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Couldn't perform an LDAP search for { $LDAP [ 'account_attribute' ] } = { $username } : " . ldap_error ( $ldap_connection ), 0 );
2018-06-01 17:10:45 +01:00
return FALSE ;
}
2020-08-03 17:35:13 +01:00
$entries [ " userPassword " ] = ldap_hashed_password ( $new_password );
2020-05-06 17:19:20 +01:00
$update = @ ldap_mod_replace ( $ldap_connection , $this_dn , $entries );
2018-06-01 17:10:45 +01:00
if ( $update ) {
2020-05-06 17:19:20 +01:00
error_log ( " $log_prefix Updated the password for $username " , 0 );
2018-06-01 17:10:45 +01:00
return TRUE ;
}
else {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix Couldn't update the password for { $username } : " . ldap_error ( $ldap_connection ), 0 );
2018-06-01 17:10:45 +01:00
return TRUE ;
}
}
2020-12-24 18:24:41 +00:00
##################################
function ldap_detect_rfc2307bis ( $ldap_connection ) {
2022-04-12 15:43:21 +01:00
global $log_prefix , $LDAP , $LDAP_DEBUG ;
2020-12-24 18:24:41 +00:00
2022-04-12 15:43:21 +01:00
if ( isset ( $LDAP [ 'rfc2307bis_available' ])) {
return $LDAP [ 'rfc2307bis_available' ];
2020-12-24 18:24:41 +00:00
}
else {
2022-04-12 15:43:21 +01:00
$LDAP [ 'rfc2307bis_available' ] = FALSE ;
2020-12-24 18:24:41 +00:00
2022-04-12 15:43:21 +01:00
if ( $LDAP [ 'forced_rfc2307bis' ] == TRUE ) {
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - skipping autodetection because FORCE_RFC2307BIS is TRUE " , 0 ); }
$LDAP [ 'rfc2307bis_available' ] = TRUE ;
2020-12-24 18:24:41 +00:00
}
else {
2022-04-12 15:43:21 +01:00
$schema_base_query = @ ldap_read ( $ldap_connection , " " , " subschemaSubentry=* " , array ( 'subschemaSubentry' ));
if ( ! $schema_base_query ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix LDAP RFC2307BIS detection - unable to query LDAP for objectClasses under { $schema_base_dn } : " . ldap_error ( $ldap_connection ), 0 );
2022-04-12 15:43:21 +01:00
error_log ( " $log_prefix LDAP RFC2307BIS detection - we'll assume that the RFC2307BIS schema isn't available. Set FORCE_RFC2307BIS to TRUE if you DO use RFC2307BIS. " , 0 );
2020-12-24 18:24:41 +00:00
}
else {
2022-04-12 15:43:21 +01:00
$schema_base_results = @ ldap_get_entries ( $ldap_connection , $schema_base_query );
if ( $schema_base_results ) {
$schema_base_dn = $schema_base_results [ 0 ][ 'subschemasubentry' ][ 0 ];
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - found that the 'subschemaSubentry' base DN is ' $schema_base_dn ' " , 0 ); }
$objclass_query = @ ldap_read ( $ldap_connection , $schema_base_dn , " (objectClasses=*) " , array ( 'objectClasses' ));
if ( ! $objclass_query ) {
2023-01-10 10:51:18 +01:00
error_log ( " $log_prefix LDAP RFC2307BIS detection - unable to query LDAP for objectClasses under { $schema_base_dn } : " . ldap_error ( $ldap_connection ), 0 );
2022-04-12 15:43:21 +01:00
}
else {
$objclass_results = @ ldap_get_entries ( $ldap_connection , $objclass_query );
$this_count = $objclass_results [ 0 ][ 'objectclasses' ][ 'count' ];
if ( $this_count > 0 ) {
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - found $this_count objectClasses under $schema_base_dn " , 0 ); }
$posixgroup_search = preg_grep ( " /NAME 'posixGroup'.*AUXILIARY/ " , $objclass_results [ 0 ][ 'objectclasses' ]);
if ( count ( $posixgroup_search ) > 0 ) {
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - found AUXILIARY in posixGroup definition which suggests we're using the RFC2307BIS schema " , 0 ); }
$LDAP [ 'rfc2307bis_available' ] = TRUE ;
}
else {
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - couldn't find AUXILIARY in the posixGroup definition which suggests we're not using the RFC2307BIS schema. Set FORCE_RFC2307BIS to TRUE if you DO use RFC2307BIS. " , 0 ); }
}
}
else {
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - no objectClasses were returned when searching under $schema_base_dn " , 0 ); }
}
}
}
else {
if ( $LDAP_DEBUG == TRUE ) { error_log ( " $log_prefix LDAP RFC2307BIS detection - unable to detect the subschemaSubentry base DN " , 0 ); }
}
2020-12-24 18:24:41 +00:00
}
}
2022-04-12 15:43:21 +01:00
if ( $LDAP [ 'rfc2307bis_available' ] == TRUE ) {
if ( ! isset ( $LDAP [ 'group_membership_attribute' ])) { $LDAP [ 'group_membership_attribute' ] = 'uniquemember' ; }
if ( ! isset ( $LDAP [ 'group_membership_uses_uid' ])) { $LDAP [ 'group_membership_uses_uid' ] = FALSE ; }
if ( ! in_array ( 'groupOfUniqueNames' , $LDAP [ 'group_objectclasses' ])) { array_push ( $LDAP [ 'group_objectclasses' ], 'groupOfUniqueNames' ); }
return TRUE ;
}
else {
if ( ! isset ( $LDAP [ 'group_membership_attribute' ])) { $LDAP [ 'group_membership_attribute' ] = 'memberuid' ; }
if ( ! isset ( $LDAP [ 'group_membership_uses_uid' ])) { $LDAP [ 'group_membership_uses_uid' ] = TRUE ; }
return FALSE ;
}
2020-12-24 18:24:41 +00:00
2022-04-12 15:43:21 +01:00
}
2020-12-24 18:24:41 +00:00
}
2018-06-01 17:10:45 +01:00
?>