<?php
/*******************************************************************************
** Basic Analysis and Security Engine (BASE)
** Copyright (C) 2004 BASE Project Team
** Copyright (C) 2000 Carnegie Mellon University
**
** (see the file 'base_main.php' for license details)
**
** Project Lead: Kevin Johnson <kjohnson@secureideas.net>
** Built upon work by Roman Danyliw <rdd@cert.org>, <roman@danyliw.com>
**
** Purpose: Create the Database schema
********************************************************************************
** Authors:
********************************************************************************
** Kevin Johnson <kjohnson@secureideas.net
**
********************************************************************************
*/

  include("base_conf.php");
  include("$BASE_path/includes/base_constants.inc.php");
  include("$BASE_path/includes/base_include.inc.php");
  include_once("$BASE_path/base_db_common.php");
  include_once("$BASE_path/base_common.php");

  $et = new EventTiming($debug_time_mode);

  $page_title = "DB Setup";
  PrintBASESubHeader($page_title, $page_title, "Back");
?>

<FORM METHOD="POST"
      ACTION="base_db_setup.php">

<?php
  $submit = ImportHTTPVar("submit");

  /* Connect to the Alert database */
  $db = NewBASEDBConnection($DBlib_path, $DBtype);
  $db->baseDBConnect($db_connect_method,
                     $alert_dbname, $alert_host, $alert_port, $alert_user, $alert_password);

  $tblBaseAG_present = $db->baseTableExists("acid_ag");
  $tblBaseAGAlert_present = $db->baseTableExists("acid_ag_alert");
  $tblBaseIPCache_present = $db->baseTableExists("acid_ip_cache");
  $tblBaseEvent_present = $db->baseTableExists("acid_event");
  $tblBaseRoles_present = $db->baseTableExists("base_roles");
  $tblBaseUsers_present = $db->baseTableExists("base_users");
  $index_event_sig_present = $db->baseIndexExists("event", "signature");
  $index_event_time_present = $db->baseIndexExists("event", "timestamp");

  if ( $debug_mode > 0 )
  {
     echo "\$submit = $submit <BR>
           table acid_ag present? $tblBaseAG_present <BR>
           table acid_ag_alert present? $tblBaseAGAlert_present <BR>
           table acid_ip_cache present? $tblBaseIPCache_present <BR>
           table acid_event present? $tblBaseEvent_present <BR>
           table base_roles present? $tblBaseRoles_present <BR>
           table base_users present? $tblBaseUsers_present <BR>
           index event.signature present? $index_event_sig_present <BR>
           index event.time present? $index_event_time_present <BR>";
  }

  if ( $submit == "Create BASE AG" )
  {
     if ( !$tblBaseAG_present )
     {
        if ( ($db->DB_type == "mysql") || ($db->DB_type == "mysqlt") || ($db->DB_type == "maxsql") )
        {         
         $sql = '
                CREATE TABLE acid_ag ( ag_id               INT           UNSIGNED NOT NULL AUTO_INCREMENT,
                                       ag_name             VARCHAR(40),
                                       ag_desc             TEXT, 
                                       ag_ctime            DATETIME,
                                       ag_ltime            DATETIME,

                                       PRIMARY KEY         (ag_id),
                                       INDEX               (ag_id))';
        }
        else if ($db->DB_type == "postgres")
        {
         $sql = '
                CREATE TABLE acid_ag ( ag_id               SERIAL NOT NULL,
                                       ag_name             TEXT,
                                       ag_desc             TEXT, 
                                       ag_ctime            TIMESTAMP,
                                       ag_ltime            TIMESTAMP,

                                       PRIMARY KEY         (ag_id))'; 
        }
        else if ($db->DB_type == "mssql") // Microsoft recommends specifying NULL if NULL is permitted
                                          // Otherwise it will unpredictably change the nullability.
        {
          $sql = '
                 CREATE TABLE acid_ag ( ag_id              NUMERIC(10,0) IDENTITY(1,1) NOT NULL,
                                        ag_name            VARCHAR(40) NULL,
                                        ag_desc            TEXT NULL,
                                        ag_ctime           DATETIME NULL,
                                        ag_ltime           DATETIME NULL,
                                        
                                        PRIMARY KEY        (ag_id))';
                                        
         }
          $db->baseExecute($sql, -1, -1, false);
          if ( $db->baseErrorMessage() != "" )
             ErrorMessage("Unable to CREATE table 'acid_ag': ".$db->baseErrorMessage());
          else
             ErrorMessage("Successfully created 'acid_ag'");

          $tblBaseAG_present = $db->baseTableExists("acid_ag");
      }

      if ( !$tblBaseAGAlert_present )
      {
          if ( ($db->DB_type == "mysql") || ($db->DB_type == "mysqlt") || ($db->DB_type == "maxsql") )
          {  
           $sql = '
                CREATE TABLE acid_ag_alert( ag_id               INT           UNSIGNED NOT NULL,
                                            ag_sid              INT           UNSIGNED NOT NULL,
                                            ag_cid              INT           UNSIGNED NOT NULL, 
                                            PRIMARY KEY         (ag_id, ag_sid, ag_cid),
                                            INDEX               (ag_id),
                                            INDEX               (ag_sid, ag_cid))';
          }
          else if ($db->DB_type == "postgres")
          {
           $sql = '
                CREATE TABLE acid_ag_alert( ag_id               INT8 NOT NULL,
                                            ag_sid              INT4 NOT NULL,
                                            ag_cid              INT8 NOT NULL, 

                                            PRIMARY KEY         (ag_id, ag_sid, ag_cid) );
                CREATE INDEX acid_ag_alert_aid_idx ON acid_ag_alert (ag_id);
                CREATE INDEX acid_ag_alert_id_idx ON acid_ag_alert (ag_sid, ag_cid);';
          }
          else if ($db->DB_type == "mssql") // Microsoft recommends specifying NULL if NULL is permitted
                                           // Otherwise it will unpredictably change the nullability.
          {
           $sql = '
                CREATE TABLE acid_ag_alert ( ag_id        NUMERIC(10,0) NOT NULL,
                                             ag_sid       NUMERIC(10,0) NOT NULL,
                                             ag_cid       NUMERIC(10,0) NOT NULL,
                                             PRIMARY KEY  (ag_id, ag_sid, ag_cid) )';
          }
          $db->baseExecute($sql, -1, -1, false);
          if ( $db->baseErrorMessage() != "" )
             ErrorMessage("Unable to CREATE table 'acid_ag_alert': ".
                          $db->baseErrorMessage());
          else
             ErrorMessage("Successfully created 'acid_ag_alert'");
 
          $tblBaseAGAlert_present = $db->baseTableExists("acid_ag_alert");
      }

      if ( !$tblBaseIPCache_present )
      {
          if ( ($db->DB_type == "mysql") || ($db->DB_type == "mysqlt") || ($db->DB_type == "maxsql") )
          {  
           $sql = '
                   CREATE TABLE acid_ip_cache( ipc_ip                  INT UNSIGNED NOT NULL,
                                               ipc_fqdn                VARCHAR(50),
                                               ipc_dns_timestamp       DATETIME,
                                               ipc_whois               TEXT,
                                               ipc_whois_timestamp     DATETIME,

                                               PRIMARY KEY         (ipc_ip),
                                               INDEX               (ipc_ip))
                  ';
          }
          else if ($db->DB_type == "postgres")
          {
           $sql = '
                   CREATE TABLE acid_ip_cache( ipc_ip                  INT8 NOT NULL,
                                               ipc_fqdn                TEXT,
                                               ipc_dns_timestamp       TIMESTAMP,
                                               ipc_whois               TEXT,
                                               ipc_whois_timestamp     TIMESTAMP,

                                               PRIMARY KEY         (ipc_ip) );
                  ';
          }
          else if ($db->DB_type == "mssql") // Microsoft recommends specifying NULL if NULL is permitted
                                            // Otherwise it will unpredictably change the nullability.
          {
           $sql = '
                   CREATE TABLE acid_ip_cache ( ipc_ip   NUMERIC(10,0) NOT NULL,
                                                ipc_fqdn  VARCHAR(50) NULL,
                                                ipc_dns_timestamp  DATETIME NULL,
                                                ipc_whois      TEXT NULL,
                                                ipc_whois_timestamp  DATETIME NULL,
                                                
                                                PRIMARY KEY     (ipc_ip) )';
          }
          $db->baseExecute($sql, -1, -1, false);
          if ( $db->baseErrorMessage() != "" )
             ErrorMessage("Unable to CREATE table 'acid_ip_cache': ".
                          $db->baseErrorMessage());
          else
             ErrorMessage("Successfully created 'acid_ip_cache'");

          $tblBaseIPCache_present = $db->baseTableExists("acid_ip_cache");
      }

      if ( !$tblBaseEvent_present )
      {
          if ( ($db->DB_type == "mysql") || ($db->DB_type == "mysqlt") || ($db->DB_type == "maxsql") )
          {  
           if ( $db->baseGetDBversion() < 100 )
              $sig_ddl = "signature      VARCHAR(255) NOT NULL,";
           else
              $sig_ddl = "signature      INT UNSIGNED NOT NULL,";

           $sql = '
                  CREATE TABLE acid_event   ( sid                 INT UNSIGNED NOT NULL,
                            cid                 INT UNSIGNED NOT NULL,'.
                            $sig_ddl.'     
                            sig_name            VARCHAR(255),
                            sig_class_id        INT UNSIGNED,
                            sig_priority        INT UNSIGNED,
                            timestamp           DATETIME NOT NULL,
                            ip_src              INT UNSIGNED,
                            ip_dst              INT UNSIGNED,
                            ip_proto            INT,
                            layer4_sport        INT UNSIGNED,
                            layer4_dport        INT UNSIGNED,

                            PRIMARY KEY         (sid,cid),
                            INDEX               (signature),
                            INDEX               (sig_name),
                            INDEX               (sig_class_id),
                            INDEX               (sig_priority),
                            INDEX               (timestamp),
                            INDEX               (ip_src),
                            INDEX               (ip_dst),
                            INDEX               (ip_proto),
                            INDEX               (layer4_sport),
                            INDEX               (layer4_dport)
                          )
                  ';
          }
          else if ($db->DB_type == "postgres")
          {
           if ( $db->baseGetDBversion() < 100 )
              $sig_ddl = "signature      TEXT NOT NULL,";
           else
              $sig_ddl = "signature      INT8 NOT NULL,";

           $sql = '
                   CREATE TABLE acid_event   ( sid                 INT8 NOT NULL,
                            cid                 INT8 NOT NULL,'.
                            $sig_ddl.'
                            sig_name            TEXT,
                            sig_class_id        INT8,
                            sig_priority        INT8,
                            timestamp           TIMESTAMP NOT NULL,
                            ip_src              INT8,
                            ip_dst              INT8,
                            ip_proto            INT4,
                            layer4_sport        INT4,
                            layer4_dport        INT4,
                            PRIMARY KEY         (sid,cid)
                          );

                   CREATE INDEX acid_event_signature ON acid_event (signature);
                   CREATE INDEX acid_event_sig_name ON acid_event (sig_name);
                   CREATE INDEX acid_event_sig_class_id ON acid_event (sig_class_id);
                   CREATE INDEX acid_event_sig_priority ON acid_event (sig_priority);
                   CREATE INDEX acid_event_timestamp ON acid_event (timestamp);
                   CREATE INDEX acid_event_ip_src ON acid_event (ip_src);
                   CREATE INDEX acid_event_ip_dst ON acid_event (ip_dst); 
                   CREATE INDEX acid_event_ip_proto ON acid_event (ip_proto);
                   CREATE INDEX acid_event_layer4_sport ON acid_event (layer4_sport);
                   CREATE INDEX acid_event_layer4_dport ON acid_event (layer4_dport);
                  ';
          }
          else if ($db->DB_type == "mssql") // Microsoft recommends specifying NULL if NULL is permitted
                                            // Otherwise it will unpredictably change the nullability.
          {
              if ( $db->baseGetDBversion() < 100 )
                $sig_ddl = "signature      TEXT NOT NULL,";
              else
                $sig_ddl = "signature      NUMERIC(10,0) NOT NULL,";

              $sql = '
                   CREATE TABLE acid_event   ( sid                 NUMERIC(10,0) NOT NULL,
                            cid                 NUMERIC(10,0) NOT NULL,'.
                            $sig_ddl.'
                            sig_name            TEXT NULL,
                            sig_class_id        NUMERIC(10,0) NULL,
                            sig_priority        NUMERIC(10,0) NULL,
                            timestamp           DATETIME NOT NULL,
                            ip_src              NUMERIC(10,0) NULL,
                            ip_dst              NUMERIC(10,0) NULL,
                            ip_proto            NUMERIC(10,0) NULL,
                            layer4_sport        NUMERIC(10,0) NULL,
                            layer4_dport        NUMERIC(10,0) NULL,
                            PRIMARY KEY         (sid,cid)
                          )

                  ';
          }
          $db->baseExecute($sql, -1, -1, false);
          if ( $db->baseErrorMessage() != "" )
             ErrorMessage("Unable to CREATE table 'acid_event': ".
                          $db->baseErrorMessage());
          else
             ErrorMessage("Successfully created 'acid_event'");

          $tblBaseEvent_present = $db->baseTableExists("acid_event");


      }
      if ($db->DB_type == "mssql")
      // Sheesh! If you create the indexes at the same time you create the
      //   tables, you get Attention and a disconnect (no error message).
      //   If you create the indexes here, it works. Go figure.
      {
        $sql = '
                   CREATE INDEX acid_ag_ag_id_idx ON acid_ag (ag_id)
                   CREATE INDEX acid_ag_alert_aid_idx ON acid_ag_alert (ag_id)
                   CREATE INDEX acid_ag_alert_id_idx ON acid_ag_alert (ag_sid, ag_cid)        
                   CREATE INDEX acid_event_sig_class_id ON acid_event (sig_class_id)
                   CREATE INDEX acid_event_sig_priority ON acid_event (sig_priority)
                   CREATE INDEX acid_event_timestamp ON acid_event (timestamp)
                   CREATE INDEX acid_event_ip_src ON acid_event (ip_src)
                   CREATE INDEX acid_event_ip_dst ON acid_event (ip_dst)
                   CREATE INDEX acid_event_ip_proto ON acid_event (ip_proto)
                   CREATE INDEX acid_event_layer4_sport ON acid_event (layer4_sport)
                   CREATE INDEX acid_event_layer4_dport ON acid_event (layer4_dport)

                ';
        $db->baseExecute($sql, -1, -1, false);
        if ($db->baseErrorMessage() != "")
          ErrorMessage("Unable to CREATE MSSQL BASE table indexes : ".$db->baseErrorMessage());
        else
          ErrorMessage("Successfully created MSSQL BASE table indexes");
      }
      
      // Added for base_roles and base_users -- Kevin
      if ( !$tblBaseRoles_present )
      {
          if ( ($db->DB_type == "mysql") || ($db->DB_type == "mysqlt") || ($db->DB_type == "maxsql") )
          {  
           $sql = '
                   CREATE TABLE base_roles ( role_id           int(11)         NOT NULL,
                            role_name         varchar(20)     NOT NULL,
                            role_desc         varchar(75)     NOT NULL,
                            PRIMARY KEY         (role_id));';
          }
          else if ($db->DB_type == "postgres")
          {
           $sql = '
                   CREATE TABLE base_roles( role_id                  INT8 NOT NULL,
                                               role_name                TEXT,
                                               role_desc                TEXT,
                                               PRIMARY KEY         (role_id) );
                  ';
          }
          else if ($db->DB_type == "mssql") // Microsoft recommends specifying NULL if NULL is permitted
                                            // Otherwise it will unpredictably change the nullability.
          {
           $sql = '
                   CREATE TABLE base_roles ( role_id   NUMERIC(10,0) NOT NULL,
                                                role_name  VARCHAR(20) NULL,
                                                role_desc  VARCHAR(75) NULL,
                                                PRIMARY KEY     (role_id) );';
          }
          $db->baseExecute($sql, -1, -1, false);
          if ( $db->baseErrorMessage() != "" )
             ErrorMessage("Unable to CREATE table 'base_roles': ".
                          $db->baseErrorMessage());
          else
             ErrorMessage("Successfully created 'base_roles'");

          $tblBaseRoles_present = $db->baseTableExists("base_roles");
      }
      
      if ( !$tblBaseUsers_present )
      {
          if ( ($db->DB_type == "mysql") || ($db->DB_type == "mysqlt") || ($db->DB_type == "maxsql") )
          {  
           $sql = 'CREATE TABLE base_users ( usr_id            int(11)         NOT NULL,
                            usr_login         varchar(25)     NOT NULL,
                            usr_pwd           varchar(32)     NOT NULL,
                            usr_name          varchar(75)     NOT NULL,
                            role_id           int(11)         NOT NULL,
                            usr_enabled       int(11)         NOT NULL,
                            PRIMARY KEY         (usr_id),
                            INDEX               (usr_login));';
          }
          else if ($db->DB_type == "postgres")
          {
           $sql = '
                   CREATE TABLE base_users ( usr_id            INT8         NOT NULL,
                            usr_login         TEXT     NOT NULL,
                            usr_pwd           TEXT     NOT NULL,
                            usr_name          TEXT     NOT NULL,
                            role_id           INT8         NOT NULL,
                            usr_enabled       INT8         NOT NULL,
                            PRIMARY KEY         (usr_id));
                            CREATE INDEX base_users_usr_login ON base_users (usr_login);
                  ';
          }
          else if ($db->DB_type == "mssql") // I did not create the usr_login index yet -- Kevin
          {
           $sql = '
                   CREATE TABLE base_users ( usr_id NUMERIC(10,0) NOT NULL,
                            usr_login         VARCHAR(25)     NOT NULL,
                            usr_pwd           VARCHAR(32)     NOT NULL,
                            usr_name          VARCHAR(75)     NOT NULL,
                            role_id           NUMERIC(10,0)         NOT NULL,
                            usr_enabled       NUMERIC(10,0)         NOT NULL,
                            PRIMARY KEY         (usr_id));
                  ';
          }
          $db->baseExecute($sql, -1, -1, false);
          if ( $db->baseErrorMessage() != "" )
             ErrorMessage("Unable to CREATE table 'base_users': ".
                          $db->baseErrorMessage());
          else
             ErrorMessage("Successfully created 'base_users'");

          $tblBaseUsers_present = $db->baseTableExists("base_users");
      }

      
      
      echo '<HR><P>';
  }

  if ( $submit == "Create Indexes" )
  {
     if ( $index_event_sig_present == 0)
        createDBIndex($db, "event", "signature", "signature_index");
     if ( $index_event_time_present == 0)
        createDBIndex($db, "event", "timestamp", "timestamp_index");

     $index_event_sig_present = $db->baseIndexExists($db, "event", "signature");
     $index_event_time_present = $db->baseIndexExists($db, "event", "timestamp");
  }

  echo '
  <TABLE WIDTH="100%">
     <TR><TD CLASS="plfieldhdr">Operation</TD>
         <TD CLASS="plfieldhdr">Description</TD>
         <TD CLASS="plfieldhdr">Status</TD>
     </TR>
     <TR><TD VALIGN=TOP><B>BASE tables</B></TD>
         <TD>Adds tables to extend the Snort DB to support the BASE functionality</TD>
         <TD VALIGN=TOP>';

  if ( $tblBaseAG_present && $tblBaseAGAlert_present && 
       $tblBaseIPCache_present && $tblBaseEvent_present
        && $tblBaseRoles_present && $tblBaseUsers_present )
     ErrorMessage("&nbsp;DONE&nbsp;");
  else
     echo '<INPUT TYPE="submit" NAME="submit" VALUE="Create BASE AG">'; 

  echo '</TD></TR>
     <TR><TD VALIGN=TOP><B>Search Indexes</B></TD>
         <TD>(Optional) Adds indexes to the Snort DB to optimize the speed of the queries</TD>
         <TD VALIGN=TOP>';

  if ( ( $index_event_sig_present == 1 ) && ( $index_event_time_present == 1 ) ) 
     ErrorMessage("&nbsp;DONE&nbsp;");
  else  if ( ( $index_event_sig_present == 0 ) || ( $index_event_time_present == 0 ) ) 
     echo '<INPUT TYPE="submit" NAME="submit" VALUE="Create Indexes">';
  else
     ErrorMessage("Unable to assess the indexes on the underlying database");

  echo '
  </TABLE>';
  
  if ( ($tblBaseAG_present) && ($tblBaseAGAlert_present) && 
       ($tblBaseIPCache_present) && ($tblBaseEvent_present)
        && ($tblBaseRoles_present) && ($tblBaseUsers_present))
     echo '<P>
           The underlying Alert DB is configured for usage with BASE.
           <P>
           <B>Additional DB permissions</B><BR>
           In order to support Alert purging (the selective ability to permanently delete
           alerts from the database) and DNS/whois lookup caching, 
           the DB user "'.$alert_user.'" must have the DELETE and UPDATE privilege
           on the database "'.$alert_dbname.'@'.$alert_host.'" 
           <P>
           Goto the <A HREF="base_main.php">Main page</A> to use the application.'; 

  $et->PrintTiming();

  echo "\n</FORM>\n";
  
  PrintBASESubFooter();
?>
