Oracle 12c STIG Password Generator in PL/SQL 20188367001

Oracle 12c STIG Password Generator in PL/SQL

Creating or modifying an Oracle Database user password can be done by using any standard password generator you can find on the WEB. But I wanted a password to comply to “ora12c_strong_verify_function”, and this isn’t as easy to generate as you might expect. Though most generators provide options to include or exclude certain character groups, I wasn’t able to find one that will let you choose options in any detail and also let you set specific requirements.
So I took up the idea to code a PL/SQL based password generator that is as flexible as possible in the choice of included or excluded characters and can be configured to comply to Oracle requirements.
This is what the Oracle 12c documentation states in respect to the “ora12c_strong_verify_function”:

The ora12c_strong_verify_function provides a set of requirements that are recommended by the Department of Defense Database Security Technical Implementation Guide. This function checks for the following requirements when users create or modify passwords:
1. The password must contain at least two upper case characters, two lower case characters, two numeric characters, and two special characters. Specials are: ‘ ~ ! @ # $ % ^ & * ( ) _ – + = { } [ ] \ / < > , . ; ? ‘ : | (space)
2. The password must differ from the previous password by at least four characters.

The following internal checks are also applied:
3. The password contains no fewer than 9 characters and does not exceed 30 characters.
4. The password does not contain the double-quotation character (“). It can be surrounded by double-quotation marks, however.

What kind of Oracle password:
I’m familiar with the fact that Oracle passwords can be max 30 characters long, must
start with an uppercase or lowercase letter and – with numbers and letters – may contain only
3 special characters: # $ _
But what I discovered after some investigation and didn’t know yet, is that the restriction on start
and special characters is off when you encase the password in double quotes. This kind of Oracle
password now seems better practice to me because of the extra complexity, but I would still like
to avoid some tricky characters for easier command line or shell script password management:
` ‘ ^ @ ” (space)

About exclusion (or inclusion) of characters:
For easy configuration I decided to use a regular table with the first 127 ascii codes and their
respective characters. Some extra – true (1) or false (0) – colums serve as profiles for [ex|in]clusion
of specific characters.
I reckoned a random number generator, configured to produce an integer between 0 and 127, should be
able to produce – in combination with Oracle supplied function CHR – any character in the ascii table.
And If it happens to generate an excluded ascii code, well, I simply let the PL/SQL try again until
the generator hits an included ascii code.

How about password verification:
To address some specific STIG requirements like a minimum number of specific characters, as before, my
coding strategy is to apply a brute force tactic. The algorithm keeps on generating passwords until
one finally fulfills all requirements. This method of “retry until OK” could be time consuming.
Well, it isn’t… check this out:

Passwords generated with ORA_STIG01 profile may contain all characters with ascii code 32 to and including 126.
The only exclusion is the double-quoted mark with ascii code 34: ”
Default length: 14 characters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SQL> set timing on
SQL> select ams_password_pck.get_password_stig ( P_ora_stig => 1 ) from dual;
 
AMS_PASSWORD_PCK.GET_PASSWORD_STIG(P_ORA_STIG=>1)
----------------------------------------------------------------------------------------------------
81EPW]76z,q_i$
 
1 row selected.
 
Elapsed: 00:00:00.00
SQL> /
 
AMS_PASSWORD_PCK.GET_PASSWORD_STIG(P_ORA_STIG=>1)
----------------------------------------------------------------------------------------------------
_2BtA_>VmdA58u
 
1 row selected.
 
Elapsed: 00:00:00.00

Passwords generated with ORA_STIG02 profile are like passwords generated with ORA_STIG01 profile, but with
five extra exclusions on top of the double-quoted mark: ` ‘ ^ @ (space)
Default length: 14 characters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SQL> select ams_password_pck.get_password_stig ( P_ora_stig => 2 ) from dual;
 
AMS_PASSWORD_PCK.GET_PASSWORD_STIG(P_ORA_STIG=>2)
----------------------------------------------------------------------------------------------------
=DCg|Y}2DTxZu5
 
1 row selected.
 
Elapsed: 00:00:00.01
SQL> /
 
