A couple of months ago I enforced a password verify function on our 11.2.0.3 databases and also one legacy 10.2.0.4 database.
At the time I tested on my account (which had elevated privileges...doh!). Now some users are hitting expiry, they can't change it via SQL Developer.
If I create a user with 'create session' privilege and set their profile to one that uses the verify function (see both below), I then log in to SQL Developer (we have tried with versions 3.1 (Windows) and 3.2 (Linux) with same failure results.
BTW,.. the password verify function enforces the following:
- password must be minimum of 8 characters
- password must not be the same as the user name, or user name (1-100)
- password must contain at least a single digit
- password must contain at least a single character
1. Works = I log into the local server and run command line SQLPlus, type 'password' and update. I can successfully change my password.
2. Fails = I log into the local server and run command line SQLPlus, type 'alter user <me> identified by <newpwd>;' I get:
TEST: SUTEMP > alter user sutemp identified by carport9999;
alter user sutemp identified by carport9999
*
ERROR at line 1:
ORA-28221: REPLACE not specified
This error is because the account does not have the 'alter user' privilege. I'm okay with this, as I don't want our users having this privilege.
3. I start SQL Developer 3.2, type 'alter user <me> identified by <newpwd>;' I get the same ORA-28221 error as above. That is fine, and as expected.
4. Now in SQL Developer, I type 'password', set a valid password, but I get 'Failed to change password' in the Script Output tab.
I have a database 'after servererror on database' trigger set, and querying the database table it is logging into, I see a record with a date stamp matching my failure with a server_error=28221 (the same as above).
So I'm wondering if I'm doing something wrong here, or if this is a bug in SQL Developer. I don't want standard users having 'alter user' privileges, but I do want to enforce password verification.
I get the same result on three 11.2.0.3 databases (haven't tried any more but suspect same results for others) and one legacy 10.2.0.4 database, and using SQL Developer 3.1 and 3.2.
DBA_PROFILE used:
PROFILE |
|
RESOURCE_NAME |
|
RESOURCE LIMIT |
------------------------------ -------------------------------- -------- ----------------------------------------
CTRU |
|
|
COMPOSITE_LIMIT |
|
KERNEL DEFAULT |
CTRU |
|
|
SESSIONS_PER_USER |
KERNEL 10 |
CTRU |
|
|
CPU_PER_SESSION |
|
KERNEL DEFAULT |
CTRU |
|
|
CPU_PER_CALL |
|
KERNEL DEFAULT |
CTRU |
|
|
LOGICAL_READS_PER_SESSION KERNEL DEFAULT |
CTRU |
|
|
LOGICAL_READS_PER_CALL |
KERNEL DEFAULT |
CTRU |
|
|
IDLE_TIME |
|
KERNEL DEFAULT |
CTRU |
|
|
CONNECT_TIME |
|
KERNEL DEFAULT |
CTRU |
|
|
PRIVATE_SGA |
|
KERNEL DEFAULT |
CTRU |
|
|
FAILED_LOGIN_ATTEMPTS |
PASSWORD 10 |
CTRU |
|
|
PASSWORD_LIFE_TIME |
PASSWORD 180 |
CTRU |
|
|
PASSWORD_REUSE_TIME |
PASSWORD DEFAULT |
CTRU |
|
|
PASSWORD_REUSE_MAX |
PASSWORD 5 |
CTRU |
|
|
PASSWORD_VERIFY_FUNCTION PASSWORD VERIFY_FUNCTION_11G |
CTRU |
|
|
PASSWORD_LOCK_TIME |
PASSWORD .002 |
CTRU |
|
|
PASSWORD_GRACE_TIME |
PASSWORD 21 |
16 rows selected.
Verify Function used:
$ cat utlpwdmg.sql
Rem
Rem $Header: utlpwdmg.sql 02-aug-2006.08:18:05 asurpur Exp $
Rem
Rem utlpwdmg.sql
Rem
Rem Copyright (c) 2006, Oracle. All rights reserved.
Rem
Rem NAME
Rem utlpwdmg.sql - script for Default Password Resource Limits
Rem
Rem DESCRIPTION
Rem This is a script for enabling the password management features
Rem by setting the default password resource limits.
Rem
Rem NOTES
Rem This file contains a function for minimum checking of password
Rem complexity. This is more of a sample function that the customer
Rem can use to develop the function for actual complexity checks that the
Rem customer wants to make on the new password.
Rem
Rem MODIFIED (MM/DD/YY)
Rem suren 05/09/13 - customise for NIHI use
Rem asurpur 05/30/06 - fix - 5246666 beef up password complexity check
Rem nireland 08/31/00 - Improve check for username=password. #1390553
Rem nireland 06/28/00 - Fix null old password test. #1341892
Rem asurpur 04/17/97 - Fix for bug479763
Rem asurpur 12/12/96 - Changing the name of password_verify_function
Rem asurpur 05/30/96 - New script for default password management
Rem asurpur 05/30/96 - Created
Rem
-- This script sets the default password resource parameters
-- This script needs to be run to enable the password features.
-- However the default resource parameters can be changed based
-- on the need.
-- A default password complexity function is also provided.
-- This function makes the minimum complexity checks like
-- the minimum length of the password, password not same as the
-- username, etc. The user may enhance this function according to
-- the need.
-- This function must be created in SYS schema.
-- connect sys/<password> as sysdba before running the script
CREATE OR REPLACE FUNCTION verify_function_11G
(username varchar2,
password varchar2,
old_password varchar2)
RETURN boolean IS
n boolean;
m integer;
differ integer;
isdigit boolean;
ischar boolean;
ispunct boolean;
db_name varchar2(40);
digitarray varchar2(20);
punctarray varchar2(25);
chararray varchar2(52);
i_char varchar2(10);
simple_password varchar2(10);
reverse_user varchar2(32);
BEGIN
digitarray:= '0123456789';
chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-- Check for the minimum length of the password
IF length(password) < 8 THEN
raise_application_error(-20001, 'Password length less than 8');
END IF;
-- Check if the password is same as the username or username(1-100)
IF NLS_LOWER(password) = NLS_LOWER(username) THEN
raise_application_error(-20002, 'Password same as or similar to user');
END IF;
FOR i IN 1..100 LOOP
i_char := to_char(i);
if NLS_LOWER(username)|| i_char = NLS_LOWER(password) THEN
raise_application_error(-20005, 'Password same as or similar to user name ');
END IF;
END LOOP;
-- Check if the password contains at least one letter, one digit
-- 1. Check for the digit
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(-20008, 'Password must contain at least one digit, one character');
END IF;
-- 2. Check for the character
<<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 endsearch;
END IF;
END LOOP;
END LOOP;
IF ischar = FALSE THEN
raise_application_error(-20009, 'Password must contain at least one digit, and one character');
END IF;
<<endsearch>>
-- Check if the password differs from the previous password by at least
-- 3 letters
IF old_password IS NOT NULL THEN
differ := length(old_password) - length(password);
differ := abs(differ);
IF differ < 3 THEN
IF length(password) < length(old_password) THEN
m := length(password);
ELSE
m := length(old_password);
END IF;
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(-20011, 'Password should differ from the old password by at least 3 characters');
END IF;
END IF;
END IF;
-- Everything is fine; return TRUE ;
RETURN(TRUE);
END;
/
alter profile ctru limit password_verify_function verify_function_11g;
alter profile default limit password_verify_function verify_function_11g;
alter profile web_and_it limit password_verify_function verify_function_11g;