diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/afsocket.c syslog-ng-2.0.5/src/afsocket.c
--- syslog-ng-2.0.5/src/afsocket.c	2007-07-22 14:13:46.000000000 +0100
+++ syslog-ng-2.0.5/src/afsocket.c	2007-09-20 20:40:39.000000000 +0100
@@ -406,8 +406,10 @@
   GSockAddr *peer_addr;
   gchar buf1[256], buf2[256];
   gint new_fd;
   gboolean res;
+  struct ucred creds;
+  socklen_t creds_len = sizeof(creds);
   
   if (g_accept(self->fd, &new_fd, &peer_addr) != G_IO_STATUS_NORMAL)
     {
       msg_error("Error accepting new connection",
@@ -423,8 +425,16 @@
     
   g_fd_set_nonblock(new_fd, TRUE);
   g_fd_set_cloexec(new_fd, TRUE);
     
+  if (getsockopt(new_fd, SOL_SOCKET, SO_PEERCRED, &creds, &creds_len) == 0
+      && creds_len == sizeof(creds))
+    {
+      peer_addr->creds.pid = creds.pid;
+      peer_addr->creds.uid = creds.uid;
+      peer_addr->creds.gid = creds.gid;
+    }
+    
   msg_verbose("Syslog connection accepted",
               evt_tag_str("from", g_sockaddr_format(peer_addr, buf1, sizeof(buf1))),
               evt_tag_str("to", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2))),
               NULL);
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/cfg-grammar.y syslog-ng-2.0.5/src/cfg-grammar.y
--- syslog-ng-2.0.5/src/cfg-grammar.y	2007-05-21 18:21:07.000000000 +0100
+++ syslog-ng-2.0.5/src/cfg-grammar.y	2007-09-21 16:32:56.000000000 +0100
@@ -106,9 +106,9 @@
 /* misc options */
 %token KW_USE_TIME_RECVD
 
 /* filter items*/
-%token KW_FACILITY KW_LEVEL KW_HOST KW_MATCH KW_NETMASK
+%token KW_FACILITY KW_LEVEL KW_HOST KW_MATCH KW_NETMASK KW_UID KW_GID KW_PID
 
 /* yes/no switches */
 %token KW_YES KW_NO
 
@@ -803,9 +803,12 @@
 	| KW_PROGRAM '(' string ')'		{ $$ = filter_prog_new($3); free($3); }
 	| KW_HOST '(' string ')'		{ $$ = filter_host_new($3); free($3); }	
 	| KW_MATCH '(' string ')'		{ $$ = filter_match_new($3); free($3); }
 	| KW_FILTER '(' string ')'		{ $$ = filter_call_new($3, configuration); free($3); }
-	| KW_NETMASK '(' string ')'		{ $$ = filter_netmask_new($3); free($3); }
+	| KW_UID '(' NUMBER ')'			{ $$ = filter_uid_new($3); }
+	| KW_GID '(' NUMBER ')'			{ $$ = filter_gid_new($3); }
+	| KW_GROUP '(' NUMBER ')'		{ $$ = filter_group_new($3); }
+	| KW_PID '(' ')'					{ $$ = filter_pid_new(); }
 	;
 
 filter_fac_list
 	: filter_fac filter_fac_list		{ $$ = $1 | $2; }
@@ -907,5 +910,5 @@
   last_driver = NULL;
   last_reader_options = NULL;
   last_writer_options = NULL;
   last_template = NULL;
-}
\ No newline at end of file
+}
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/cfg-lex.l syslog-ng-2.0.5/src/cfg-lex.l
--- syslog-ng-2.0.5/src/cfg-lex.l	2007-05-21 18:21:07.000000000 +0100
+++ syslog-ng-2.0.5/src/cfg-lex.l	2007-09-21 16:32:35.000000000 +0100
@@ -164,8 +164,11 @@
 	{ "program",		KW_PROGRAM },
         { "host",               KW_HOST },
         { "match",		KW_MATCH },
         { "netmask",		KW_NETMASK },
+        { "uid",		KW_UID },
+        { "gid",		KW_GID },
+        { "pid",		KW_PID },
 
 	/* on/off switches */
 	{ "yes",		KW_YES },
 	{ "on",			KW_YES },
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/filter.c syslog-ng-2.0.5/src/filter.c
--- syslog-ng-2.0.5/src/filter.c	2007-05-21 18:21:07.000000000 +0100
+++ syslog-ng-2.0.5/src/filter.c	2007-09-21 16:32:05.000000000 +0100
@@ -28,8 +28,11 @@
 
 #include <regex.h>
 #include <string.h>
 #include <stdlib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
 
 static void log_filter_rule_free(LogFilterRule *self);
 
 gboolean 
