Index: trunk/src/dnmalloc.c
===================================================================
--- trunk/src/dnmalloc.c	(revision 178)
+++ trunk/src/dnmalloc.c	(revision 180)
@@ -1509,5 +1509,5 @@
 }
 void dnmalloc_fork_child(void) {
-  int rc;
+  int rc = 0;
 #ifdef __GLIBC__
   if (dnmalloc_use_mutex)
Index: trunk/src/sh_cat.c
===================================================================
--- trunk/src/sh_cat.c	(revision 178)
+++ trunk/src/sh_cat.c	(revision 180)
@@ -135,7 +135,7 @@
 #ifdef SH_USE_PORTCHECK
   { MSG_PORT_MISS,   SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceMissing] %s\"")},
-  { MSG_PORT_NEW,    SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceNew] %s\"")},
-  { MSG_PORT_RESTART,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceRestarted] %s\"")},
-  { MSG_PORT_NEWPORT,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServicePortSwitch] %s\"")},
+  { MSG_PORT_NEW,    SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceNew] %s\" path=\"%s\" userid=\"%s\"")},
+  { MSG_PORT_RESTART,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceRestarted] %s\" path=\"%s\" userid=\"%s\"")},
+  { MSG_PORT_NEWPORT,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServicePortSwitch] %s\" path=\"%s\" userid=\"%s\"")},
 #endif
 
@@ -453,7 +453,7 @@
 #ifdef SH_USE_PORTCHECK
   { MSG_PORT_MISS,   SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceMissing] %s>")},
-  { MSG_PORT_NEW,    SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceNew] %s>")},
-  { MSG_PORT_RESTART,SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceRestarted] %s>")},
-  { MSG_PORT_NEWPORT,SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServicePortSwitch] %s>")},
+  { MSG_PORT_NEW,    SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceNew] %s> path=<%s> userid=<%s>")},
+  { MSG_PORT_RESTART,SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceRestarted] %s> path=<%s> userid=<%s>")},
+  { MSG_PORT_NEWPORT,SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServicePortSwitch] %s> path=<%s> userid=<%s>")},
 #endif
 
