new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / syscheckd / run_check.c
old mode 100755 (executable)
new mode 100644 (file)
index 8288e48..1bf45c6
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/syscheckd/run_check.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2010 Trend Micro Inc.
  * All right reserved.
  *
  * Foundation
  */
 
-
 /* SCHED_BATCH is Linux specific and is only picked up with _GNU_SOURCE */
 #ifdef __linux__
-       #define _GNU_SOURCE
-       #include <sched.h>
+#define _GNU_SOURCE
+#include <sched.h>
+#endif
+#ifdef WIN32
+#include <winsock2.h>
+#include <aclapi.h>
+#include <sddl.h>
 #endif
 
 #include "shared.h"
 #include "os_crypto/md5/md5_op.h"
 #include "os_crypto/sha1/sha1_op.h"
 #include "os_crypto/md5_sha1/md5_sha1_op.h"
-
 #include "rootcheck/rootcheck.h"
 
-
-/** Prototypes **/
-int c_read_file(char *file_name, char *oldsum, char *newsum);
+/* Prototypes */
+static void send_sk_db(void);
 
 
-/* Send syscheck message.
- * Send a message related to syscheck change/addition.
- */
-int send_syscheck_msg(char *msg)
+/* Send a message related to syscheck change/addition */
+int send_syscheck_msg(const char *msg)
 {
-    if(SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0)
-    {
+    if (SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0) {
         merror(QUEUE_SEND, ARGV0);
 
-        if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
-        {
+        if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
             ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
         }
 
-        /* If we reach here, we can try to send it again */
+        /* Try to send it again */
         SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ);
     }
-
-    return(0);
+    return (0);
 }
 
-
-
-/* Send rootcheck message.
- * Send a message related to rootcheck change/addition.
- */
-int send_rootcheck_msg(char *msg)
+/* Send a message related to rootcheck change/addition */
+int send_rootcheck_msg(const char *msg)
 {
-    if(SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0)
-    {
+    if (SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) {
         merror(QUEUE_SEND, ARGV0);
 
-        if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
-        {
+        if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
             ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
         }
 
-        /* If we reach here, we can try to send it again */
+        /* Try to send it again */
         SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ);
     }
-
-    return(0);
+    return (0);
 }
 