@@ -493,4 +496,122 @@
   self->address.s_addr &= self->netmask.s_addr;
   self->super.eval = filter_netmask_eval;
   return &self->super;
 }
+
+typedef struct _FilterUid
+{
+  FilterExprNode super;
+  uid_t uid;
+} FilterUid;
+
+static gboolean
+filter_uid_eval(FilterExprNode *s, LogMessage *msg)
+{
+  FilterUid *self = (FilterUid *) s;
+  return (msg->saddr->creds.pid && msg->saddr->creds.uid == self->uid) ^ self->super.comp;
+}
+
+FilterExprNode *
+filter_uid_new(guint32 uid)
+{
+  FilterUid *self = g_new0(FilterUid, 1);
+
+  self->super.eval = filter_uid_eval;
+  self->uid = uid;
+  self->super.type = "uid";
+  return &self->super;
+}
+
+typedef struct _FilterGid
+{
+  FilterExprNode super;
+  gid_t gid;
+} FilterGid;
+
+static gboolean
+filter_gid_eval(FilterExprNode *s, LogMessage *msg)
+{
+  FilterGid *self = (FilterGid *) s;
+  return (msg->saddr->creds.pid && msg->saddr->creds.gid == self->gid) ^ self->super.comp;
+}
+
+FilterExprNode *
+filter_gid_new(guint32 gid)
+{
+  FilterGid *self = g_new0(FilterGid, 1);
+
+  self->super.eval = filter_gid_eval;
+  self->gid = gid;
+  self->super.type = "gid";
+  return &self->super;
+}
+
+typedef struct _FilterGroup
+{
+  FilterExprNode super;
+  gid_t gid;
+} FilterGroup;
+
+static gboolean
+filter_group_eval(FilterExprNode *s, LogMessage *msg)
+{
+  FilterGroup *self = (FilterGroup *) s;
+  if (msg->saddr->creds.pid)
+    {
+      struct passwd *pwd = getpwuid(msg->saddr->creds.uid);
+      struct group *grp = getgrgid(self->gid);
+      int i;
+      if (pwd != NULL && grp != NULL)
+        for (i = 0; i >= 0 && grp->gr_mem[i] != NULL; i++)
+          if (!strcmp(pwd->pw_name, grp->gr_mem[i]))
+            return 1 ^ self->super.comp;
+    }
+  return 0 ^ self->super.comp;
+}
+
+FilterExprNode *
+filter_group_new(guint32 gid)
+{
+  FilterGroup *self = g_new0(FilterGroup, 1);
+
+  self->super.eval = filter_group_eval;
+  self->gid = gid;
+  self->super.type = "group";
+  return &self->super;
+}
+
+typedef struct _FilterPid
+{
+  FilterExprNode super;
+} FilterPid;
+
+static gboolean
+filter_pid_eval(FilterExprNode *s, LogMessage *msg)
+{
+  FilterGroup *self = (FilterGroup *) s;
+  if (msg->saddr->creds.pid)
+    if (msg->msg.len)
+      {
+        gchar *start, *end;
+
+        start = strchr(msg->msg.str, '[');
+        if (start)
+          {
+             start++;
+             end = strchr(msg->msg.str, ']');
+             if (end)
+                 return (msg->saddr->creds.pid == atol(start)) ^ self->super.comp;
+          }
+      }
+  return 0 ^ self->super.comp;
+}
+
+FilterExprNode *
+filter_pid_new()
+{
+  FilterPid *self = g_new0(FilterPid, 1);
+
+  self->super.eval = filter_pid_eval;
+  self->super.type = "pid";
+  return &self->super;
+}
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/filter.h syslog-ng-2.0.5/src/filter.h
--- syslog-ng-2.0.5/src/filter.h	2007-05-21 18:21:07.000000000 +0100
+++ syslog-ng-2.0.5/src/filter.h	2007-09-21 16:33:37.000000000 +0100
@@ -53,8 +53,12 @@
 FilterExprNode *filter_host_new(gchar *host);
 FilterExprNode *filter_match_new(gchar *re);
 FilterExprNode *filter_call_new(gchar *rule, struct _GlobalConfig *cfg);
 FilterExprNode *filter_netmask_new(gchar *cidr);
