Page 1 of 1

Mise en place d'un système de connexion MD5 / LDAP

Posted: 22 Dec 2017, 14:34
by ArthurDmz
Bonjour j'ai travaillé sur la mise en place d'un système de connexion permettant d'utiliser simultanément le MD5 et le LDAP.
Afin de permettre d'utiliser ces deux systèmes de connexion j'ai utilisé ceci :

http://www.mantisbt.org/forums/viewtopi ... ldap+local

J'ai ensuite corrigé les différentes incohérences du au mode de connexion LDAP, dans le fichiers de connexion :

J'ai ajouté un champ, "account_type", à la base de données, dans la table mantis_user_table afin de différencier les utilisateurs LDAP et les utilisateur non LDAP.
Il a pour valeur par défaut 0 pour les utilisateur non LDAP et qui passe à 1 pour les utilisateurs LDAP.
J'ai ensuite modifié la fonction auth_auto_create_user dans la page core/authentication_api.php et user_create dans core/user_api.php afin de remplir correctement le nouveau champ lors de la création de nouveaux utilisateurs :

Code: Select all

/**
 * In the case where a user is attempting to authenticate but doesn't exist.
 * Check if the authentication provider supports auto-creation of users and
 * whether the password matches.
 *
 * @param string  $p_username   A prepared username.
 * @param string  $p_password   A prepared password.
 * @return int|boolean user id or false in case of failure.
 * @access private
 */
function auth_auto_create_user( $p_username, $p_password ) {
	$t_login_method = config_get( 'login_method' );
	# this variable return the value for the new field in the user table 
       $p_account_type = 0;

	if( $t_login_method == BASIC_AUTH ) {
		$t_auto_create = true;
	} else if( $t_login_method == LDAP && ldap_authenticate_by_username( $p_username, $p_password ) ) {
		$t_auto_create = true;
		$p_account_type = 1;
	} else {
		$t_auto_create = false;
	}

	if( $t_auto_create ) {
		# attempt to create the user

		if(!$p_account_type){
			$t_cookie_string = user_create( $p_username, md5( $p_password ), 1);
		}
		else {
			$t_cookie_string = user_create($p_username, $p_password, '', null, false, true, '', '', $p_account_type);
		}
		if( $t_cookie_string === false ) {
			# it didn't work
			return false;
		}

		# ok, we created the user, get the row again
		return user_get_id_by_name( $p_username );
	}

	return false;
}

Code: Select all

/**
 * Create a user.
 * returns false if error, the generated cookie string if valid
 *
 * @param string  $p_username     A valid username.
 * @param string  $p_password     The password to set for the user.
 * @param string  $p_email        The Email Address of the user.
 * @param integer $p_access_level The global access level for the user.
 * @param boolean $p_protected    Whether the account is protected from modifications (default false).
 * @param boolean $p_enabled      Whether the account is enabled.
 * @param string  $p_realname     The realname of the user.
 * @param string  $p_admin_name   The name of the administrator creating the account.
 * @param int $p_account_type     The value of the field for define if the user come to Active Directory. 
 * 1 = AD account & 0 = Mantis account.
 * @return string Cookie String
 */

function user_create( $p_username, $p_password, $p_email = '',
	$p_access_level = null, $p_protected = false, $p_enabled = true,
	$p_realname = '', $p_admin_name = '', $p_account_type = 0 ) {
	if( null == $p_access_level ) {
		$p_access_level = config_get( 'default_new_account_access_level' );
	}

	$t_password = auth_process_plain_password( $p_password );
	$c_enabled = (bool)$p_enabled;

	user_ensure_name_valid( $p_username );
	user_ensure_name_unique( $p_username );
	user_ensure_email_unique( $p_email );
	user_ensure_realname_unique( $p_username, $p_realname );
	email_ensure_valid( $p_email );

	$t_cookie_string = auth_generate_unique_cookie_string();

	db_param_push();
	$t_query = 'INSERT INTO {user}
				    ( username, email, password, date_created, last_visit,
				     enabled, access_level, login_count, cookie_string, realname, account_type )
				  VALUES
				    ( ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param()  . ',
				     ' . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ', ' . db_param() . ', ' . db_param() . ')';
	db_query( $t_query, array( $p_username, $p_email, $t_password, db_now(), db_now(), $c_enabled, (int)$p_access_level, 0, $t_cookie_string, $p_realname, $p_account_type) );

	# Create preferences for the user
	$t_user_id = db_insert_id( db_get_table( 'user' ) );

	# Users are added with protected set to FALSE in order to be able to update
	# preferences.  Now set the real value of protected.
	if( $p_protected ) {
		user_set_field( $t_user_id, 'protected', (bool)$p_protected );
	}

	# Send notification email
	if( !is_blank( $p_email ) ) {
		$t_confirm_hash = auth_generate_confirm_hash( $t_user_id );
		token_set( TOKEN_ACCOUNT_ACTIVATION, $t_confirm_hash, TOKEN_EXPIRY_ACCOUNT_ACTIVATION, $t_user_id );
		email_signup( $t_user_id, $t_confirm_hash, $p_admin_name );
	}

	event_signal( 'EVENT_MANAGE_USER_CREATE', array( $t_user_id ) );

	return $t_cookie_string;
}
Afin de rendre le champ mail obligatoire et éviter les erreurs de saisie de l'administrateur, j'ai ajouté un renvoie d'erreur si le champ mail est vide (N'oubliez pas, si ce n'est pas le cas, d'activer le champ e-mail dans sur la page manage_user_create_page.php) :