Index: trunk/src/sh_port2proc.c
===================================================================
--- trunk/src/sh_port2proc.c	(revision 180)
+++ trunk/src/sh_port2proc.c	(revision 180)
@@ -0,0 +1,372 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 2008 Rainer Wichmann                                      */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
+#else
+#define dirent direct
+#define NAMLEN(dirent) (dirent)->d_namlen
+#ifdef HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif
+#ifdef HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif
+#ifdef HAVE_NDIR_H
+#include <ndir.h>
+#endif
+#endif
+#define NEED_ADD_DIRENT
+
+#if defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
+
+#if defined(__linux__)
+ 
+#include "samhain.h"
+#include "sh_error_min.h"
+#include "sh_utils.h"
+#include "sh_pthread.h"
+
+#define FIL__  _("sh_port2proc.c")
+
+static  size_t  sh_minpid = 0x0001;
+static  size_t  sh_maxpid = 0x8000;
+
+#ifndef HAVE_LSTAT
+#define lstat(x,y) stat(x,y)
+#endif /* HAVE_LSTAT */
+
+#if defined(S_IFLNK) && !defined(S_ISLNK)
+#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#else
+#if !defined(S_ISLNK)
+#define S_ISLNK(mode) (0)
+#endif
+#endif
+
+struct sock_store {
+  unsigned long sock;
+  size_t        pid;
+  char *        path;
+  char *        user;
+  struct sock_store * next;
+};
+
+/* /proc: 
+ *        linux:     /proc/pid/exe
+ *        freebsd:   /proc/pid/file
+ *        solaris10: /proc/pid/path/a.out
+ */
+static void get_user_and_path (struct sock_store * add)
+{
+  extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
+
+  char        path[128];
+  char *      buf;
+  struct stat sbuf;
+  int         len;
+  char *      tmp;
+
+  sl_snprintf (path, sizeof(path), "/proc/%ld/exe", (unsigned long) add->pid);
+
+  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
+    {
+      goto linkread;
+    }
+
+  sl_snprintf (path, sizeof(path), "/proc/%ld/file", (unsigned long) add->pid);
+
+  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
+    {
+      goto linkread;
+    }
+
+  sl_snprintf (path, sizeof(path), "/proc/%ld/path/a.out", (unsigned long) add->pid);
+
+  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
+    {
+      goto linkread;
+    }
+
+  return;
+
+ linkread:
+
+  buf = SH_ALLOC(PATH_MAX);
+  len = readlink(path, buf, PATH_MAX);   /* flawfinder: ignore */
+  len = (len >= PATH_MAX) ? (PATH_MAX-1) : len;
+
+  if (len > 0)
+    { 
+      buf[len] = '\0';
+      add->path = buf;
+    }
+  else
+    {
+      SH_FREE(buf);
+    }
+
+  add->user = SH_ALLOC(USER_MAX);
+  tmp  = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, add->user, USER_MAX);
+
+  if (!tmp)
+    sl_snprintf (add->user, USER_MAX, "%ld", (unsigned long) sbuf.st_uid);
+
+  return;
+}
+
+#if defined(__linux__)
+#define PROC_PID_MAX _("/proc/sys/kernel/pid_max")
+
+static int proc_max_pid (size_t * procpid)
+{
+  char * ret;
+  unsigned long  pid;
+  FILE * fd;
+  char   str[128];
+  char * ptr;
+
+  SL_ENTER(_("proc_max_pid"));
+    
+  if (0 == access(PROC_PID_MAX, R_OK)) /* flawfinder: ignore */
+    {
+      if (NULL != (fd = fopen(PROC_PID_MAX, "r")))
+        {
+          str[0] = '\0';
+          ret = fgets(str, 128, fd);
+          if (ret && *str != '\0')
+            {
+              pid = strtoul(str, &ptr, 0);
+              if (*ptr == '\0' || *ptr == '\n')
+                {
+                  fclose(fd);
+                  *procpid = (size_t) pid;
+                  SL_RETURN(0, _("proc_max_pid"));
+                }
+            }
+          fclose(fd);
+        }
+    }
+  SL_RETURN((-1), _("proc_max_pid"));
+}
+#else
+static int proc_max_pid(size_t * procpid)
+{
+  *procpid = sh_maxpid;
+  return 0;
+}
+#endif
+
+static struct sock_store * socklist = NULL;
+
+static void del_sock_all()
+{
+  struct sock_store * del = socklist;
+
+  while (del)
+    {
+      socklist = del->next;
+      if (del->path)
+	SH_FREE(del->path);
+      if (del->user)
+	SH_FREE(del->user);
+      SH_FREE(del);
+      del = socklist;
+    }
+  socklist = NULL;
+  return;
+}
+
+static void add_sock(unsigned long sock, size_t pid)
+{
+  struct sock_store * add = SH_ALLOC(sizeof(struct sock_store));
+
+  add->sock = sock;
+  add->pid  = pid;
+  add->path = NULL;
+  add->user = NULL;
+  SH_MUTEX_LOCK(mutex_thread_nolog);
+  get_user_and_path(add);
+  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+  add->next = socklist;
+  socklist  = add;
+  return;
+}
+
+static void check_and_add_sock(char * fbuf, size_t pid)
+{
+  if (0 == strncmp(_("socket:["), fbuf, 8))
+    {
+      char * end;
+      unsigned long sock;
+      size_t len = strlen(fbuf);
+      if (fbuf[len-1] == ']')
+	fbuf[len-1] = '\0';
+      sock = strtoul(&fbuf[8], &end, 0);
+      if (*end == '\0' && fbuf[8] != '\0')
+	{
+	  add_sock(sock, pid);
+	}
+    }
+}
+
+static void fetch_socks(size_t pid)
+{
+  char path[128];
+  DIR * dir;
+  sl_snprintf(path, sizeof(path), _("/proc/%lu/fd"), (unsigned long) pid);
+
+  dir = opendir(path);
+  if (dir)
+    {
+      struct dirent *entry;
+      while (NULL != (entry = readdir(dir)))
+	{
+	  char fpath[384];
+	  char fbuf[64];
+	  int  ret;
+	  /* /proc/PID/fd/N-> socket:[15713] */
+	  sl_snprintf(fpath, sizeof(fpath), _("%s/%s"), path, entry->d_name);
+	  ret = readlink(fpath, fbuf, sizeof(fbuf)-1);   /* flawfinder: ignore */
+	  if (ret > 0)
+	    {
+	      fbuf[ret] = '\0';
+	      check_and_add_sock(fbuf, pid);
+	    }
+	}
+      closedir(dir);
+    }
+}
+
+int sh_port2proc_prepare()
+{
+  size_t i;
+  
+  if (0 != proc_max_pid(&sh_maxpid))
+    {
+      SH_MUTEX_LOCK(mutex_thread_nolog);
+      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+                      _("Failed to detect max_pid"), 
+                      _("sh_port2proc"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
+      SL_RETURN ((-1), _("sh_port2proc"));
+    }
+
+  /* Delete old socket list and re-create it
+   */
+  del_sock_all();
+
+  for (i = sh_minpid; i < sh_maxpid; ++i)
+    {
+      fetch_socks(i);
+    }
+
+  return 0;
+}
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
+			  char * user, size_t userlen)
+{
+  FILE * fd;
+
+  if (proto == IPPROTO_TCP)
+    fd = fopen("/proc/net/tcp", "r");
+  else
+    fd = fopen("/proc/net/udp", "r");
+
+  if (fd)
+    {
+      int n, iface, port, inode;
+      char line[512];
+
+      while (NULL != fgets(line, sizeof(line), fd))
+	{
+	
+	  if (4 == sscanf(line, 
+			  "%d: %X:%X %*X:%*X %*X %*X:%*X %*X:%*X %*X %*d %*d %d %*s",
+			  &n, &iface, &port, &inode))
+	    {
+	      struct in_addr haddr;
+	      haddr.s_addr = (unsigned long)iface;
+
+	      if (haddr.s_addr == saddr->s_addr && port == sport)
+		{
+		  struct sock_store * new = socklist;
+
+		  while (new)
+		    {
+		      if ((unsigned int)inode == new->sock)
+			{
+			  fclose(fd);
+			  if (new->path)
+			    {
+			      if (new->user)
+				sl_strlcpy(user, new->user, userlen);
+			      else
+				sl_strlcpy(user, "-", userlen);
+			      return sh_util_strdup(new->path);
+			    }
+			  goto err_out;
+			}
+		      new = new->next;
+		    }
+		}
+	    }
+	}
+      fclose(fd);
+    }
+ err_out:
+  sl_strlcpy(user, "0", userlen);
+  return sh_util_strdup("-");
+}
+
+#else /* !defined(__linux__) */
+
+char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
+			  char * user, size_t userlen)
+{
+  (void) proto;
+  (void) saddr;
+  (void) sport;
+
+  sl_strlcpy(user, "-", userlen);
+  return sh_util_strdup("-");
+}
+
+int sh_port2proc_prepare()
+{
+  return 0;
+}
+
+#endif
+
+#endif /* defined(SH_USE_PORTCHECK) */
Index: trunk/src/sh_portcheck.c
===================================================================
--- trunk/src/sh_portcheck.c	(revision 178)
+++ trunk/src/sh_portcheck.c	(revision 180)
@@ -135,4 +135,9 @@
 
 static int sh_portchk_severity  = SH_ERR_SEVERE;