+FilterExprNode *filter_uid_new(guint32 uid);
+FilterExprNode *filter_gid_new(guint32 gid);
+FilterExprNode *filter_group_new(guint32 gid);
+FilterExprNode *filter_pid_new();
 
 typedef struct _LogFilterRule
 {
   gint ref_cnt;
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/gsockaddr.c syslog-ng-2.0.5/src/gsockaddr.c
--- syslog-ng-2.0.5/src/gsockaddr.c	2007-05-21 18:21:07.000000000 +0100
+++ syslog-ng-2.0.5/src/gsockaddr.c	2007-09-20 20:59:30.000000000 +0100
@@ -278,8 +278,9 @@
 {
   gint refcnt;
   guint32 flags;
   GSockAddrFuncs *sa_funcs;
+  struct ucred creds;
   int salen;
   struct sockaddr_in sin;
 } GSockAddrInet;
 
@@ -355,8 +356,11 @@
       addr->sin.sin_family = AF_INET;
       addr->sin.sin_port = htons(port);
       addr->sin.sin_addr = ina;
       addr->sa_funcs = &inet_sockaddr_funcs;
+      addr->creds.pid = 0;
+      addr->creds.uid = -1;
+      addr->creds.gid = -1;
     }
   return (GSockAddr *) addr;
 }
 
@@ -381,8 +385,11 @@
   addr->flags = 0;
   addr->salen = sizeof(struct sockaddr_in);
   addr->sin = *sin;
   addr->sa_funcs = &inet_sockaddr_funcs;
+  addr->creds.pid = 0;
+  addr->creds.uid = -1;
+  addr->creds.gid = -1;
   
   return (GSockAddr *) addr;
 }
 
@@ -396,8 +403,9 @@
 {
   gint refcnt;
   guint32 flags;
   GSockAddrFuncs *sa_funcs;
+  struct ucred creds;
   int salen;
   struct sockaddr_in sin;
   gpointer options;
   guint options_length;
@@ -462,15 +470,17 @@
   addr->sin.sin_family = AF_INET;
   inet_aton(ip, &addr->sin.sin_addr);
   addr->sin.sin_port = 0;
   addr->sa_funcs = &inet_range_sockaddr_funcs;
+  addr->creds.pid = 0;
+  addr->creds.uid = -1;
+  addr->creds.gid = -1;
   if (max_port > min_port)
     {
       addr->last_port = (rand() % (max_port - min_port)) + min_port;
     }
   addr->min_port = min_port;
   addr->max_port = max_port;
-  
   return (GSockAddr *) addr;
 }
 
 
@@ -486,8 +496,9 @@
 {
   gint refcnt;
   guint32 flags;
   GSockAddrFuncs *sa_funcs;
+  struct ucred creds;
   int salen;
   struct sockaddr_in6 sin6;
 } GSockAddrInet6;
 
@@ -549,8 +560,11 @@
   addr->sin6.sin6_family = AF_INET6;
   inet_pton(AF_INET6, ip, &addr->sin6.sin6_addr);
   addr->sin6.sin6_port = htons(port);
   addr->sa_funcs = &inet6_sockaddr_funcs;
+  addr->creds.pid = 0;
+  addr->creds.uid = -1;
+  addr->creds.gid = -1;
   
   return (GSockAddr *) addr;
 }
 
@@ -576,8 +590,11 @@
   addr->flags = 0;
   addr->salen = sizeof(struct sockaddr_in6);
   addr->sin6 = *sin6;
   addr->sa_funcs = &inet6_sockaddr_funcs;
+  addr->creds.pid = 0;
+  addr->creds.uid = -1;
+  addr->creds.gid = -1;
   
   return (GSockAddr *) addr;
 }
 
@@ -595,8 +612,9 @@
 {
   gint refcnt;
   guint32 flags;
   GSockAddrFuncs *sa_funcs;
+  struct ucred creds;
   int salen;
   struct sockaddr_un saun;
 } GSockAddrUnix;
 
@@ -642,8 +660,11 @@
     {
       addr->saun.sun_path[0] = 0;
       addr->salen = 2;
     }