-
-/* Sends syscheck db to the server.
- */
-void send_sk_db()
+/* Send syscheck db to the server */
+static void send_sk_db()
 {
-    /* Sending scan start message */
-    if(syscheck.dir[0])
-    {
+    /* Send scan start message */
+    if (syscheck.dir[0]) {
         merror("%s: INFO: Starting syscheck scan (forwarding database).", ARGV0);
         send_rootcheck_msg("Starting syscheck scan.");
-    }
-    else
-    {
-        sleep(syscheck.tsleep +10);
+    } else {
         return;
     }
 
-    create_db(1);
-
+    create_db();
 
-    /* Sending scan ending message */
-    sleep(syscheck.tsleep +10);
+    /* Send scan ending message */
+    sleep(syscheck.tsleep + 10);
 
-    if(syscheck.dir[0])
-    {
+    if (syscheck.dir[0]) {
         merror("%s: INFO: Ending syscheck scan (forwarding database).", ARGV0);
         send_rootcheck_msg("Ending syscheck scan.");
     }
 }
 
-
-
-/* start_daemon
- * Run periodicaly the integrity checking
- */
+/* Periodically run the integrity checker */
 void start_daemon()
 {
     int day_scanned = 0;
     int curr_day = 0;
-
     time_t curr_time = 0;
-
     time_t prev_time_rk = 0;
     time_t prev_time_sk = 0;
-
     char curr_hour[12];
-
     struct tm *p;
 
-
-    /* To be used by select. */
-    #ifdef USEINOTIFY
+#ifdef INOTIFY_ENABLED
+    /* To be used by select */
     struct timeval selecttime;
     fd_set rfds;
-    #endif
-
+#endif
 
-    /*
-     * SCHED_BATCH forces the kernel to assume this is a cpu intensive
-     * process
-     * and gives it a lower priority. This keeps ossec-syscheckd
-     * from reducing
-     * the interactity of an ssh session when checksumming large files.
-     * This is available in kernel flavors >= 2.6.16
+    /* SCHED_BATCH forces the kernel to assume this is a cpu intensive
+     * process and gives it a lower priority. This keeps ossec-syscheckd
+     * from reducing the interactivity of an ssh session when checksumming
+     * large files. This is available in kernel flavors >= 2.6.16.
      */
-    #ifdef SCHED_BATCH
+#ifdef SCHED_BATCH
     struct sched_param pri;
     int status;
 
@@ -147,395 +113,294 @@ void start_daemon()
     status = sched_setscheduler(0, SCHED_BATCH, &pri);
 
     debug1("%s: Setting SCHED_BATCH returned: %d", ARGV0, status);
-    #endif
-
-
-    #ifdef DEBUG
-    verbose("%s: Starting daemon ..",ARGV0);
-    #endif
-
+#endif
 
+#ifdef DEBUG
+    verbose("%s: Starting daemon ..", ARGV0);
+#endif
 
     /* Some time to settle */
     memset(curr_hour, '\0', 12);
     sleep(syscheck.tsleep * 10);
 
-
-
     /* If the scan time/day is set, reset the
      * syscheck.time/rootcheck.time
      */
-    if(syscheck.scan_time || syscheck.scan_day)
-    {
-        /* At least once a week. */
+    if (syscheck.scan_time || syscheck.scan_day) {
+        /* At least once a week */
         syscheck.time = 604800;
         rootcheck.time = 604800;
     }
 
-
     /* Will create the db to store syscheck data */
-    if(syscheck.scan_on_start)
-    {
+    if (syscheck.scan_on_start) {
         sleep(syscheck.tsleep * 15);
         send_sk_db();
-    }
-    else
-    {
-        prev_time_rk = time(0);
-    }
 
+#ifdef WIN32
+        /* Check for registry changes on Windows */
+        os_winreg_check();
+#endif
+        /* Send database completed message */
+        send_syscheck_msg(HC_SK_DB_COMPLETED);
+        debug2("%s: DEBUG: Sending database completed message.", ARGV0);
 
+    } else {
+        prev_time_rk = time(0);
+    }
 
     /* Before entering in daemon mode itself */
     prev_time_sk = time(0);
     sleep(syscheck.tsleep * 10);
 
-
     /* If the scan_time or scan_day is set, we need to handle the
      * current day/time on the loop.
      */
-    if(syscheck.scan_time || syscheck.scan_day)
-    {
+    if (syscheck.scan_time || syscheck.scan_day) {
         curr_time = time(0);
         p = localtime(&curr_time);
 
-
         /* Assign hour/min/sec values */
         snprintf(curr_hour, 9, "%02d:%02d:%02d",
-                p->tm_hour,
-                p->tm_min,
-                p->tm_sec);
-
+                 p->tm_hour,
+                 p->tm_min,
+                 p->tm_sec);
 
         curr_day = p->tm_mday;
 
-
-
-        if(syscheck.scan_time && syscheck.scan_day)
-        {
-            if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
-               (OS_IsonDay(p->tm_wday, syscheck.scan_day)))
-            {
+        if (syscheck.scan_time && syscheck.scan_day) {
+            if ((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
+                    (OS_IsonDay(p->tm_wday, syscheck.scan_day))) {
                 day_scanned = 1;
             }
-        }
-
-        else if(syscheck.scan_time)
-        {
-            if(OS_IsAfterTime(curr_hour, syscheck.scan_time))
-            {
+        } else if (syscheck.scan_time) {
+            if (OS_IsAfterTime(curr_hour, syscheck.scan_time)) {
                 day_scanned = 1;
             }
-        }
-        else if(syscheck.scan_day)
-        {
-            if(OS_IsonDay(p->tm_wday, syscheck.scan_day))
-            {
+        } else if (syscheck.scan_day) {
+            if (OS_IsonDay(p->tm_wday, syscheck.scan_day)) {
                 day_scanned = 1;
             }
         }
     }
 
-
-    /* Checking every SYSCHECK_WAIT */
-    while(1)
-    {
+    /* Check every SYSCHECK_WAIT */
+    while (1) {
         int run_now = 0;
         curr_time = time(0);
 
-
-        /* Checking if syscheck should be restarted, */
+        /* Check if syscheck should be restarted */
         run_now = os_check_restart_syscheck();
 
-
-        /* Checking if a day_time or scan_time is set. */
-        if(syscheck.scan_time || syscheck.scan_day)
-        {
+        /* Check if a day_time or scan_time is set */
+        if (syscheck.scan_time || syscheck.scan_day) {
             p = localtime(&curr_time);
 
-
-            /* Day changed. */
-            if(curr_day != p->tm_mday)
-            {
+            /* Day changed */
+            if (curr_day != p->tm_mday) {
                 day_scanned = 0;
                 curr_day = p->tm_mday;
             }
 
-
-            /* Checking for the time of the scan. */
-            if(!day_scanned && syscheck.scan_time && syscheck.scan_day)
-            {
+            /* Check for the time of the scan */
+            if (!day_scanned && syscheck.scan_time && syscheck.scan_day) {
                 /* Assign hour/min/sec values */
                 snprintf(curr_hour, 9, "%02d:%02d:%02d",
-                                    p->tm_hour, p->tm_min, p->tm_sec);
+                         p->tm_hour, p->tm_min, p->tm_sec);
 
-                if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
-                   (OS_IsonDay(p->tm_wday, syscheck.scan_day)))
-                {
+                if ((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
+                        (OS_IsonDay(p->tm_wday, syscheck.scan_day))) {
                     day_scanned = 1;
                     run_now = 1;
                 }
-            }
-
-            else if(!day_scanned && syscheck.scan_time)
-            {
+            } else if (!day_scanned && syscheck.scan_time) {
                 /* Assign hour/min/sec values */
                 snprintf(curr_hour, 9, "%02d:%02d:%02d",
-                                    p->tm_hour, p->tm_min, p->tm_sec);
+                         p->tm_hour, p->tm_min, p->tm_sec);
 
-                if(OS_IsAfterTime(curr_hour, syscheck.scan_time))
-                {
+                if (OS_IsAfterTime(curr_hour, syscheck.scan_time)) {
                     run_now = 1;
                     day_scanned = 1;
                 }
-            }
-
-            /* Checking for the day of the scan. */
-            else if(!day_scanned && syscheck.scan_day)
-            {
-                if(OS_IsonDay(p->tm_wday, syscheck.scan_day))
-                {
+            } else if (!day_scanned && syscheck.scan_day) {
+                /* Check for the day of the scan */
+                if (OS_IsonDay(p->tm_wday, syscheck.scan_day)) {
                     run_now = 1;
                     day_scanned = 1;
                 }
             }
         }
 
-
-
-        /* If time elapsed is higher than the rootcheck_time,
-         * run it.
-         */
-        if(syscheck.rootcheck)
-        {
-            if(((curr_time - prev_time_rk) > rootcheck.time) || run_now)
-            {
+        /* If time elapsed is higher than the rootcheck_time, run it */
+        if (syscheck.rootcheck) {
+            if (((curr_time - prev_time_rk) > rootcheck.time) || run_now) {
                 run_rk_check();
                 prev_time_rk = time(0);
             }
         }
 
-
-        /* If time elapsed is higher than the syscheck time,
-         * run syscheck time.
-         */
-        if(((curr_time - prev_time_sk) > syscheck.time) || run_now)
-        {
-            /* We need to create the db, if scan on start is not set. */
-            if(syscheck.scan_on_start == 0)
-            {
+        /* If time elapsed is higher than the syscheck time, run syscheck time */
+        if (((curr_time - prev_time_sk) > syscheck.time) || run_now) {
+            if (syscheck.scan_on_start == 0) {
+                /* Need to create the db if scan on start is not set */
                 sleep(syscheck.tsleep * 10);
                 send_sk_db();
                 sleep(syscheck.tsleep * 10);
 
                 syscheck.scan_on_start = 1;
-            }
-
-
-            else
-            {
-                /* Sending scan start message */
-                if(syscheck.dir[0])
-                {
+            } else {
+                /* Send scan start message */
+                if (syscheck.dir[0]) {
                     merror("%s: INFO: Starting syscheck scan.", ARGV0);
                     send_rootcheck_msg("Starting syscheck scan.");
                 }
-
-
-                #ifdef WIN32
-                /* Checking for registry changes on Windows */
+#ifdef WIN32
+                /* Check for registry changes on Windows */
                 os_winreg_check();
-                #endif
-
-
-                /* Checking for changes */
+#endif
+                /* Check for changes */
                 run_dbcheck();
             }
 
-
-            /* Sending scan ending message */
+            /* Send scan ending message */
             sleep(syscheck.tsleep + 20);
-            if(syscheck.dir[0])
-            {
+            if (syscheck.dir[0]) {
                 merror("%s: INFO: Ending syscheck scan.", ARGV0);
                 send_rootcheck_msg("Ending syscheck scan.");
             }
 
-
-
-            /* Sending database completed message */
+            /* Send database completed message */
             send_syscheck_msg(HC_SK_DB_COMPLETED);
             debug2("%s: DEBUG: Sending database completed message.", ARGV0);
 
-
             prev_time_sk = time(0);
         }
 
-
-        #ifdef USEINOTIFY
-        if(syscheck.realtime && (syscheck.realtime->fd >= 0))
-        {
+#ifdef INOTIFY_ENABLED
+        if (syscheck.realtime && (syscheck.realtime->fd >= 0)) {
             selecttime.tv_sec = SYSCHECK_WAIT;
             selecttime.tv_usec = 0;
 
             /* zero-out the fd_set */
             FD_ZERO (&rfds);
-
             FD_SET(syscheck.realtime->fd, &rfds);
 
             run_now = select(syscheck.realtime->fd + 1, &rfds,
                              NULL, NULL, &selecttime);
-            if(run_now < 0)
-            {
+            if (run_now < 0) {
                 merror("%s: ERROR: Select failed (for realtime fim).", ARGV0);
                 sleep(SYSCHECK_WAIT);
-            }
-            else if(run_now == 0)
-            {
-                /* Timeout. */
-            }
-            else if (FD_ISSET (syscheck.realtime->fd, &rfds))
-            {
+            } else if (run_now == 0) {
+                /* Timeout */
+            } else if (FD_ISSET (syscheck.realtime->fd, &rfds)) {
                 realtime_process();
             }
-        }
-        else
-        {
+        } else {
             sleep(SYSCHECK_WAIT);
         }
-
-        #elif WIN32
-        if(syscheck.realtime && (syscheck.realtime->fd >= 0))
-        {
-            run_now = WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE);
-            if(run_now == WAIT_FAILED)
-            {
+#elif defined(WIN32)
+        if (syscheck.realtime && (syscheck.realtime->fd >= 0)) {
+            if (WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE) == WAIT_FAILED) {
                 merror("%s: ERROR: WaitForSingleObjectEx failed (for realtime fim).", ARGV0);
                 sleep(SYSCHECK_WAIT);
-            }
-            else
-            {
+            } else {
                 sleep(1);
             }
-        }
-        else
-        {
+        } else {
             sleep(SYSCHECK_WAIT);
         }
-
-
-        #else
+#else
         sleep(SYSCHECK_WAIT);
-        #endif
+#endif
     }
 }
 
-
-
-
-/* c_read_file
- * Read file information and return a pointer
- * to the checksum
- */
-int c_read_file(char *file_name, char *oldsum, char *newsum)
+/* Read file information and return a pointer to the checksum */
+int c_read_file(const char *file_name, const char *oldsum, char *newsum)
 {
     int size = 0, perm = 0, owner = 0, group = 0, md5sum = 0, sha1sum = 0;
-
+    int return_error = 0;
     struct stat statbuf;
-
     os_md5 mf_sum;
     os_sha1 sf_sum;
 
-
-    /* Cleaning sums */
+    /* Clean sums */
     strncpy(mf_sum, "xxx", 4);
     strncpy(sf_sum, "xxx", 4);
 
-
-
-    /* Stating the file */
-    #ifdef WIN32
-    if(stat(file_name, &statbuf) < 0)
-    #else
-    if(lstat(file_name, &statbuf) < 0)
-    #endif
+    /* Stat the file */
+#ifdef WIN32
+    return_error = (stat(file_name, &statbuf) < 0);
+#else
+    return_error = (lstat(file_name, &statbuf) < 0);
+#endif
+    if (return_error)
     {
-        char alert_msg[912 +2];
+        char alert_msg[PATH_MAX+4];
 
-        alert_msg[912 +1] = '\0';
-        snprintf(alert_msg, 912,"-1 %s", file_name);
+        alert_msg[PATH_MAX + 3] = '\0';
+        snprintf(alert_msg, PATH_MAX + 4, "-1 %s", file_name);
         send_syscheck_msg(alert_msg);
 
-        return(-1);
+        return (-1);
     }
 
-    /* Getting the old sum values */
+    /* Get the old sum values */
 
     /* size */
-    if(oldsum[0] == '+')
+    if (oldsum[0] == '+') {
         size = 1;
+    }
 
     /* perm */
-    if(oldsum[1] == '+')
+    if (oldsum[1] == '+') {
         perm = 1;
+    }
 
     /* owner */
-    if(oldsum[2] == '+')
+    if (oldsum[2] == '+') {
         owner = 1;
+    }
 
     /* group */
-    if(oldsum[3] == '+')
+    if (oldsum[3] == '+') {
         group = 1;
+    }
 
     /* md5 sum */
-    if(oldsum[4] == '+')
+    if (oldsum[4] == '+') {
         md5sum = 1;
+    }
 
     /* sha1 sum */
-    if(oldsum[5] == '+')
+    if (oldsum[5] == '+') {
         sha1sum = 1;
-
-    else if(oldsum[5] == 's')
-    {
+    } else if (oldsum[5] == 's') {
         sha1sum = 1;
-    }
-    else if(oldsum[5] == 'n')
-    {
+    } else if (oldsum[5] == 'n') {
         sha1sum = 0;
     }
 
-
-    /* Generating new checksum */
-    #ifdef WIN32
-    if(S_ISREG(statbuf.st_mode))
-    #else
-    if(S_ISREG(statbuf.st_mode))
-    #endif
+    /* Generate new checksum */
+    if (S_ISREG(statbuf.st_mode))
     {
-        if(sha1sum || md5sum)
-        {
-            /* Generating checksums of the file. */
-            if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
-            {
+        if (sha1sum || md5sum) {
+            /* Generate checksums of the file */
+            if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) {
                 strncpy(sf_sum, "xxx", 4);
                 strncpy(mf_sum, "xxx", 4);
             }
         }
     }
-    #ifndef WIN32
-    /* If it is a link, we need to check if the actual file is valid. */
-    else if(S_ISLNK(statbuf.st_mode))
-    {
+#ifndef WIN32
+    /* If it is a link, check if the actual file is valid */
+    else if (S_ISLNK(statbuf.st_mode)) {
         struct stat statbuf_lnk;
-        if(stat(file_name, &statbuf_lnk) == 0)
-        {
-            if(S_ISREG(statbuf_lnk.st_mode))
-            {
-                if(sha1sum || md5sum)
-                {
-                    /* Generating checksums of the file. */
-                    if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
-                    {
+        if (stat(file_name, &statbuf_lnk) == 0) {
+            if (S_ISREG(statbuf_lnk.st_mode)) {
+                if (sha1sum || md5sum) {
+                    /* Generate checksums of the file */
+                    if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) {
                         strncpy(sf_sum, "xxx", 4);
                         strncpy(mf_sum, "xxx", 4);
                     }
@@ -543,20 +408,62 @@ int c_read_file(char *file_name, char *oldsum, char *newsum)
             }
         }
     }
-    #endif
+#endif
 
     newsum[0] = '\0';
     newsum[255] = '\0';
-    /* chris: changed st_size int to long */
-    snprintf(newsum,255,"%ld:%d:%d:%d:%s:%s",
-            size == 0?0:(long)statbuf.st_size,
-            perm == 0?0:(int)statbuf.st_mode,
-            owner== 0?0:(int)statbuf.st_uid,
-            group== 0?0:(int)statbuf.st_gid,
-            md5sum   == 0?"xxx":mf_sum,
-            sha1sum  == 0?"xxx":sf_sum);
-
-    return(0);
-}
+#ifndef WIN32
+    snprintf(newsum, 255, "%ld:%d:%d:%d:%s:%s",
+             size == 0 ? 0 : (long)statbuf.st_size,
+             perm == 0 ? 0 : (int)statbuf.st_mode,
+             owner == 0 ? 0 : (int)statbuf.st_uid,
+             group == 0 ? 0 : (int)statbuf.st_gid,
+             md5sum   == 0 ? "xxx" : mf_sum,
+             sha1sum  == 0 ? "xxx" : sf_sum);
+#else
+    HANDLE hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hFile == INVALID_HANDLE_VALUE) {
+        DWORD dwErrorCode = GetLastError();
+        char alert_msg[PATH_MAX+4];
+        alert_msg[PATH_MAX + 3] = '\0';
+        snprintf(alert_msg, PATH_MAX + 4, "CreateFile=%ld %s", dwErrorCode, file_name);
+        send_syscheck_msg(alert_msg);
+        return -1;
+    }
 
-/* EOF */
+    PSID pSidOwner = NULL;
+    PSECURITY_DESCRIPTOR pSD = NULL;
+    DWORD dwRtnCode = GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD);
+    if (dwRtnCode != ERROR_SUCCESS) {
+        DWORD dwErrorCode = GetLastError();
+        CloseHandle(hFile);
+        char alert_msg[PATH_MAX+4];
+        alert_msg[PATH_MAX + 3] = '\0';
+        snprintf(alert_msg, PATH_MAX + 4, "GetSecurityInfo=%ld %s", dwErrorCode, file_name);
+        send_syscheck_msg(alert_msg);
+        return -1;
+    }
+
+    LPSTR szSID = NULL;
+    ConvertSidToStringSid(pSidOwner, &szSID);
+    char* st_uid = NULL;
+    if( szSID ) {
+      st_uid = (char *) calloc( strlen(szSID) + 1, 1 );
+      memcpy( st_uid, szSID, strlen(szSID) );
+    }
+    LocalFree(szSID);
+    CloseHandle(hFile);
+
+    snprintf(newsum, 255, "%ld:%d:%s:%d:%s:%s",
+             size == 0 ? 0 : (long)statbuf.st_size,
+             perm == 0 ? 0 : (int)statbuf.st_mode,
+             owner == 0 ? "0" : st_uid,
+             group == 0 ? 0 : (int)statbuf.st_gid,
+             md5sum   == 0 ? "xxx" : mf_sum,
+             sha1sum  == 0 ? "xxx" : sf_sum);
+
+    free(st_uid);
+#endif
+
+    return (0);
+}