Example create profile password parameters

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Type Exemple DDL Oracle
Contexte Profil Oracle — volet mots de passe (complexité, expiration, verrouillage)
Voir aussi Example create profile resource parameters · Example database resource manager setup

Un profil Oracle (CREATE PROFILE) regroupe deux familles de règles indépendantes : les paramètres de mots de passe (traités ici) et les paramètres de limitation de ressources (traités dans Example create profile resource parameters). Un même profil peut combiner les deux, mais les scripts d'exemple les séparent pour rester lisibles — c'est la même séparation qui est reprise ici.

Ce script fournit une fonction PL/SQL de vérification de mot de passe (largement inspirée du script standard Oracle utlpwdmg.sql), puis un profil qui l'utilise via le paramètre PASSWORD_VERIFY_FUNCTION.

Fonction de complexité

La fonction verify_function rejette un mot de passe si :

  • il est identique (à la casse près) au nom d'utilisateur ;
  • il fait moins de 4 caractères ;
  • il figure dans une liste de mots trop simples (welcome, oracle,
 password…) ;
  • il ne contient pas au moins un chiffre, une lettre et un caractère de ponctuation ;
  • il diffère de moins de 3 caractères de l'ancien mot de passe.

Paramètres du profil

Paramètre Rôle
PASSWORD_LIFE_TIME Durée de validité du mot de passe (en jours, ou fraction de jour)
PASSWORD_GRACE_TIME Délai de grâce accordé pour changer le mot de passe après expiration
PASSWORD_REUSE_TIME / PASSWORD_REUSE_MAX Anti-réutilisation — l'un des deux doit rester à UNLIMITED
FAILED_LOGIN_ATTEMPTS Nombre d'échecs avant verrouillage du compte (ORA-28000)
PASSWORD_LOCK_TIME Durée du verrouillage après dépassement du seuil ci-dessus
PASSWORD_VERIFY_FUNCTION Fonction PL/SQL de contrôle de complexité

Pour exprimer une fraction de jour : y/z, où z est le nombre total de la sous-unité choisie (24 pour des heures, 1440 pour des minutes, 86400 pour des secondes). Exemple : laisser 6 heures de délai de grâce s'exprime 6/24 (soit 1/4 simplifié).

Script

CONNECT / AS SYSDBA

-- Fonction de vérification de la complexité du mot de passe
CREATE OR REPLACE FUNCTION verify_function (
    username      VARCHAR2
  , password      VARCHAR2
  , old_password  VARCHAR2
) RETURN BOOLEAN IS

  m           INTEGER;
  differ      INTEGER;
  isdigit     BOOLEAN;
  ischar      BOOLEAN;
  ispunct     BOOLEAN;
  digitarray  VARCHAR2(20);
  punctarray  VARCHAR2(25);
  chararray   VARCHAR2(52);

BEGIN

  digitarray := '0123456789';
  chararray  := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  punctarray := '!"#$%&()*+,-/:;<=>?_';

  -- Le mot de passe ne doit pas ressembler au nom d'utilisateur
  IF NLS_LOWER(password) = NLS_LOWER(username) THEN
    raise_application_error(-20001, 'Password same as or similar to user');
  END IF;

  -- Longueur minimale
  IF length(password) < 4 THEN
    raise_application_error(-20002, 'Password length less than 4');
  END IF;

  -- Liste de mots de passe trop simples
  IF NLS_LOWER(password) IN ('welcome', 'database', 'account', 'user',
                              'password', 'oracle', 'computer', 'abcd') THEN
    raise_application_error(-20002, 'Password too simple');
  END IF;

  -- Doit contenir au moins un chiffre, une lettre et un caractère de ponctuation
  isdigit := FALSE;
  m := length(password);
  FOR i IN 1..10 LOOP
    FOR j IN 1..m LOOP
      IF substr(password, j, 1) = substr(digitarray, i, 1) THEN
        isdigit := TRUE;
        GOTO findchar;
      END IF;
    END LOOP;
  END LOOP;
  IF isdigit = FALSE THEN
    raise_application_error(-20003, 'Password should contain at least one digit, one character and one punctuation');
  END IF;

  <<findchar>>
  ischar := FALSE;
  FOR i IN 1..length(chararray) LOOP
    FOR j IN 1..m LOOP
      IF substr(password, j, 1) = substr(chararray, i, 1) THEN
        ischar := TRUE;
        GOTO findpunct;
      END IF;
    END LOOP;
  END LOOP;
  IF ischar = FALSE THEN
    raise_application_error(-20003, 'Password should contain at least one digit, one character and one punctuation');
  END IF;

  <<findpunct>>
  ispunct := FALSE;
  FOR i IN 1..length(punctarray) LOOP
    FOR j IN 1..m LOOP
      IF substr(password, j, 1) = substr(punctarray, i, 1) THEN
        ispunct := TRUE;
        GOTO endsearch;
      END IF;
    END LOOP;
  END LOOP;
  IF ispunct = FALSE THEN
    raise_application_error(-20003, 'Password should contain at least one digit, one character and one punctuation');
  END IF;

  <<endsearch>>
  -- Doit différer de l'ancien mot de passe d'au moins 3 caractères
  IF old_password IS NULL THEN
    raise_application_error(-20004, 'Old password is null');
  END IF;

  differ := length(old_password) - length(password);

  IF abs(differ) < 3 THEN
    IF length(password) < length(old_password) THEN
      m := length(password);
    ELSE
      m := length(old_password);
    END IF;

    differ := abs(differ);

    FOR i IN 1..m LOOP
      IF substr(password, i, 1) != substr(old_password, i, 1) THEN
        differ := differ + 1;
      END IF;
    END LOOP;
    IF differ < 3 THEN
      raise_application_error(-20004, 'Password should differ by at least 3 characters');
    END IF;
  END IF;

  RETURN TRUE;

END;
/

-- Profil utilisant la fonction ci-dessus pour les règles de mot de passe
CREATE PROFILE developer_profile LIMIT
  PASSWORD_LIFE_TIME        60
  PASSWORD_GRACE_TIME       10
  PASSWORD_REUSE_TIME       1800
  PASSWORD_REUSE_MAX        UNLIMITED
  FAILED_LOGIN_ATTEMPTS     3
  PASSWORD_LOCK_TIME        1/1440
  PASSWORD_VERIFY_FUNCTION  verify_function
/

Voir aussi