Wednesday, August 31, 2022

dnf (yum) throws "The SSL certificate failed verification" error

All of a sudden an application named dnf (a successor of yum, used as package manager on Oracle Linux OS) stopped functioning, but throwing the message from the title, even when it's being called with help option(s). The main cause was local machine time, it wasn't synchronized with real clock time. The solution was to sync it, as well as modify the chrony.conf (add string like 'server vm_host iburst' in order to sync time quickly after save_vm->restore_vm operation) and run the dnf with required options :

# systemctl stop chronyd

# chronyd -q 'pool pool.ntp.org iburst'

# systemctl start chronyd

# dnf help

Good Luck !

Monday, August 29, 2022

Authentication of Oracle database users in Microsoft Active Directory - outlook

The assignment - to exclude maintenance of two equal user entities (in Microsoft AD and Oracle DB) and provide password-less entrance into database provided successful authorization in AD. User starts its session on Windows, and run 2-level applications which require authorization in the databases as well.

All the info below is a conspectus. Please look through official Oracle Security documents and blogs for the information in detail. Good starting point is :

https://blogs.oracle.com/database/post/make-someone-else-do-the-work-managing-oracle-database-19c-users-in-active-directory-part-1-kerberos 

1. Important database parameter is os_authent_prefix. Default value of it is "OPS$". It's a prefix to the operating system (OS) username. In order to have equal database and OS usernames, leave the null value for this parameter. It's not online and PDB modifiable - you need to restart the DB/CDB. 

2. Authentication goes through Kerberos5 protocol, port 88 (default) should be accessible from database server(s).

3. Edition of database - Enterprise (EE) 

4. You need to create so called proxy technological AD user on behalf of whum the kerberos5 ticket will be received on the database side. Toggle "Password never expires", deselect "DES encryption" and "Kerberos Pre-authentication".

On AD side enter the command :

c:> ktpass -princ oracle/db_server_dns_name.dns_domain_name@DOMAIN_NAME -pass <password> -mapuser technological_user@DOMAIN_NAME -crypto all -ptype KRB5_NT_PRINCIPAL -out c:\krb5.keytab. 

DOMAIN_NAME (i.e. AD domain name) must always be in upper-case, including in database sql statements containing oracle usernames.

Put resulted file to $ORACLE_HOME/network/admin server directory.

!Important! Objects in AD have so called knum attribute (analog of SCN 😀 in Oracle DB), which goes forward after any alterations of the user. So keep the keytab file in sync with this AD user. After any alteration of technological user recreate keytab file, because database checks the equality of technological user's knum and knum inside keytab. Also, because of this, create dedicated AD user for every other (standby or else) database servers. 

5. Example of Oracle server configuration files :

5.1 Add these lines into sqlnet.ora

# kerberos parameters
sqlnet.kerberos5_conf                  = /u01/app/oracle/product/1910/network/admin/krb5.conf
sqlnet.kerberos5_conf_mit              = true
sqlnet.fallback_authentication         = true
sqlnet.authentication_kerberos5_service = oracle
sqlnet.authentication_services         = (beq, kerberos5pre, kerberos5)
names.directory_path                   = (ldap, tnsnames, ezconnect, hostname)
# server-side only
sqlnet.kerberos5_keytab                = /u01/app/oracle/product/1910/network/admin/krb5.keytab

5.2 krb5.conf

[libdefaults]
 default_realm = DOMAIN_NAME
 clockskew = 6000
 passwd_check_s_address = false
 noaddresses = true
 forwardable = yes
[realms]
  DOMAIN_NAME = {
   kdc = domain_controller_1.DOMAIN_NAME:88
   kdc = domain_controller_2.DOMAIN_NAME:88
 }
[domain_realm]
  .domain_name =
DOMAIN_NAME 
   domain_name =
DOMAIN_NAME
  .
DOMAIN_NAME = DOMAIN_NAME
  
DOMAIN_NAME = DOMAIN_NAME

