21 dic 2014

IBM i - Listando journals de auditoría usando PHP

Los journals de auditoría son bastante útiles a la hora de dar seguimiento a actividad de los usuarios. Para poder activar la auditoría del IBM i es necesario :

1) Crear un journal receiver y el journal, que es el que permitirá guardar la información. Es aconsejable respaldar los journals con cierta frecuencia para poder depurarlos. Lo ideal es respaldarlos de forma separada a los datos del equipo, por lo que recomienda crear una biblioteca especialmente para ellos

CRTLIB JRNLIB
RTJRNRCV JRNRCV(JRNLIB/AUD)
CRTJRN JRN(QSYS/QAUDJRN) JRNRCV(JRNLIB/AUD)   

2) Cambiar los valores del sistema para que se active la recogida de información

WRKSYSVAL y cambiar los siguientes valores

QAUDCTL
 *AUDLVL 
*OBJAUD 
*NOQTEMP

QAUDLVL
*AUTFAIL
*CREATE 
*DELETE 
*SECURITY
*SAVRST 

3) Marcar los usuarios que deseemos como auditables. Lo mismo podemos hacer con los objetos

La información se irá recogiendo en los receivers, pero no será muy util si no la podemos leer de forma cómoda.
Para tal fin, y pensando en poder armar reportes de auditoría, creé un par de programas en PHP que permiten listar estos informes.

Armé un pequeño CL que diariamente lista los incidentes de seguridad de AF (Fallas de autorización) y PW (Fallas de usuario y/o password) y guarda la información en una tabla

PGM                                                                   
                                                                      
             DCL        VAR(&FECHA1) TYPE(*CHAR) LEN(6)               
             DCL        VAR(&FECHA2) TYPE(*CHAR) LEN(8)               
             RTVSYSVAL  SYSVAL(QDATE)  RTNVAR(&FECHA1)                
             CVTDAT    DATE(&FECHA1) TOVAR(&FECHA2) FROMFMT(*sysval) +
                          TOFMT(*DMY) TOSEP(*NONE)                    
             chgvar     (&FECHA2)  Value(%SST(&FECHA2 1 4) *TCAT +    
                        '20' *TCAT %SST(&FECHA2 5 2))                 
             SNDMSG     MSG(&FECHA2) TOUSR(BOMIAUD)                   
             CPYAUDJRNE ENTTYP(AF PW CD) OUTFILE(MYLIB/QAUDIT) +  
                          OUTMBR(*FIRST *ADD) JRNRCV(*CURCHAIN) +     
                          FROMTIME(&FECHA2 000000)                    
             MONMSG     MSGID(CPF0000)                                
ENDPGM


Este pequeño CL lo agregué en el JOB SCHEDULLER para que diariamente ejecute en las noches y vaya poblando mis tablas de trabajo, que luego listaré en los reportes.

Luego,armé 2 programas en PHP, cada uno lista un tipo de entrada

AUDAF.php

<html>
<head>
<title>Journal de auditoria - Fallas de Autorizacion</title>
</head>
<p align="center"><b>Journal de auditoria - Fallas de Autorizacion</b></p>
<p>

<i><b>
<?php
include 'Connection.php';

$date = new DateTime();
$cdate = $date->format('Y-m-d');
$fdd = $date;
$fht = $date;
$cdd = $cdate . ' 00:00:00';
$cht = $cdate . ' 23:59:59';
if (!empty($_POST)){
    $fdesde=$_POST['fdesde'];
    $fhasta=$_POST['fhasta'];
} else {
    $fdesde=$cdate;
    $fhasta=$cdate;
}
echo "<form name='form1'' method='post'' action='audaf.php'>";
echo "<td>";
echo "<table width='100%'' border='0'' cellpadding='3'' cellspacing='1'' bgcolor='#FFFFFF'>";
echo "<tr>";
echo "<td colspan='3'><strong>Parametros del reporte</strong></td>";
echo "</tr>";
echo "<tr>";
echo "<td width='78'>Desde</td>";
echo "<td width='6'>:</td>";
echo "<td width='294'><input name='fdesde' type='text' id='fdesde' value='$fdesde'</td> </tr>";
echo "<tr> <td>Hasta</td><td>:</td>";
echo "<td><input name='fhasta'' type='text' id='fhasta' value='$fhasta' </td></tr>";
echo "<tr>";
echo "<td>&nbsp;</td>";
echo "<td>&nbsp;</td>";
echo "<td><input type='submit'' name='Submit'' value='Aceptar'></td>";
echo "</tr>";
echo "</table>";
echo "</td>";
echo "</form>";