AMS_PASSWORD_PCK.GET_PASSWORD_STIG(P_ORA_STIG=>2)
----------------------------------------------------------------------------------------------------
92y0IB|+(eEVk?
 
1 row selected.
 
Elapsed: 00:00:00.00

ORA_DEF profile is meant for passwords without enclosed double quotes, and without any verification function.
Only numeric characters, uppercase and lowercase letters and 3 special characters are allowed: # $ _
In addition the password must start with an uppercase or lowercase letter.
Default length: 14 characters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SQL> select ams_password_pck.get_password( P_ora_def => 1 ) from dual;
 
AMS_PASSWORD_PCK.GET_PASSWORD(P_ORA_DEF=>1)
----------------------------------------------------------------------------------------------------
h4srali4#z2BLh
 
1 row selected.
 
Elapsed: 00:00:00.01
SQL> /
 
AMS_PASSWORD_PCK.GET_PASSWORD(P_ORA_DEF=>1)
----------------------------------------------------------------------------------------------------
PdaDEFZu6$VR1o
 
1 row selected.
 
Elapsed: 00:00:00.00
SQL> exit
 
Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Advanced Analytics
and Real Application Testing options (with complications)
$

Before installing the following code in some schema, connect with sys first and grant this schema owner execute on sys.ora12c_strong_verify_function… use the code at your discretion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
CREATE TABLE AMS_ASCII
(
  ASCII#      NUMBER(3),
  ASCIICHR    VARCHAR2(3 CHAR) NOT NULL,
  UPPERCHR    NUMBER(1) DEFAULT 0 NOT NULL,
  LOWERCHR    NUMBER(1) DEFAULT 0 NOT NULL,
  ORA_DEF     NUMBER(1) DEFAULT 0 NOT NULL,
  ORA_STIG01  NUMBER(1) DEFAULT 0 NOT NULL,
  ORA_STIG02  NUMBER(1) DEFAULT 0 NOT NULL,
  NUM         NUMBER(1) DEFAULT 0 NOT NULL
);
 
CREATE UNIQUE INDEX AMS_ASCII_PK ON AMS_ASCII(ASCII#);
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_PK PRIMARY KEY (ASCII#));
 
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_CK06 CHECK (NUM in (0,1)));
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_CK05 CHECK (ORA_STIG02 in (0,1)));
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_CK04 CHECK (ORA_STIG01 in (0,1)));
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_CK03 CHECK (ORA_DEF in (0,1)));
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_CK02 CHECK (LOWERCHR in (0,1)));
ALTER TABLE AMS_ASCII ADD (CONSTRAINT AMS_ASCII_CK01 CHECK (UPPERCHR in (0,1)));
 
