setFormatter(new LineFormatter("%datetime% %level_name% %message%" . PHP_EOL, "H:i:s.u")); $log = new Logger("stig_parser"); $log->pushHandler(new StreamHandler(LOG_PATH . "/stig_parser.log", $log_level)); $log->pushHandler($stream); check_path(TMP . "/stigs"); check_path(TMP . "/stigs/zip"); check_path(TMP . "/stigs/checklist"); check_path(TMP . "/stigs/xml"); check_path(DOC_ROOT . "/reference/stigs"); $path = realpath(TMP . "/stigs"); if (isset($cmd['d']) && $cmd['d']) { $path = $cmd['d']; } chdir($path); $db = new db(); $zip_files = glob("*.zip"); $zip = new ZipArchive(); // Find the .zip files that were uploaded foreach ($zip_files as $file) { $ft = FileDetection($file); if ($ft['type'] == DISA_STIG_LIBRARY_ZIP) { $log->info("Extracting $file"); $zip->open($file); $zip->extractTo(realpath(TMP . "/stigs/checklist")); $zip->close(); if (isset($cmd['delete'])) { unlink($file); } } } // traverse the checklist directory to find all the zip files and extract those for ($x = 0; $x < 2; $x++) { $dir = new RecursiveDirectoryIterator(realpath(TMP . "/stigs/checklist")); $files = new RecursiveIteratorIterator($dir); directory_crawl($files); } // traverse the zip directory, and extract the xml, xsl, jpg, or gif files. for ($x = 0; $x < 3; $x++) { $dir = new RecursiveDirectoryIterator(realpath(TMP . "/stigs/zip")); $files = new RecursiveIteratorIterator($dir); directory_crawl($files); } if (isset($cmd['x']) || isset($cmd['extract'])) { $log->info("Extract only complete"); die; } // find all the xml files in the directory chdir(TMP . "/stigs/xml"); $xml_files = glob("*.xml"); // change back to the document root directory chdir(DOC_ROOT); $count = 0; $db->help->update("settings", ['meta_value' => 0], [ [ 'field' => 'meta_key', 'value' => 'stig-progress' ] ]); $db->help->execute(); $regex = null; if (isset($cmd['exclude'])) { $regex = $cmd['exclude']; } foreach ($xml_files as $key => $file) { // if the file has a space in the file name we need to replace it because it will cause parsing errors if (strpos($file, ' ') !== false) { $new_file = str_replace(' ', '_', $file); rename(realpath(TMP . "/stigs/xml/$file"), TMP . "/stigs/xml/$new_file"); $xml_files[$key] = $file = $new_file; copy(realpath(TMP . "/stigs/xml/$file"), realpath(DOC_ROOT . "/reference/stigs") . "/$file"); } if (!is_null($regex) && preg_match("/$regex/i", $file)) { unlink($file); $log->debug("Skipping $file due to matching regex"); continue; } elseif(!empty(STIG_EXCLUSIONS) && preg_match("/" . STIG_EXCLUSIONS . "/i", $file)) { unlink(TMP . "/stigs/xml/$file"); $log->debug("Skipping $file due to matching STIG exclusion"); continue; } // determine the file type $ft = FileDetection(TMP . "/stigs/xml/$file"); // add the file to the stack if it is of the proper type // can add additional types as the parser are created if ($ft['type'] == DISA_STIG_XML) { $log->info("Parsing STIG file: $file"); $script = realpath(defined('PHP_BIN') ? PHP_BIN : PHP) . " -c " . realpath(PHP_CONF) . " -f " . realpath(DOC_ROOT . "/exec/parse_stig.php") . " --" . " -f=\"" . realpath(TMP . "/stigs/xml/{$file}") . "\"" . (isset($cmd['debug']) ? " --debug" : ""); $db->add_Catalog_Script(basename($file)); passthru($script); } else { $log->debug("Skipping $file"); continue; } $count++; $db->help->update("settings", ['meta_value' => number_format(($count / count($xml_files) * 100), 2)], [ [ 'field' => 'meta_key', 'op' => '=', 'value' => 'stig-progress' ] ]); $db->help->execute(); } $db->help->update("catalog_scripts", ['status' => 'COMPLETE'], [ [ 'field' => 'perc_comp', 'op' => '=', 'value' => 100 ], [ 'field' => 'status', 'op' => '=', 'value' => 'RUNNING', 'sql_op' => 'AND' ] ]); $db->help->execute(); $db->help->update("settings", ['meta_value' => 100], [ [ 'field' => 'meta_key', 'op' => IN, 'value' => ['stig-dl-progress', 'stig-progress'] ] ]); $db->help->execute(); if (isset($cmd['delete'])) { if (strtolower(substr(PHP_OS, 0, 3)) == 'win') { exec("del /S /Q /F " . realpath(TMP . "/stigs/checklist") . "\\*"); exec("del /S /Q /F " . realpath(TMP . "/stigs/zip") . "\\*"); } else { exec("rm -rf " . realpath(TMP . "/stigs/checklist") . "/*"); exec("rm -rf " . realpath(TMP . "/stigs/zip") . "/*"); } } /** * Function to crawl directory structure to find zip, xml, xsl, gif, and jpg files * * @param RecursiveIteratorIterator $files */ function directory_crawl($files) { global $zip, $log; foreach ($files as $file) { if (preg_match('/\.zip/', $file)) { if ($zip->open($file) === true) { for ($i = 0; $i < $zip->numFiles; $i++) { $contents = ''; $in_Skips = false; $path = ''; $filename = str_replace('\\', '/', $zip->getNameIndex($i)); $fileinfo = pathinfo($filename); if (isset($fileinfo['extension']) && !$in_Skips) { switch (strtolower($fileinfo['extension'])) { case 'zip': $path = TMP . "/stigs/zip/"; break; case 'xml': if (!preg_match('/xccdf/i', $fileinfo['basename'])) { continue; } elseif (strpos($fileinfo['basename'], "$") !== false) { continue; } $path = TMP . "/stigs/xml/"; break; case 'xsl': case 'gif': case 'jpg': $path = DOC_ROOT . "/reference/stigs/"; break; } if ($path) { $fp = $zip->getStream($filename); if (!$fp) { error_log("Couldn't get zip file stream for file $filename in $file"); } else { while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); if (file_put_contents($path . $fileinfo['basename'], $contents) === false) { die; } } } } } $zip->close(); } } } } function usage() { print <<