Code: Select all

$f_email = trim( $f_email );
email_ensure_not_disposable( $f_email );
if( is_blank( $f_email ) ) {
	trigger_error( ERROR_EMPTY_FIELD, ERROR );
}
Ensuite afin de pouvoir gérer les comptes non LDAP malgré la configuration LDAP il faut modifier les conditions d'affichage de la page account_page.php et account_update.php, afin que l'utilisateurs puisse gérer son mot de passe ainsi que son nom réel :

Code: Select all

# request for know the account_type value of the user
			$t_query = 'SELECT account_type 
				FROM {user} WHERE username = ' . db_param() ;
			
			$t_result = db_query( $t_query, array( $u_username) );
			
			while( $t_row = db_fetch_array( $t_result ) ) {
				$t_account_type = $t_row['account_type'];
			}

			if( $t_can_change_password && $t_account_type == 1) {
				# With LDAP -->
			?>
			<tr>
				<td class="category">
					<?php echo lang_get( 'username' ) ?>
				</td>
				<td>
					<?php echo string_display_line( $u_username ) ?>
				</td>
			</tr>
			<tr>
				<td class="category">
					<?php echo lang_get( 'password' ) ?>
				</td>
				<td>
					<?php echo lang_get( 'no_password_change' ) ?>
				</td>
			</tr><?php
			} else {
				# Without LDAP
				$t_show_update_button = true;
			?>
			<tr>
				<td class="category">
					<?php echo lang_get( 'username' ) ?>
				</td>
				<td>
					<?php echo string_display_line( $u_username ) ?>
				</td>
			</tr><?php
			# When verifying account, set a token and don't display current password
			if( $t_account_verification ) {
				token_set( TOKEN_ACCOUNT_VERIFY, true, TOKEN_EXPIRY_AUTHENTICATED, $u_id );
			} else {
			?>
			<tr>
				<td class="category">
					<span class="required"><?php if( $t_force_pw_reset ) { ?> * <?php } ?></span> <?php echo lang_get( 'current_password' ) ?>
				</td>
				<td>
					<input class="input-sm" id="password-current" type="password" name="password_current" size="32" maxlength="<?php echo auth_get_password_max_size(); ?>" />
				</td>
			</tr>
			<?php
			} ?>
			<tr>
				<td class="category">
					<span class="required"><?php if( $t_force_pw_reset ) { ?> * <?php } ?></span> <?php echo lang_get( 'new_password' ) ?>
				</td>
				<td>
					<input class="input-sm" id="password" type="password" name="password" size="32" maxlength="<?php echo auth_get_password_max_size(); ?>" />
				</td>
			</tr>
			<tr>
				<td class="category">
					<span class="required"><?php if( $t_force_pw_reset ) { ?> * <?php } ?></span> <?php echo lang_get( 'confirm_password' ) ?>
				</td>
				<td>
					<input class="input-sm" id="password-confirm" type="password" name="password_confirm" size="32" maxlength="<?php echo auth_get_password_max_size(); ?>" />
				</td>
			</tr>
			<?php
			}

Code: Select all

if( $t_ldap && ON == config_get( 'use_ldap_realname' ) && $t_account_type == 1 ) {
					# With LDAP
					echo '<td class="category">' . lang_get( 'realname' ) . '</td>';
					echo '<td>';
					echo string_display_line( ldap_realname_from_username( $u_username ) );
					echo '</td>';
				} else {
					# Without LDAP
					$t_show_update_button = true;
					echo '<td class="category">' . lang_get( 'realname' ) . '</td>';
					echo '<td>';
					echo '<input class="input-sm" id="realname" type="text" size="32" maxlength="' . DB_FIELD_SIZE_REALNAME . '" name="realname" value="' . string_attribute( $u_realname ) . '" />';
					echo '</td>';
				}

Code: Select all

$t_query = 'SELECT account_type 
	FROM {user} WHERE username = ' . db_param() ;
			
$t_result = db_query( $t_query, array( $u_username) );

while( $t_row = db_fetch_array( $t_result ) ) {
	$t_account_type = $t_row['account_type'];
}

