Nous avons vu dans l’article précédent comment récupérer les propriétés d’un compte utilisateur depuis l’AD, mais aussi de déterminer avec Powershell quelles sont les propriétés de n’importe quel type d’objet. Le souci avec les comptes d’utilisateur ou d’ordinateur, c’est qu’ils peuvent être désactivés et donc n’accèdent plus au domaine. Vous devez absolument en tenir compte, notamment dans l’exemple d’application de login que nous allons créer.
L’intérêt de désactiver un compte AD, qu’il soit utilisateur ou ordinateur, est d’empêcher à cette personne ou à cette machine d’accéder aux ressources partagées sur le domaine (des répertoires, des données…). C’est souvent le cas après qu’un utilisateur ait quitté une entreprise, ou que le PC a été infecté par un virus : on l’isole du reste du réseau, pour éviter les pires ennuis.
Le but aujourd’hui étant de créer un petit formulaire de login, il faudra évidemment vérifier que le compte de l’utilisateur n’est pas désactivé avant de lui permettre de se connecter à notre appli. Pour cela, il faut lire une propriété spéciale de l’objet AD, le useraccountcontrol.
Coucou, tu veux voir mon bit ?
Cette propriété useraccountcontrol a une particularité : il s’agit d’un masque de bits (non, n’imaginez rien), ou bitmask en anglais. Autrement dit, il s’agit d’une combinaison de plusieurs valeurs qui doivent être isolées pour obtenir l’information recherchée.
Un petit rappel : les ordinateurs ne savent compter qu’en binaire, ou base deux. Autrement dit, les seules valeurs qu’ils connaissent sont le 0 et le 1. Évidemment, on ne va pas bien loin avec deux valeurs : pour pallier à cette limite, il suffit de rajouter un chiffre et lui attribuer une puissance supplémentaire. Explication : en base 10 (ou décimal), qui est la façon de compter à l’école, nous avons les unités, puis les dizaines, puis les centaines, les milliers, etc. Autrement dit, lorsqu’on rajoute un chiffre à la gauche du précédent, on change de puissance de 10 : les dizaines sont 10 à la puissance 1, les centaines 10 à la puissance 2, les milliers 10 à la puissance 3, etc. En binaire, le principe est le même sauf qu’au lieu d’utiliser des puissances de 10, on utilise des puissances de 2. Ainsi, on commence à 2 puissance 0 (exprimé par 2^0), ce qui fait 1. Comme un bit a deux valeurs possibles (0 ou 1), cela nous donne :
bit à 0 : 0 x 2^0 = 0 x1 = 0
bit à 1 : 1 x 2^0 = 1 x 1 = 1
On ne peut pas dire que c’est compliqué. Rajoutons un second bit, à la gauche du premier. Lui aussi peut prendre deux valeurs (0 ou 1), mais cette fois-ci, la puissance de 2 augmente d’un cran, soit 2^1 (ce qui est égal à 2 en décimal). Ce bit vaudra donc :
bit à 0 : 0 x 2^1 = 0 x 2 = 0
bit à 1 : 1 x 2^1 = 1 x 2 = 2
Avec un troisième bit, soit 2^2 (ce qui est égal à 4) :
bit à 0 : 0 x 2^2 = 0 x 4 = 0
bit à 1 : 1 x 2^2 = 1 x 4 = 4
Par convention, le bit correspondant à 2^0 est appelé bit 0, celui correspondant à 2^1 bit 1, celui correspondant à 2^2 bit 2, etc… Ajoutons ces bits les uns aux autres (tout en respectant l’ordre, qui va de droite à gauche, comme en décimal) :
Valeur binaire : 101 = (1 x 2^2) + (0 x 2^1) + (1 x 2^0) = (1 x 4) + (0 x 2) + (1 x 1) = 4 + 0 + 1 = 5 en décimal
Valeur binaire : 1111 = 8 + 4 + 2 + 1 = 15 en décimal
Maintenant que vous savez convertir du binaire en décimal, vous vous doutez bien qu’il est possible de faire l’inverse, et donc de convertir du décimal en binaire. Les processeurs passent leur temps à faire ce genre de conversion pour être plus compréhensibles pour les humains (et même si je parle binaire et hexadécimal (base 16) assez couramment, j’avoue que je vais plus vite en base 10).
Comme en binaire tout est puissance de 2, lorsqu’on veut convertir une valeur binaire en décimal, il faut prendre la puissance de 2 immédiatement inférieure ou égale à la valeur en décimal, la déduire de notre valeur, et recommencer jusqu’à ce qu’il ne reste plus rien. Démonstration : prenons la valeur décimal 4128. Quelle est la puissance de 2 immédiatement inférieure ? 4096, soit 2^12 (on sait déjà qu’il faudra donc 13 bits pour coder 4128, vu qu’on est au-delà de 4096).
Ensuite, on ôte 4096 de 4128 : il nous reste donc 32. Quelle est la puissance de 2 immédiatement inférieure ou égale à 32 ? Ben c’est 32, ou 2^5 ! Et il ne reste rien après. On peut donc écrire 4128 en binaire de cette façon :
0001 0000 0010 0000
Notez que j’ai rassemblé mes bits en quadruplets (nibbles en anglais, quatre bits) pour me faciliter la vie : les ordinateurs utilisent des groupes de bits de taille variable, mais toujours par groupes de 8 : 8 bits font un octet, 16 bits un mot, 32 bit un mot long etc. Là nous avons typiquement besoin d’un mot de 16 bits pour pouvoir écrire notre valeur 4128 en binaire.
N’oubliez pas que le bit 0 est celui le plus à droite : on l’appelle également bit de poids faible (ou LSB, Less Significant Bit), puis qu’un changement de valeur aura peu de poids sur le résultat final (de fait, si je mets ce bit à 1 dans mon exemple, je passe de 4128 à 4129 seulement). Conséquence, ce bit 0 sert aussi à déterminer si une valeur est paire (bit 0 à 0) ou impaire (bit 0 à 1). Et oui, vous pouvez écrire n’importe quel nombre en binaire, si ce bit est à 0, vous n’aurez forcément que des nombres pairs en décimal. Et inversement, des nombres impairs s’il est à 1.
Le bit le plus à gauche (dans notre exemple, le bit 15) est appelé le bit de poids fort (ou MSB, Most Significant Bit), car un changement de sa valeur aura d’énormes conséquences sur le résultat final : si je le mets à 1, on passe de 4128 à 36896, car 2^15 = 32768 ! Ça fait une grosse différence…
Bon, c’est bien beau toutes ces histoires de bits, mais quel est le rapport avec la propriété useraccountcontrol ? Comme je l’ai dit au début, cette propriété est un masque de bits, et il y a une logique derrière tout ça vu que nous allons devoir effectuer une opération logique – c’est logique – sur ce masque de bits pour savoir si notre compte est désactivé ou pas !
Logique floue
Certes, si vous n’avez pas l’habitude de programmer, tout ceci a l’air un peu confus. Mais en réalité c’est simple. En gros, notre propriété useraccountcontrol va nous renvoyer une valeur décimale, par exemple 4128, et comme je vous l’ai dit, cette valeur décimale code en fait plusieurs significations, chacune représentée par un bit. La signification – ou indicateur de propriété – qui nous intéresse, c’est le bit 1 (qui vaut donc 0 ou 2 en décimal), et qui correspond à ACCOUNTDISABLE dans le tableau ci-dessous :
[table]
Indicateur de propriété,Valeur hexadécimale,Valeur décimale
SCRIPT,0 x 0001,1
ACCOUNTDISABLE,0 x 0002,2
HOMEDIR_REQUIRED,0 x 0008,8
LOCKOUT,0 x 0010,16
PASSWD_NOTREQD,0 x 0020,32
PASSWD_CANT_CHANGE,0 x 0040,64
ENCRYPTED_TEXT_PWD_ALLOWED,0 x 0080,128
TEMP_DUPLICATE_ACCOUNT,0 x 0100,256
NORMAL_ACCOUNT,0 x 0200,512
INTERDOMAIN_TRUST_ACCOUNT,0 x 0800,2048
WORKSTATION_TRUST_ACCOUNT,0 x 1000,4096
SERVER_TRUST_ACCOUNT,0 x 2000,8192
DONT_EXPIRE_PASSWORD,0 x 10000,65536
MNS_LOGON_ACCOUNT,0 x 20000,131072
SMARTCARD_REQUIRED,0 x 40000,262144
TRUSTED_FOR_DELEGATION,0 x 80000,524288
NOT_DELEGATED,0 x 100000,1048576
USE_DES_KEY_ONLY,0x200000,2097152
DONT_REQ_PREAUTH,0 x 400000,4194304
PASSWORD_EXPIRED,0x800000,8388608
TRUSTED_TO_AUTH_FOR_DELEGATION,0x1000000,16777216
PARTIAL_SECRETS_ACCOUNT,0x04000000,67108864
[/table]
Vous voyez le principe ? Notre valeur retournée par la propriété useraccountcontrol sera la somme des valeurs de chaque indicateur activé (dont le bit correspondant est à 1). Si nous reprenons notre exemple de 4128, une fois décomposé c’est la somme de 4096 et 32, et donc les indicateurs WORKSTATION_TRUST_ACCOUNT et PASSWD_NOTREQD sont actifs (et au passage, ACCOUNTDISABLE ne l’est pas, donc notre compte n’est pas désactivé). Peu importe la signification de ces indicateurs, seul ACCOUNTDISABLE nous intéresse pour le moment. Si toutefois vous êtes curieux (ce qui n’est pas un vilain défaut), vous pouvez consulter la KB305144 sur le Technet.
Alors, comment déterminer si notre bit 1 – autrement dit la valeur 2, ou ACCOUNTDISABLE – est activée ou non en PHP ? Tout simplement avec l’opération logique AND (et). En pseudo-code, voilà ce que ça donne :
Si la condition (valeur de Useraccountcontrol ET 2) est vraie, alors le compte est désactivé. Sinon le compte n'est pas désactivé.
Traduit en PHP :
if($useraccountcontrol & 2) // le & veut dire AND { echo "Compte désactivé !"; } else { echo "Compte pas désactivé !"; }
Tout ça pour ça ?
Et oui, j’estime ce petit rappel nécessaire, ça ne fait pas de mal de bien comprendre ce point pour la suite de la série. Évidemment, vous vous doutez que notre variable $useraccountcontrol contient la valeur que vous avez récupéré depuis un résultat de recherche LDAP, provenant donc d’un tableau multidimensionnel tel qu’on en a vu dans les deux articles précédents… Il aurait donc fallu au préalable écrire la ligne suivante :
$useraccountcontrol=$result[0]["useraccountcontrol"][0];
…mais je parie que vous l’aviez deviné.
Comme je n’avais pas prévu d’écrire un tel pavé dès potron-minet un dimanche, je remets l’exercice pratique au prochain article, qui cette fois-ci sera orienté code : vous aurez l’occasion de faire du HTML, du Javascript et du PHP, rien que ça ! Tchüss !