+
+extern char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
+				 char * user, size_t userlen);
+extern int sh_port2proc_prepare();
+
 #endif
 
@@ -509,4 +514,7 @@
       if (!portent)
 	{
+	  char * path;
+	  char   user[USER_MAX];
+
 	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
@@ -515,8 +523,10 @@
 		  inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
 #else
+	  path = sh_port2proc_query(proto, &haddr, port, user, sizeof(user));
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_NEW, errbuf);
+			  MSG_PORT_NEW, errbuf, path, user);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  SH_FREE(path);
 #endif
 	  /* 
@@ -527,4 +537,7 @@
       else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
 	{
+	  char * path;
+	  char   user[USER_MAX];
+
 	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
@@ -532,8 +545,10 @@
 	  fprintf(stderr, _("service: %s\n"), errbuf);
 #else
+	  path = sh_port2proc_query(proto, &haddr, port, user, sizeof(user));
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_RESTART, errbuf);
+			  MSG_PORT_RESTART, errbuf, path, user);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  SH_FREE(path);
 #endif
 
@@ -542,4 +557,7 @@
       else if (port != portent->port && (-1) != portent->port)
 	{
+	  char * path;
+	  char   user[USER_MAX];
+
 	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
@@ -547,8 +565,10 @@
 	  fprintf(stderr, _("service: %s\n"), errbuf);
 #else
+	  path = sh_port2proc_query(proto, &haddr, port, user, sizeof(user));
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_NEWPORT, errbuf);
+			  MSG_PORT_NEWPORT, errbuf, path, user);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  SH_FREE(path);
 #endif
 	  portent->port   = port;
@@ -564,4 +584,7 @@
       if (!portent)
 	{
+	  char * path;
+	  char   user[USER_MAX];
+
 	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
@@ -570,8 +593,10 @@
 		  inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
 #else
+	  path = sh_port2proc_query(proto, &haddr, port, user, sizeof(user));
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_NEW, errbuf);
+			  MSG_PORT_NEW, errbuf, path, user);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  SH_FREE(path);
 #endif
 
@@ -582,4 +607,7 @@
       else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
 	{
+	  char * path;
+	  char   user[USER_MAX];
+
 	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
@@ -587,8 +615,10 @@
 	  fprintf(stderr, _("port   : %s\n"), errbuf);
 #else
+	  path = sh_port2proc_query(proto, &haddr, port, user, sizeof(user));
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_RESTART, errbuf);
+			  MSG_PORT_RESTART, errbuf, path, user);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  SH_FREE(path);
 #endif
 
@@ -1482,10 +1512,16 @@
 #endif
 	}
+
+      sh_port2proc_prepare();
+
       if (sh_portchk_check_udp == 1)
 	sh_portchk_scan_ports_udp(min_port, -1);
       sh_portchk_scan_ports_tcp(min_port, -1);
+
+
       sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
       if (sh_portchk_check_udp == 1)
 	sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
+
     }
   SH_MUTEX_UNLOCK(mutex_port_check);
Index: trunk/src/sh_prelude.c
===================================================================
--- trunk/src/sh_prelude.c	(revision 178)
+++ trunk/src/sh_prelude.c	(revision 180)
@@ -700,4 +700,6 @@
         idmef_address_t *address;
         idmef_node_t *node;
+	idmef_user_t *user;
+	idmef_process_t *process;
         idmef_service_t *service;
         idmef_source_t *source = idmef_alert_get_next_source(alert, NULL);
@@ -847,4 +849,52 @@
 
 	SH_FREE( new );
+
+        ptr = get_value(msg, _("user"), NULL);
+
+        if ( ptr ) {
+
+	        ret = idmef_source_new_user(source, &user);
+                if ( ret < 0 ) {
+                        free(ptr);
+                        return ret;
+                }
+
+		ret = idmef_user_new_ident(user, &str);
+                if ( ret < 0 ) {
+		        free(ptr);
+                        return ret;
+		}
+                prelude_string_set_nodup(str, ptr);
+	}
+
+        ptr = get_value(msg, _("path"), NULL);
+
+        if ( ptr ) {
+
+                /*
+                 * In term of IDMEF, this is the full path,
+                 * including the name.
+                 */
+                ret = idmef_source_new_process(source, &process);
+                if ( ret < 0 ) {
+		        free(ptr);
+                        return ret;
+		}
+
+		ret = idmef_process_new_path(process, &str);
+                if ( ret < 0 ) {
+		        free(ptr);
+                        return ret;
+		}
+                prelude_string_set_nodup(str, ptr);
+
+                ptr = strrchr(ptr, '/');
+                if ( ptr ) {
+                        ret = idmef_process_new_name(process, &str);
+                        if ( ret == 0 ) {
+			        prelude_string_set_dup(str, ptr + 1);
+			}
+                }
+        }
 
 	return 0;