# Update real name (but only if not a LDAP user)
if( $t_account_type == 0 ) {
	# strip extra spaces from real name
	$t_realname = string_normalize( $f_realname );
	if( $t_realname != user_get_field( $t_user_id, 'realname' ) ) {
		# checks for problems with realnames
		$t_username = user_get_field( $t_user_id, 'username' );
		user_ensure_realname_unique( $t_username, $t_realname );
		$t_update_realname = true;
	}
}
Pour que l'utilisateur non LDAP puisse modifier le mot de passe généré par Mantis à la création de son compte, il faut ajouter, à la fonction custom_function_default_auth_can_change_password la valeur "LDAP" :

Code: Select all

function custom_function_default_auth_can_change_password() {
	$t_can_change = array(
		PLAIN,
		CRYPT,
		CRYPT_FULL_SALT,
		LDAP,
		MD5,
	);
	if( in_array( config_get( 'login_method' ), $t_can_change ) ) {
		return true;
	} else {
		return false;
	}
}
Enfin, pour gérer la suppression ou la modification d'un utilisateur dans l'Active Directory et éviter qu'il puisse toujours se connecter avec ses anciens identifiants il faut modifier la fonction auth_does_password_match dans la page authentication_api.php :

Code: Select all

function auth_does_password_match( $p_user_id, $p_test_password ) {
	$t_configured_login_method = config_get( 'login_method' );

	if ( LDAP == $t_configured_login_method ) {
		# If the user's account type is 'LDAP' , then login with LDAP
		
		# request for know the account_type value of the user
		$t_query = 'SELECT account_type 
			FROM {user} WHERE id = ' . db_param() ;
		
		$t_result = db_query( $t_query, array( $p_user_id) );
		
		while( $t_row = db_fetch_array( $t_result ) ) {
			$t_account_type = $t_row['account_type'];
		}

		if($t_account_type == 1) {
		    if ( ldap_authenticate( $p_user_id, $p_test_password ) ) {
		    	# return true if an user use the LDAP authentication 
		        return true;
		    }
		    else {
		    	# false otherwise
		    	return false;
		    }
		}
	}
[...]
Ainsi si l'utilisateur est présent dans la base de données il vérifiera la valeur du account_type et orientera la connexion vers le LDAP ou non. :mrgreen:
Voilà de cette manière si votre configuration Mantis est correcte vous pourrez utiliser les deux systèmes de connexion en parallèle.

Re: Mise en place d'un système de connexion MD5 / LDAP

Posted: 27 Dec 2017, 15:52
by rkarmann
Salut,

Si tu avais pu posté cela il y a une semaine, tu m'aurais fais gagner beaucoup de temps :P

J'ai fini par utiliser une solution maison un peu bancale mais qui marche !

En tout cas ta contribution est solide, je pense qu'elle aidera bon nombre d'entre nous :)

Merci !

Re: Mise en place d'un système de connexion MD5 / LDAP

Posted: 08 Jan 2018, 11:09
by ArthurDmz
Je te remercie :oops: , j'espère en tout cas qu'elle va aider un maximum,ça fait plaisir de se rendre utilise. :D

Re: Mise en place d'un système de connexion MD5 / LDAP

Posted: 12 Feb 2018, 18:56
by rkarmann
Si je peux me permettre, un petit duplicata sur le forum "MantisBT - International" (en anglais donc) serait très, très utile ! J'ai encore vu passer une question sur le sujet il y a qq temps... Si tu as le temps bien sûr :D

Merci !

Re: Mise en place d'un système de connexion MD5 / LDAP

Posted: 27 Feb 2018, 16:47
by ArthurDmz
rkarmann wrote: 12 Feb 2018, 18:56 Si je peux me permettre, un petit duplicata sur le forum "MantisBT - International" (en anglais donc) serait très, très utile ! J'ai encore vu passer une question sur le sujet il y a qq temps... Si tu as le temps bien sûr :D

Merci !
Bien sûr je n'hésiterais pas dès que j'ai le temps à ajouter cette contribution sur le Forum Anglais.
Désolé, je n'ai pas été très actif ces derniers temps, je n'ai pas beaucoup surveillé mon post étant donné que je suis actuellement sur un nouveau projet.

Je vous remercie en tout cas pour votre intérêt, c'est plaisant de voir que son travail a pu être utile. :D

Re: Mise en place d'un système de connexion MD5 / LDAP

Posted: 28 Feb 2018, 08:54
by rkarmann
Pas de soucis, je comprends, nous avons tous des impératif et Mantis doit rester un +. Merci encore :D

Re: Mise en place d'un système de connexion MD5 / LDAP

Posted: 13 Apr 2018, 09:01
by aborderon
Bonjour,

merci pour votre travail, afin de faciliter l'implémentation de votre code, avez-vous la possibilité de le transformer en tant que pluggin Mantis à l'aide du pluggin SampleAuth : https://github.com/mantisbt-plugins/SampleAuth

Je vous remercie par avance.