if (!empty($_POST)){
$fdesde=$_POST['fdesde'];
$fhasta=$_POST['fhasta'];
$cdd = $fdesde . ' 00:00:00';
$cht = $fhasta . ' 23:59:59';
}

#Consulta  de registros PW
$sqlaf = "SELECT date(a.AFTSTP) as Fecha, Time(a.AFTSTP) as Hora,a.AFUSER as Usuario, a.AFJOB as Trabajo,a.AFNBR as Nro_Trabajo,a.AFPGM as Programa, a.AFPGMLIB as Biblioteca,trim(a.AFRADR) as Direccion_IP, a.AFVIOL as Tipo, b.AFVIOLDS as Descripcion
        From MYLIB.QAUDITAF a left outer join MYLIB.AUDAFTYPE b
        on a.AFVIOL = b.AFVIOL
        where a.AFTSTP >= '$cdd' and a.AFTSTP <=  '$cht'
        order by a.AFTSTP" ;

#echo $sqlaf;
$result=odbc_exec($conn,$sqlaf);


echo '<table border=1 cellspacing=0 cellpadding=2 ><tr>';
    $fila = 1;
     while (odbc_fetch_row($result)) {
         $FieldQ = odbc_num_fields($result);

         if ($fila==1) {
             for ($i = 1; $i <= $FieldQ ; $i++)
             {
             $fn = odbc_field_name($result,$i);
             echo "<th bgcolor=#AFAFAF>$fn</th>";
             }
             echo "</tr>";
         }
         $fila++;
        echo "<tr>";
         $td = "<td bgcolor=#DCEBF9>";
         if (($fila/2)==intval($fila/2)) {
             $td = "<td bgcolor=#FFFFFF>";
         }

         for ($i = 1; $i <= $FieldQ ; $i++)
         {
         $fn = odbc_field_name($result,$i);
         $Campo = odbc_result($result,$fn);
         echo $td . $Campo . "</td>";
         }
         echo "</tr>";

    }
    echo "</table>";

$clo = odbc_close($conn);
?></b></i>

//-------------------------------------------------------------//


Luego tengo otro programa que lista las entradas de fallas de usuario y password

AUDPW.php

<html>
<head>
<title>Journal de auditoria - Fallas de Password</title>
</head>
<p align="center"><b>Journal de auditoria - Fallas de Password</b></p>
<p>

<i><b>
<?php
include 'Connection.php';

$date = new DateTime();
$cdate = $date->format('Y-m-d');
$fdd = $date;
$fht = $date;
$cdd = $cdate . ' 00:00:00';
$cht = $cdate . ' 23:59:59';
if (!empty($_POST)){
    $fdesde=$_POST['fdesde'];
    $fhasta=$_POST['fhasta'];
} else {
    $fdesde=$cdate;
    $fhasta=$cdate;
}
echo "<form name='form1'' method='post'' action='audpw.php'>";
echo "<td>";
echo "<table width='100%'' border='0'' cellpadding='3'' cellspacing='1'' bgcolor='#FFFFFF'>";
echo "<tr>";
echo "<td colspan='3'><strong>Parametros del reporte</strong></td>";
echo "</tr>";
echo "<tr>";
echo "<td width='78'>Desde</td>";
echo "<td width='6'>:</td>";
echo "<td width='294'><input name='fdesde' type='text' id='fdesde' value='$fdesde'</td> </tr>";
echo "<tr> <td>Hasta</td><td>:</td>";
echo "<td><input name='fhasta'' type='text' id='fhasta' value='$fhasta' </td></tr>";
echo "<tr>";
echo "<td>&nbsp;</td>";
echo "<td>&nbsp;</td>";
echo "<td><input type='submit'' name='Submit'' value='Aceptar'></td>";
echo "</tr>";
echo "</table>";
echo "</td>";
echo "</form>";

if (!empty($_POST)){
$fdesde=$_POST['fdesde'];
$fhasta=$_POST['fhasta'];
$cdd = $fdesde . ' 00:00:00';
$cht = $fhasta . ' 23:59:59';
##$fdd = strtotime($cdd);
##$fht = strtotime($cht);
}