5.3 Also it's important to enable tracing on the server in case of  troubleshooting (there gonna be lots of trace files with huge amount of space; so keep an eye on the free space in trace file directory). The example of enabled tracing in sqlnet.ora :

# trace
DIAG_ADR_ENABLED = off
TRACE_LEVEL_SERVER = on
TRACE_DIRECTORY_SERVER = /u01/app/oracle/product/1910/krb5/trace
TRACE_FILE_SERVER=oracle

Some of the settings are enabled on the fly, but very likely you should restart database to enable most of them.

6. On the client machine add authentication settings to sqlnet.ora :

sqlnet.kerberos5_conf                  = %ORACLE_HOME%\network\admin\krb5.conf
sqlnet.kerberos5_conf_mit              = true
sqlnet.fallback_authentication         = true
sqlnet.authentication_kerberos5_service = oracle
sqlnet.authentication_services         = (kerberos5pre, kerberos5)
sqlnet.kerberos5_cc_name                = OSMSFT://

krb5.conf may be replicated from the database server. 

!Important! If the task or program doesn't support AD authentication and there's a need to logon to database user authenticated by the database, use another dedicated sqlnet.ora with sqlnet.authentication_services = none.

Also make sure that file %windir%\system32\drivers\etc\services contains lines:

kerberos 88/tcp kerberos5 krb5 kerberos-sec #Kerberos

kerberos 88/udp kerberos5 krb5 kerberos-sec #Kerberos

7. Alter database user to authenticate using Microsoft AD :

SQL> alter user username identified externally as '<ad_user>.DOMAIN_NAME' ;

8. Check username and corresponding AD usernames (with domain) in rhw :

SQL> select username, external_name from dba_users where external_name is not null ;

9. Connect to the database without entering username/password, for example :

c:> sqlplus /@tns_name_for_connect

SQL> select user, sys_context('userenv','authentication_method'), sys_context('userenv','authenticated_identity') from dual ;

Basically, that's all. Hope it'll help ! Enjoy ;-)

Thursday, August 25, 2022

ORA-06502: PL/SQL: numeric or value error when calling PL/SQL procedure via dblink

Suppose we've got 2 Oracle databases connected via db link : client db and server db. On the client database the PL/SQL procedure (from the package) calls another procedure via database link (from package on the server database) and saves the result into a cursor (which is also declared via the same database link). Next the result is processed and data is delivered to the application.

Out of the sudden, an application started to get the error 6502 sometimes. As it's figured out the cause laid in the length of varchar2 variable (let's call it 'a'). So, 'a' is declared varchar2 (100) variable (in bytes) inside a pl/sql procedure on the client side. It gets data via database link from the cursor (declared via database link as I said before), created on the server side (the corresponding column also has varchar2 (100) datatype (in bytes)). 

It seems when client database gets the value of the this column in language different from English it internally converts it into client database characterset (from server database characterset - CL8MSWIN1251 to AL32UTF8 - characterset of client database). When converted value's length is greater then 100 bytes - the error ORA-06502 is arising. At this point increasing variable length (to 1000) fixed the issue. 

I hope you were able to comprehend the above ;-) Good Luck !!!

PS: simplified version of the client procedure :

PACKAGE BODY package_body AS
c_num varchar2(30);
FUNCTION getfullinfo(c VARCHAR2,date_from VARCHAR2,date_to VARCHAR2,flag NUMBER DEFAULT 0, cr NUMBER DEFAULT 0, megat NUMBER DEFAULT 0) RETURN curstype
IS
curs cursType;
recTableremote server_user.server_package.table_type@db_link;
recTablelocal local_user.local_package.table_type;
rec
local_user.local_package.record_type;
BEGIN

recTablelocal := {initializing the type} ;
server_user.server_package.procedure@db_link(c, date_from, date_to, flag, cr, megat, recTableremote);
 

for i in 1 .. recTableremote.count
loop
rec.row_numb :=
recTableremote(i).row_numb;
...