CREATE OR REPLACE TRIGGER AMS_ASCII_B4IU
BEFORE INSERT OR UPDATE OF ASCII# ON AMS_ASCII
FOR EACH ROW
BEGIN
  :NEW.ASCIICHR := CHR(:NEW.ASCII#);
END;
/
  
SET DEFINE OFF;
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (0, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (1, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (2, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (3, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (4, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (5, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (6, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (7, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (8, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (9, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (10, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (11, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (12, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (13, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (14, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (15, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (16, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (17, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (18, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (19, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (20, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (21, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (22, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (23, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (24, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (25, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (26, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (27, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (28, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (29, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (30, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (31, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (32, 0, 0, 0, 1, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (33, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (34, 0, 0, 0, 0, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (35, 0, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (36, 0, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (37, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (38, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (39, 0, 0, 0, 1, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (40, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (41, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (42, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (43, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (44, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (45, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (46, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (47, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (48, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (49, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (50, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (51, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (52, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (53, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (54, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (55, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (56, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (57, 0, 0, 1, 1, 1, 1);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (58, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (59, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (60, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (61, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (62, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (63, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (64, 0, 0, 0, 1, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (65, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (66, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (67, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (68, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (69, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (70, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (71, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (72, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (73, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (74, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (75, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (76, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (77, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (78, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (79, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (80, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (81, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (82, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (83, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (84, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (85, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (86, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (87, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (88, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (89, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (90, 1, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (91, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (92, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (93, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (94, 0, 0, 0, 1, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (95, 0, 0, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (96, 0, 0, 0, 1, 0, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (97, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (98, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (99, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (100, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (101, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (102, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (103, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (104, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (105, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (106, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (107, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (108, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (109, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (110, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (111, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (112, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (113, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (114, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (115, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (116, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (117, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (118, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (119, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (120, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (121, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (122, 0, 1, 1, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (123, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (124, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (125, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (126, 0, 0, 0, 1, 1, 0);
Insert into AMS_ASCII (ASCII#, UPPERCHR, LOWERCHR, ORA_DEF, ORA_STIG01, ORA_STIG02, NUM) Values (127, 0, 0, 0, 0, 0, 0);
 
COMMIT
/
 
 
CREATE OR REPLACE PACKAGE        Ams_Password_Pck
AS
--------------------------------------------------------------------------------
FUNCTION Get_Password
  (  P_length_password      PLS_INTEGER := 14
   , P_ora_def              PLS_INTEGER := 0 )
  RETURN VARCHAR2;
 
-----------------------------------------------------------------
-- Create an oracle password that is validated by ora12c_strong_verify_function
/****************************************************************************************************
The ora12c_strong_verify_function function provides a set of requirements that
are recommended by the Department of Defense Database Security Technical Implementation Guide.
This function checks for the following requirements when users create or modify passwords:
--1--
The password must contain at least:
       two upper case characters,
       two lower case characters,
       two numeric characters, and
       two special characters. These special characters are as follows:
       ‘ ~ ! @ # $ % ^ & * ( ) _ - + = { } [ ] \ / < > , . ; ? ' : | (space)
--2--
The password must differ from the previous password by at least four characters.
--3--
The following internal checks are also applied:
    The password contains no fewer than 9 characters and does not exceed 30 characters.
    The password does not contain the double-quotation character (").
    It can be surrounded by double-quotation marks, however.
*****************************************************************************************************/
 
FUNCTION Get_Password_Stig
  (  P_old_password         VARCHAR2    := NULL
   , P_length_password      PLS_INTEGER := 14
   , P_ora_stig             PLS_INTEGER := 2 )
  RETURN VARCHAR2;
--------------------------------------------------------------------------------
  
END Ams_Password_Pck;
/
 
SHOW ERRORS;
 
CREATE OR REPLACE PACKAGE BODY        Ams_Password_Pck
AS
--------------------------------------------------------------------------------
   m   CONSTANT NUMBER   := 100000000;
   m1  CONSTANT NUMBER   := 10000;
   b   CONSTANT NUMBER   := 31415821;
   a   NUMBER            := TO_NUMBER( TO_CHAR( SYSTIMESTAMP, 'FFFFFFFFFF' ) );
    
--------------------------------------------------------------------------------
FUNCTION RANDOM
   ( r IN PLS_INTEGER := 127 )
  RETURN PLS_INTEGER
IS
    
  FUNCTION f
     ( p IN NUMBER
     , q IN NUMBER)
    RETURN NUMBER
  IS
     p1    NUMBER;
     p0    NUMBER;
     q1    NUMBER;
     q0    NUMBER;
  BEGIN
     p1 := TRUNC( p / m1 );
     p0 := MOD( p, m1 );
     q1 := TRUNC( q / m1 );
     q0 := MOD( q, m1 );
    
     RETURN( MOD( ( MOD( p0 * q1 + p1 * q0, m1 ) * m1 + p0 * q0 ), m ) );
  END f;
 
BEGIN
   /* generate a random number and set it to be the new seed */
   a := MOD( f( a, b ) + 1, m );
--   dbms_output.put_line(a);
    
   /* return random integer between [0,r-1] */
   RETURN ( TRUNC( ( TRUNC( a / m1 ) * r ) / m1 ));
END RANDOM;
 
--------------------------------------------------------------------------------
FUNCTION Get_Password
  (  P_length_password      PLS_INTEGER := 14
   , P_ora_def              PLS_INTEGER := 0 )
  RETURN VARCHAR2
IS
  pwd       VARCHAR2(30);
  pwd_part  PLS_INTEGER;
   
/* password length min 9, max 30 characters  */
  v_length_password PLS_INTEGER := CASE WHEN P_length_password < 9 THEN 9 WHEN P_length_password > 30 THEN 30
                                   ELSE P_length_password END;
BEGIN
 
-- start with a letter ( upper or lower ) if generating a regular oracle password
  IF P_ora_def = 1 THEN
    LOOP
    EXIT WHEN length(pwd) = 1;
      pwd_part := random(127);
      for i in (select asciichr chr
                from ams_ascii
                where (    upperchr = 1
                        or lowerchr = 1 )
                  and ascii# = pwd_part )
      loop
        pwd := pwd||i.chr;
      end loop;
    END LOOP;
  END IF;   
   
  LOOP
  EXIT WHEN length(pwd) = v_length_password;
    pwd_part := random(127);
     
/* use profile ora_def to include only letters, numbers and specials # $ _ */
    if P_ora_def = 1 then
      for i in (select asciichr chr
                from ams_ascii
                where ora_def = 1
                  and ascii# = pwd_part )
      loop
        pwd := pwd||i.chr;
      end loop;
       
/* only exclude (space) and control characters */
    else
      for i in (select asciichr chr
                from ams_ascii
                where ascii# > 32
                  and ascii# = pwd_part )
      loop
        pwd := pwd||i.chr;
      end loop;
    end if;     
  END LOOP;
   
  RETURN pwd;
   
END Get_Password;
 
---------------------------------------------------------------------------------------
FUNCTION Get_Password_Stig
  (  P_old_password         VARCHAR2    := NULL
   , P_length_password      PLS_INTEGER := 14
   , P_ora_stig             PLS_INTEGER := 2 )
  RETURN VARCHAR2
IS
  pwd       VARCHAR2(30);
  pwd_part  PLS_INTEGER;
   
/* password length min 9, max 30 characters  */  
  v_length_password PLS_INTEGER := CASE WHEN P_length_password < 9 THEN 9 WHEN P_length_password > 30 THEN 30
                                   ELSE P_length_password END;
BEGIN
  LOOP
  EXIT WHEN length(pwd) = v_length_password;
    pwd_part := random(127);
     
/* use profile ora_stig01 to exclude special character " and control characters */   
    if P_ora_stig =1
    then   
      for i in (select asciichr chr
                from ams_ascii
                where ora_stig01 = 1
                  and ascii# = pwd_part )
      loop
        pwd := pwd||i.chr;
      end loop;
       
/* use profile ora_stig02 to exclude special characters "` ' ^ @ " (space) and control characters */
    elsif P_ora_stig = 2
    then
      for i in (select asciichr chr
                from ams_ascii
                where ora_stig02 = 1
                  and ascii# = pwd_part )
      loop
        pwd := pwd||i.chr;
      end loop;
    end if;     
  END LOOP;
 
/* check if the new password contains two upper case, two lower case, two numeric,
   and two special characters. if not... try again */
  IF (    ( length(pwd) = trim(length(translate( pwd,' 01234',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' 56789',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' abcdefghijklm',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' nopqrstuvwxyz',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' ABCDEFGHIJKLM',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' NOPQRSTUVWXYZ',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' !#$%^*()_-+={',' '))) )
       OR ( length(pwd) = trim(length(translate( pwd,' }[]\/<>,.;?:|',' '))) )
     ) THEN
    pwd := Get_Password_Stig ( P_old_password
                             , P_length_password
                             , P_ora_stig );
  END IF;
 
/* if P_old_password is not null, check if the new password differs at least 4
   characters from the old one.  if not, this function raises an application error */
  IF sys.ora12c_strong_verify_function (NULL,pwd,P_old_password) then 
    RETURN pwd;
  END IF;
   
  RETURN ('NO VALUE');
   
END Get_Password_Stig;
 
---------------------------------------------------------------------------------------
END Ams_Password_Pck;
/
 
SHOW ERRORS;

One Response

  1. Manuel August 23, 2018