#Consulta  de registros PW
$sqlpw = "SELECT date(a.PWTSTP) as Fecha, time(a.PWTSTP) as Hora,a.PWUSRN as Usuario, a.PWJOB as Trabajo,a.PWNBR as Nro_Trabajo, a.PWPGM as Programa, a.PWPGMLIB as Biblioteca,trim(a.PWRADR) as Direccion_IP, a.PWTYPE as Tipo_de_Intento, b.PWTYPEDS as Detalle_del_Intento
        from MYLIB.QAUDITPW a left  join MYLIB.AUDPWTYPE b
        on a.PWTYPE = b.PWTYPE
        where a.PWTSTP >= '$cdd' and a.PWTSTP <= '$cht'
        order by a.PWTSTP" ;

##echo $sqlpw;
$result=odbc_exec($conn,$sqlpw);


echo '<table border=1 cellspacing=0 cellpadding=2 ><tr>';
    $fila = 1;
     while (odbc_fetch_row($result)) {
         $FieldQ = odbc_num_fields($result);

         if ($fila==1) {
             for ($i = 1; $i <= $FieldQ ; $i++)
             {
             $fn = odbc_field_name($result,$i);
             echo "<th bgcolor=#AFAFAF>$fn</th>";
             }
             echo "</tr>";
         }
         $fila++;
        echo "<tr>";
         $td = "<td bgcolor=#DCEBF9>";
         if (($fila/2)==intval($fila/2)) {
             $td = "<td bgcolor=#FFFFFF>";
         }

         for ($i = 1; $i <= $FieldQ ; $i++)
         {
         $fn = odbc_field_name($result,$i);
         $Campo = odbc_result($result,$fn);
         echo $td . $Campo . "</td>";
         }
         echo "</tr>";

    }
    echo "</table>";

$clo = odbc_close($conn);
?></b></i>

//---------------------------------------//



El programa Connection.php es común en ambos reportes




<?php
$user="usuario"; #a valid username that will connect to the DB
$pass="password"; #a password for the username
$dsn = "Driver={Client Access ODBC Driver (32-bit)};System=IP_SERVIDOR;BLOCKSIZE=256;BLOCKFETCH=0;
        DateFormat=6;DSP=0;COMPRESSION=1;PREFETCH=1;TRANSLATE=1;ExtendedDynamic=1;";
#Connect to the Database with ODBC
# $conn is defined and loaded using the odbc_connect PHP directive.
$conn=odbc_connect($dsn,$user,$pass);

#Check Connection
if ($conn == false) {
echo "<br>";
echo "Not able to connect to database<br>";
echo "<br>";
}
?>


//---------------------------------------//

Hay que preparar un par de tablas con descripciones, para que los reportes tengan algo de sentido

MYLIB.AUDPWTYPE

PWTYPE  PWTYPEDS                                                              
  A     APPC bind failure                                                     
  C     User authentication with the CHKPWD command failed                    
  D     Service tools user ID name not valid                                  
  E     Service tools user ID password not valid                              
  P     Password not valid                                                    
  Q     Attempted signon (user authentication) failed because user profile is d
  R     Attempted signon failed because password was expired. This audit record
  S     SQL Decryption password is not valid                                  
  U     User name not valid                                                   
  X     Service tools user ID is disabled                                     
  Y     Service tools user ID not valid                                       
  Z     Service tools user ID password not valid
                              
 


MYLIB.AUDAFTYPE

AFVIOL  AFVIOLDS                                                             
  A     Not authorized to object                                             
  B     Restricted instruction                                               
  C     Validation failure (see J5 offset 639)                               
  D     Validation failure (see J5 offset 639)                               
  E     Hardware storage protection error, program constant space violation  
  S     Default sign-on attempt                                              
  T     Not authorized to TCP/IP port                                        
  F     ICAPI authorization error                                            
  G     ICAPI authentication error                                           
  H     Scan exit program action (see J5 offset 639)                         
  I     System Java  inheritance not allowed                                 
  J     Submit job profile error                                             
  K     Special authority violation                                          
  N     Profile token not a regenerable token                                
  O     Optical Object Authority Failure                                     
  P     Profile swap error                                                   
  R     Hardware protection error                                             
  U     User permission request not valid                                     
  V     Profile token not valid for generating new profile token              
  W     Profile token not valid for swap                                      
  X     System violation                                                      
  Y     Not authorized to the current JUID field during a clear JUID operation
  Z     Not authorized to the current JUID field during a set JUID operation. 
 


Esto se probó corriendo en Windows con WAMPSERVER y System i Access V6R1 sin problema alguno.

Cómo conectarme a un servidor remoto en una red protegida - Versión actualizada

En un artículo anterior describí cómo conectarse a un equipo remoto en una red protegida http://diego-k.blogspot.mx/2014/12/como-conectarme...