+  addr->creds.pid = 0;
+  addr->creds.uid = -1;
+  addr->creds.gid = -1;
   return (GSockAddr *) addr;
 }
 
 /*+
@@ -668,8 +689,11 @@
   addr->flags = 0;
   addr->sa_funcs = &unix_sockaddr_funcs;
   addr->salen = sunlen;
   addr->saun = *saun;
+  addr->creds.pid = 0;
+  addr->creds.uid = -1;
+  addr->creds.gid = -1;
   return (GSockAddr *) addr;
 }
 
 /*+ private function to prepare a bind on AF_UNIX sockets, e.g. unlink
@@ -696,10 +720,15 @@
 g_sockaddr_unix_format(GSockAddr *addr, gchar *text, gulong n)
 {
   GSockAddrUnix *unix_addr = (GSockAddrUnix *) addr;
   
-  g_snprintf(text, n, "AF_UNIX(%s)", 
-             unix_addr->salen > sizeof(unix_addr->saun.sun_family) && unix_addr->saun.sun_path[0] ? unix_addr->saun.sun_path
-                                          : "anonymous");
+  if (addr->creds.pid != 0)
+    g_snprintf(text, n, "AF_UNIX(%s %u:%u:%u)", 
+               unix_addr->salen > sizeof(unix_addr->saun.sun_family) && unix_addr->saun.sun_path[0] ? unix_addr->saun.sun_path
+                                : "anonymous", addr->creds.pid, addr->creds.uid, addr->creds.gid);
+  else
+    g_snprintf(text, n, "AF_UNIX(%s)", 
+               unix_addr->salen > sizeof(unix_addr->saun.sun_family) && unix_addr->saun.sun_path[0] ? unix_addr->saun.sun_path
+                                : "anonymous");
   return text;
 }
 
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/gsockaddr.h syslog-ng-2.0.5/src/gsockaddr.h
--- syslog-ng-2.0.5/src/gsockaddr.h	2007-05-21 18:21:07.000000000 +0100
+++ syslog-ng-2.0.5/src/gsockaddr.h	2007-09-20 20:57:18.000000000 +0100
@@ -41,8 +41,9 @@
 {
   gint refcnt;
   guint32 flags;
   GSockAddrFuncs *sa_funcs;
+  struct ucred creds;
   int salen;
   struct sockaddr sa;
 } GSockAddr;
 
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/macros.c syslog-ng-2.0.5/src/macros.c
--- syslog-ng-2.0.5/src/macros.c	2007-07-22 14:12:30.000000000 +0100
+++ syslog-ng-2.0.5/src/macros.c	2007-09-20 21:36:41.000000000 +0100
@@ -30,8 +30,11 @@
 #include "filter.h"
 
 #include <time.h>
 #include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
 
 struct macro_def
 {
   char *name;
@@ -99,8 +102,14 @@
         { "FULLHOST_FROM", M_FULLHOST_FROM },
         { "HOST", M_HOST },
         { "FULLHOST", M_FULLHOST },
 
+        { "FROM_PID", M_FROM_PID },
+        { "FROM_UID", M_FROM_UID },
+        { "FROM_GID", M_FROM_GID },
+        { "FROM_USER", M_FROM_USER },
+        { "FROM_GROUP", M_FROM_GROUP },
+
         { "PROGRAM", M_PROGRAM },
         { "PID", M_PID },
         { "MSG", M_MESSAGE },
         { "MSGONLY", M_MSGONLY },
@@ -260,8 +269,55 @@
               }
           }
         break;
       }
+    case M_FROM_PID:
+      {
+        /* from pid */
+        if (msg->saddr->creds.pid != 0)
+          {
+            g_string_sprintfa(result, "%u", msg->saddr->creds.pid);
+          }
+        break;
+      }
+    case M_FROM_UID:
+      {
+        /* from uid */
+        if (msg->saddr->creds.pid != 0)
+          {
+            g_string_sprintfa(result, "%u", msg->saddr->creds.uid);
+          }
+        break;
+      }
+    case M_FROM_GID:
+      {
+        /* from gid */
+        if (msg->saddr->creds.pid != 0)
+          g_string_sprintfa(result, "%u", msg->saddr->creds.gid);
+        break;
+      }
+    case M_FROM_USER:
+      {
+        /* from user */
+        if (msg->saddr->creds.pid != 0)
+          {
+            struct passwd *pwd = getpwuid(msg->saddr->creds.uid);
+            if (pwd != NULL)
+              g_string_sprintfa(result, "%s", pwd->pw_name);
+          }
+        break;
+      }
+    case M_FROM_GROUP:
+      {
+        /* from group */
+        if (msg->saddr->creds.pid != 0)
+          {
+            struct group *grp = getgrgid(msg->saddr->creds.gid);
+            if (grp != NULL)
+              g_string_sprintfa(result, "%s", grp->gr_name);
+          }
+        break;
+      }
     case M_DATE:
     case M_FULLDATE:
     case M_ISODATE:
     case M_STAMP:
diff -X syslog-ng-2.0.5/diff.ignore -U4 -r syslog-ng-2.0.5/src/macros.h syslog-ng-2.0.5/src/macros.h
--- syslog-ng-2.0.5/src/macros.h	2007-07-22 14:12:30.000000000 +0100
+++ syslog-ng-2.0.5/src/macros.h	2007-09-20 21:30:04.000000000 +0100
@@ -97,8 +97,14 @@
   M_HOST_FROM,
   M_PROGRAM,
   M_PID,
 
+  M_FROM_PID,
+  M_FROM_UID,
+  M_FROM_GID,
+  M_FROM_USER,
+  M_FROM_GROUP,
+
   M_MESSAGE,
   M_MSGONLY,
   M_SOURCE_IP,
   M_MAX,
