gunnar: server/imapd/patches/cyrus-imapd-2.3.10 KOLAB_cyrus-cyradm_Annotations.patch, NONE, 1.1 KOLAB_cyrus-imapd_Annotations2.patch, NONE, 1.1 KOLAB_cyrus-imapd_Folder-names.patch, NONE, 1.1 KOLAB_cyrus-imapd_Groups.patch, NONE, 1.1 KOLAB_cyrus-imapd_Logging.patch, NONE, 1.1 KOLAB_cyrus-imapd_UID.patch, NONE, 1.1

cvs at kolab.org cvs at kolab.org
Thu Apr 23 23:33:11 CEST 2009


Author: gunnar

Update of /kolabrepository/server/imapd/patches/cyrus-imapd-2.3.10
In directory doto:/tmp/cvs-serv19408/cyrus-imapd-2.3.10

Added Files:
	KOLAB_cyrus-cyradm_Annotations.patch 
	KOLAB_cyrus-imapd_Annotations2.patch 
	KOLAB_cyrus-imapd_Folder-names.patch 
	KOLAB_cyrus-imapd_Groups.patch KOLAB_cyrus-imapd_Logging.patch 
	KOLAB_cyrus-imapd_UID.patch 
Log Message:
Move the cyrus patches over here. In addition a Makefile has been added to facilitate the patch series update between versions. This Makefile is dependant on mercurial. It will automatically fetch an old version, check the patch series, fetch the new version, pull in changes and reapply the patch series (make update). After fixing any errors that may occur on pushing the series the patches can be exported into their respective patch directory by running make patches.

--- NEW FILE: KOLAB_cyrus-cyradm_Annotations.patch ---
Allows to use arbitrary annotations with the cyradm tool.

diff -r a07884e259c3 doc/man/cyradm.1.html
--- a/doc/man/cyradm.1.html	Thu Oct 25 08:24:39 2007 +0200
+++ b/doc/man/cyradm.1.html	Thu Oct 25 08:29:40 2007 +0200
@@ -241,6 +241,13 @@ The currently supported attributes are:<
 <dd>
 <p>Sets an email address to which messages injected into the server via NNTP 
 will be sent.</p>
+</dd>
+</li>
+<dt><strong><a NAME="item__2fexplicit_2fannotation"><code>/explicit/annotation</code></a></strong>
+
+<dd>
+<p>Sets the annotation <em>/explicit/annotation</em>
+on <em>mailbox</em> to <em>value</em>.</p>
 </dd>
 </li>
 <dt><strong><a name="item_sharedseen"><code>sharedseen</code></a></strong>
diff -r a07884e259c3 perl/imap/IMAP/Admin.pm
--- a/perl/imap/IMAP/Admin.pm	Thu Oct 25 08:24:39 2007 +0200
+++ b/perl/imap/IMAP/Admin.pm	Thu Oct 25 08:29:40 2007 +0200
@@ -796,11 +796,11 @@ sub mboxconfig {
     return undef;
   }
 
-  if(!exists($values{$entry})) {
-    $self->{error} = "Unknown parameter $entry";
-  }
-
-  $entry = $values{$entry};
+  if(exists($values{$entry})) {
+    $entry = $values{$entry};    
+  } else {
+    $self->{error} = "Unknown parameter $entry" unless substr($entry,0,1) eq "/";
+  }
 
   my ($rc, $msg);
 
diff -r a07884e259c3 perl/imap/IMAP/Shell.pm
--- a/perl/imap/IMAP/Shell.pm	Thu Oct 25 08:24:39 2007 +0200
+++ b/perl/imap/IMAP/Shell.pm	Thu Oct 25 08:29:40 2007 +0200
@@ -126,7 +126,7 @@ my %builtins = (exit =>
 		  [\&_sc_info, '[mailbox]',
 		   'display mailbox/server metadata'],
 		mboxcfg =>
-		  [\&_sc_mboxcfg, 'mailbox [comment|condstore|expire|news2mail|sharedseen|sieve|squat] value',
+		  [\&_sc_mboxcfg, 'mailbox [comment|condstore|news2mail|expire|sieve|squat|/<explicit annotation>] value',
 		   'configure mailbox'],
 		mboxconfig => 'mboxcfg',
 		reconstruct =>
@@ -1436,7 +1436,7 @@ sub _sc_mboxcfg {
   while (defined ($opt = shift(@argv))) {
     last if $opt eq '--';
     if ($opt =~ /^-/) {
-      die "usage: mboxconfig mailbox [comment|condstore|expire|news2mail|sharedseen|sieve|squat] value\n";
+      die "usage: mboxconfig mailbox [comment|condstore|expire|news2mail|sharedseen|sieve|squat|/<explicit annotation>] value\n";
     }
     else {
       push(@nargv, $opt);
@@ -1445,7 +1445,7 @@ sub _sc_mboxcfg {
   }
   push(@nargv, @argv);
   if (@nargv < 2) {
-    die "usage: mboxconfig mailbox [comment|condstore|expire|news2mail|sharedseen|sieve|squat] value\n";
+    die "usage: mboxconfig mailbox [comment|condstore|expire|news2mail|sharedseen|sieve|squat|/<explicit annotation>] value\n";
   }
   if (!$cyrref || !$$cyrref) {
     die "mboxconfig: no connection to server\n";
diff -r a07884e259c3 perl/imap/cyradm.sh
--- a/perl/imap/cyradm.sh	Thu Oct 25 08:24:39 2007 +0200
+++ b/perl/imap/cyradm.sh	Thu Oct 25 08:29:40 2007 +0200
@@ -241,6 +241,10 @@ mailboxes).
 
 Indicates that the mailbox should have a squat index created for it.
 
+=item C</explicit/annotation>
+
+Sets the annotation I</explicit/annotation> on I<mailbox> to I<value>. 
+
 =back 
 
 =item C<renamemailbox> [C<--partition> I<partition>] I<oldname> I<newname>

--- NEW FILE: KOLAB_cyrus-imapd_Annotations2.patch ---
Provides a new version of annotation support for the cyrus imapd server [Version: 2.3.9]

diff -r b693d1281318 imap/annotate.c
--- a/imap/annotate.c	Thu Oct 25 08:21:36 2007 +0200
+++ b/imap/annotate.c	Thu Oct 25 08:24:37 2007 +0200
@@ -40,6 +40,13 @@
  *
  */
 /*
+ * This file contains code Copyright (c) 2006 by Thomas Viehmann.
+ * You may distribute source code or binaries under the conditions
+ * conditions given in the CMU license, provided this note stays intact
+ * in the distributed source. If you want to distribute my code without
+ * this notice, do contact me at <tv at beamnet.de>.
+ */
+/*
  * $Id: KOLAB_cyrus-imapd_Annotations2.patch,v 1.1 2009/04/23 21:33:09 gunnar Exp $
  */
 
@@ -92,6 +99,8 @@ int (*proxy_store_func)(const char *serv
 int (*proxy_store_func)(const char *server, const char *mbox_pat,
 			struct entryattlist *entryatts) = NULL;
 
+void init_annotation_definitions();
+
 /* String List Management */
 /*
  * Append 's' to the strlist 'l'.  Possibly include metadata.
@@ -238,6 +247,8 @@ void annotatemore_init(int myflags,
     if (store_func) {
 	proxy_store_func = store_func;
     }
+    
+    init_annotation_definitions();
 }
 
 void annotatemore_open(char *fname)
@@ -1833,6 +1844,224 @@ const struct annotate_st_entry mailbox_r
     { NULL, 0, ANNOTATION_PROXY_T_INVALID, 0, 0, NULL, NULL }
 };
 
+struct annotate_st_entry_list *server_entries_list = NULL;
+struct annotate_st_entry_list *mailbox_rw_entries_list = NULL;
+
+enum {
+  ANNOTATION_SCOPE_SERVER = 1,
+  ANNOTATION_SCOPE_MAILBOX = 2
+};
+
+const struct annotate_attrib annotation_scope_names[] =
+{
+    { "server", ANNOTATION_SCOPE_SERVER },
+    { "mailbox", ANNOTATION_SCOPE_MAILBOX },
+    { NULL, 0 }
+};
+
+const struct annotate_attrib annotation_proxy_type_names[] =
+{
+    { "proxy", PROXY_ONLY },
+    { "backend", BACKEND_ONLY },
+    { "proxy_and_backend", PROXY_AND_BACKEND },
+    { NULL, 0 }
+};
+
+const struct annotate_attrib attribute_type_names[] = 
+{
+    { "content-type", ATTRIB_TYPE_CONTENTTYPE },
+    { "string", ATTRIB_TYPE_STRING },
+    { "boolean", ATTRIB_TYPE_BOOLEAN },
+    { "uint", ATTRIB_TYPE_UINT },
+    { "int", ATTRIB_TYPE_INT },
+    { NULL, 0 }
+};
+
+#define ANNOT_DEF_MAXLINELEN 1024
+
+int table_lookup(const struct annotate_attrib *table,
+                                  char* name,
+                                  size_t namelen,
+                                  char* errmsg) 
+/* search in table for the value given by name and namelen (name is null-terminated,
+   but possibly more than just the key). errmsg is used to hint the user where we failed */
+{
+  char errbuf[ANNOT_DEF_MAXLINELEN*2];
+  int entry;
+  
+  for (entry = 0; table[entry].name &&
+                  (strncasecmp(table[entry].name, name, namelen)
+                   || table[entry].name[namelen] != '\0'); entry++);
+
+  if (! table[entry].name) {
+    sprintf(errbuf, "invalid %s at '%s'", errmsg, name);
+    fatal(errbuf, EC_CONFIG);
+  }
+  return table[entry].entry;
+}
+
+char *consume_comma(char* p)
+  /* advance beyond the next ',', skipping whitespace, fail if next non-space is no comma */
+{
+  char errbuf[ANNOT_DEF_MAXLINELEN*2];
+
+  for (; *p && isspace(*p); p++);  
+  if (*p != ',') {
+    sprintf(errbuf, "',' expected, '%s' found parsing annotation definition",
+            p);
+    fatal(errbuf, EC_CONFIG);
+  }
+  p++;
+  for (; *p && isspace(*p); p++);  
+  
+  return p;
+}
+
+int parse_table_lookup_bitmask(const struct annotate_attrib *table,
+                               char** s,
+                               char* errmsg) 
+  /* parses strings of the form value1 [ value2 [ ... ]]
+     value1 is mapped via table to ints and the result ored
+     whitespace is allowed between value names and punctuation
+     the field must end in '\0' or ','
+     s is advanced to '\0' or ','
+     on error errmsg is used to identify item to be parsed
+   */
+{
+  char errbuf[ANNOT_DEF_MAXLINELEN*2];
+  int result = 0;
+  char *p, *p2;
+
+  p = *s;
+  do {
+    p2 = p;
+    for (; *p && (isalnum(*p) || *p=='.' || *p=='-' || *p=='_' || *p=='/');p++);
+    result |= table_lookup(table, p2, p-p2, errmsg);
+    for (; *p && isspace(*p); p++);
+  } while (*p && *p != ',');
+
+  *s = p;
+  return result;
+}
+
+void init_annotation_definitions()
+{
+  char *p, *p2, *tmp;
+  const char *filename;
+  char aline[ANNOT_DEF_MAXLINELEN];
+  char errbuf[ANNOT_DEF_MAXLINELEN*2];
+  struct annotate_st_entry_list *se, *me;
+  struct annotate_st_entry *ae;
+  int i;
+  FILE* f;
+
+  /* NOTE: we assume # static entries > 0 */
+  server_entries_list = xmalloc(sizeof(struct annotate_st_entry_list));
+  mailbox_rw_entries_list = xmalloc(sizeof(struct annotate_st_entry_list));
+  se = server_entries_list;
+  me = mailbox_rw_entries_list;
+  /* copy static entries into list */
+  for (i = 0; server_entries[i].name;i++) {
+    se->entry = &server_entries[i];
+    if (server_entries[i+1].name) {
+      se->next = xmalloc(sizeof(struct annotate_st_entry_list));
+      se = se->next;
+    }
+  }
+  /* copy static entries into list */
+  for (i = 0; mailbox_rw_entries[i].name;i++) {
+    me->entry = &mailbox_rw_entries[i];
+    if (mailbox_rw_entries[i+1].name) {
+      me->next = xmalloc(sizeof(struct annotate_st_entry_list));
+      me = me->next;
+    }
+  }
+
+  /* parse config file */
+  filename = config_getstring(IMAPOPT_ANNOTATION_DEFINITIONS);
+
+  if (! filename) {
+    se->next = NULL;
+    me->next = NULL;
+    return;
+  }
+  
+  f = fopen(filename,"r");
+  if (! f) {
+    sprintf(errbuf, "could not open annotation definiton %s", filename);
+    fatal(errbuf, EC_CONFIG);
+  }
+  
+  while (fgets(aline, sizeof(aline), f)) {
+    // remove leading space, skip blank lines and comments
+    for (p = aline; *p && isspace(*p); p++);
+    if (!*p || *p == '#') continue;
+
+    // note, we only do the most basic validity checking and may
+    // be more restrictive than neccessary
+
+    ae = xmalloc(sizeof(struct annotate_st_entry));
+
+    p2 = p;
+    for (; *p && (isalnum(*p) || *p=='.' || *p=='-' || *p=='_' || *p=='/');p++);
+    // TV-TODO: should test for empty
+    ae->name = xstrndup(p2, p-p2);
+
+    p = consume_comma(p);
+  
+    p2 = p;
+    for (; *p && (isalnum(*p) || *p=='.' || *p=='-' || *p=='_' || *p=='/');p++);
+
+    if (table_lookup(annotation_scope_names, p2, p-p2,
+                     "annotation scope")==ANNOTATION_SCOPE_SERVER) {
+      se->next = xmalloc(sizeof(struct annotate_st_entry_list));
+      se = se->next;
+      se->entry = ae;
+    }
+    else {
+      me->next = xmalloc(sizeof(struct annotate_st_entry_list));
+      me = me->next;      
+      me->entry = ae;
+    }
+    
+    p = consume_comma(p);
+    p2 = p;
+    for (; *p && (isalnum(*p) || *p=='.' || *p=='-' || *p=='_' || *p=='/');p++);
+    ae->type = table_lookup(attribute_type_names, p2, p-p2,
+                                  "attribute type");
+  
+    p = consume_comma(p);
+    ae->proxytype = parse_table_lookup_bitmask(annotation_proxy_type_names,
+                                               &p,
+                                               "annotation proxy type");
+
+    p = consume_comma(p);
+    ae->attribs = parse_table_lookup_bitmask(annotation_attributes,
+                                             &p,
+                                             "annotation attributes");
+    
+    p = consume_comma(p);
+    p2 = p;
+    for (; *p && (isalnum(*p) || *p=='.' || *p=='-' || *p=='_' || *p=='/');p++);
+    tmp = xstrndup(p2, p-p2);
+    ae->acl = cyrus_acl_strtomask(tmp);
+    free(tmp);
+
+    for (; *p && isspace(*p); p++);
+    if (*p) {
+      sprintf(errbuf, "junk at end of line: '%s'", p);
+      fatal(errbuf, EC_CONFIG);
+    }
+    
+    ae->set = annotation_set_todb;
+    ae->rock = NULL;
+  }
+
+  fclose(f);
+  se->next = NULL;
+  me->next = NULL;
+}
+
 int annotatemore_store(char *mailbox,
 		       struct entryattlist *l,
 		       struct namespace *namespace,
@@ -1844,7 +2073,7 @@ int annotatemore_store(char *mailbox,
     struct entryattlist *e = l;
     struct attvaluelist *av;
     struct storedata sdata;
-    const struct annotate_st_entry *entries;
+    const struct annotate_st_entry_list *entries, *currententry;
     time_t now = time(0);
 
     memset(&sdata, 0, sizeof(struct storedata));
@@ -1855,45 +2084,45 @@ int annotatemore_store(char *mailbox,
 
     if (!mailbox[0]) {
 	/* server annotations */
-	entries = server_entries;
+	entries = server_entries_list;
     }
     else {
 	/* mailbox annotation(s) */
-	entries = mailbox_rw_entries;
+	entries = mailbox_rw_entries_list;
     }
 
     /* Build a list of callbacks for storing the annotations */
     while (e) {
-	int entrycount, attribs;
+	int attribs;
 	struct annotate_st_entry_list *nentry = NULL;
 
 	/* See if we support this entry */
-	for (entrycount = 0;
-	     entries[entrycount].name;
-	     entrycount++) {
-	    if (!strcmp(e->entry, entries[entrycount].name)) {
+	for (currententry = entries;
+	     currententry;
+	     currententry = currententry->next) {
+	    if (!strcmp(e->entry, currententry->entry->name)) {
 		break;
 	    }
 	}
-	if (!entries[entrycount].name) {
+	if (!currententry) {
 	    /* unknown annotation */
 	    return IMAP_PERMISSION_DENIED;
 	}
 
 	/* Add this entry to our list only if it
 	   applies to our particular server type */
-	if ((entries[entrycount].proxytype != PROXY_ONLY)
+	if ((currententry->entry->proxytype != PROXY_ONLY)
 	    || proxy_store_func) {
 	    nentry = xzmalloc(sizeof(struct annotate_st_entry_list));
 	    nentry->next = sdata.entry_list;
-	    nentry->entry = &(entries[entrycount]);
+	    nentry->entry = currententry->entry;
 	    nentry->shared.modifiedsince = now;
 	    nentry->priv.modifiedsince = now;
 	    sdata.entry_list = nentry;
 	}
 
 	/* See if we are allowed to set the given attributes. */
-	attribs = entries[entrycount].attribs;
+	attribs = currententry->entry->attribs;
 	av = e->attvalues;
 	while (av) {
 	    const char *value;
@@ -1903,7 +2132,7 @@ int annotatemore_store(char *mailbox,
 		    goto cleanup;
 		}
 		value = annotate_canon_value(av->value,
-					     entries[entrycount].type);
+					     currententry->entry->type);
 		if (!value) {
 		    r = IMAP_ANNOTATION_BADVALUE;
 		    goto cleanup;
@@ -1929,7 +2158,7 @@ int annotatemore_store(char *mailbox,
 		    goto cleanup;
 		}
 		value = annotate_canon_value(av->value,
-					     entries[entrycount].type);
+					     currententry->entry->type);
 		if (!value) {
 		    r = IMAP_ANNOTATION_BADVALUE;
 		    goto cleanup;
diff -r b693d1281318 lib/imapoptions
--- a/lib/imapoptions	Thu Oct 25 08:21:36 2007 +0200
+++ b/lib/imapoptions	Thu Oct 25 08:24:37 2007 +0200
@@ -152,6 +152,9 @@ are listed with ``<none>''.
    user on their mailboxes?  In a large organization this can cause
    support problems, but it's enabled by default. */
 
+{ "annotation_definitions", NULL, STRING }
+/* File containing annotation definitions. */
+
 { "auth_mech", "unix", STRINGLIST("unix", "pts", "krb", "krb5")}
 /* The authorization mechanism to use. */
 

--- NEW FILE: KOLAB_cyrus-imapd_Folder-names.patch ---
Modifies the set of accepted characters in folder names for the cyrus imapd server [Version: 2.3.9]

diff -r 6bcd324910d3 imap/mboxname.c
--- a/imap/mboxname.c	Thu Oct 25 08:30:33 2007 +0200
+++ b/imap/mboxname.c	Thu Oct 25 08:30:43 2007 +0200
@@ -700,8 +700,13 @@ int mboxname_netnewscheck(char *name)
 /*
  * Apply site policy restrictions on mailbox names.
  * Restrictions are hardwired for now.
- */
+
+ * original definition 
 #define GOODCHARS " +,-.0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"
+ */
+
+#define GOODCHARS " #$%'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+
 int mboxname_policycheck(char *name)
 {
     unsigned i;

--- NEW FILE: KOLAB_cyrus-imapd_Groups.patch ---
Allows to use a file other than /etc/groups for group definitions within the cyrus imapd server [Version: 2.3.9]

diff -r e502c48f9ba9 lib/auth_unix.c
--- a/lib/auth_unix.c	Thu Oct 25 08:10:12 2007 +0200
+++ b/lib/auth_unix.c	Thu Oct 25 08:21:36 2007 +0200
@@ -48,12 +48,133 @@
 #include <stdlib.h>
 #include <pwd.h>
 #include <grp.h>
+#include <stdio.h>
 #include <ctype.h>
 #include <string.h>
 
 #include "auth.h"
 #include "libcyr_cfg.h"
 #include "xmalloc.h"
+
+#ifdef __FreeBSD__
+/*
+ * __getgrent.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf at linux.mit.edu>.
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+static struct group *__getgrent(int grp_fd, char *line_buff, char **members)
+{
+    short line_index;
+    short buff_size;
+    static struct group group;
+    register char *ptr;
+    char *field_begin;
+    short member_num;
+    char *endptr;
+    int line_len;
+
+    /* We use the restart label to handle malformatted lines */
+    restart:
+    line_index = 0;
+    buff_size = 256;
+
+    line_buff = realloc(line_buff, buff_size);
+    while (1) {
+        if ((line_len = read(grp_fd, line_buff + line_index,
+                        buff_size - line_index)) <= 0) {
+            return NULL;
+        }
+        field_begin = strchr(line_buff, '\n');
+        if (field_begin != NULL) {
+            lseek(grp_fd,
+                    (long) (1 + field_begin -
+                            (line_len + line_index + line_buff)), SEEK_CUR);
+            *field_begin = '\0';
+            if (*line_buff == '#' || *line_buff == ' '
+                    || *line_buff == '\n' || *line_buff == '\t')
+                goto restart;
+            break;
+        } else {
+            /* Allocate some more space */
+            line_index = buff_size;
+            buff_size += 256;
+            line_buff = realloc(line_buff, buff_size);
+        }
+    }
+
+    /* Now parse the line */
+    group.gr_name = line_buff;
+    ptr = strchr(line_buff, ':');
+    if (ptr == NULL)
+        goto restart;
+    *ptr++ = '\0';
+
+    group.gr_passwd = ptr;
+    ptr = strchr(ptr, ':');
+    if (ptr == NULL)
+        goto restart;
+    *ptr++ = '\0';
+
+    field_begin = ptr;
+    ptr = strchr(ptr, ':');
+    if (ptr == NULL)
+        goto restart;
+    *ptr++ = '\0';
+
+    group.gr_gid = (gid_t) strtoul(field_begin, &endptr, 10);
+    if (*endptr != '\0')
+        goto restart;
+
+    member_num = 0;
+    field_begin = ptr;
+
+    if (members != NULL)
+        free(members);
+    members = (char **) malloc((member_num + 1) * sizeof(char *));
+    for ( ; field_begin && *field_begin != '\0'; field_begin = ptr) {
+        if ((ptr = strchr(field_begin, ',')) != NULL)
+            *ptr++ = '\0';
+        members[member_num++] = field_begin;
+        members = (char **) realloc(members,
+                (member_num + 1) * sizeof(char *));
+    }
+    members[member_num] = NULL;
+
+    group.gr_mem = members;
+    return &group;
+}
+    
+static char *line_buff = NULL;
+static char **members  = NULL;
+
+struct group *fgetgrent(FILE *file)
+{
+    if (file == NULL) {
+        errno = EINTR;
+        return NULL;
+    }
+    return __getgrent(fileno(file), line_buff, members);
+}
+#endif /* __FreeBSD__ */
 
 struct auth_state {
     char userid[81];
@@ -142,6 +263,25 @@ static char allowedchars[256] = {
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+static struct group* fgetgrnam(const char* name)
+{
+    struct group *grp;
+    FILE *groupfile;
+
+    groupfile = fopen("/etc/imapd.group", "r");
+    if (!groupfile) groupfile = fopen("/etc/group", "r");
+    if (groupfile) {
+       while ((grp = fgetgrent(groupfile))) {
+         if (strcasecmp(grp->gr_name, name) == 0) {
+           fclose(groupfile);
+           return grp;
+         }
+       }
+    } 
+    if (groupfile) fclose(groupfile);
+    return NULL;
+} 
+
 /*
  * Convert 'identifier' into canonical form.
  * Returns a pointer to a static buffer containing the canonical form
@@ -177,7 +317,7 @@ size_t len;
      */
     
     if (!strncmp(retbuf, "group:", 6)) {
-	grp = getgrnam(retbuf+6);
+	grp = fgetgrnam(retbuf+6);
 	if (!grp) return 0;
 	strcpy(retbuf+6, grp->gr_name);
 	return retbuf;
@@ -228,6 +368,7 @@ static struct auth_state *mynewstate(con
     int ret, ngroups = 0;
 #else
     char **mem;
+    FILE *groupfile;
 #endif
 
     identifier = mycanonifyid(identifier, 0);
@@ -286,20 +427,23 @@ err:
     if (groupids) free(groupids);
 
 #else /* !HAVE_GETGROUPLIST */
-    setgrent();
-    while ((grp = getgrent())) {
-	for (mem = grp->gr_mem; *mem; mem++) {
-	    if (!strcmp(*mem, identifier)) break;
-	}
-
-	if (*mem || (pwd && pwd->pw_gid == grp->gr_gid)) {
-	    newstate->ngroups++;
-	    newstate->group = (char **)xrealloc((char *)newstate->group,
-						newstate->ngroups * sizeof(char *));
-	    newstate->group[newstate->ngroups-1] = xstrdup(grp->gr_name);
-	}
-    }
-    endgrent();
+    groupfile = fopen("/etc/imapd.group", "r");
+    if (!groupfile) groupfile = fopen("/etc/group", "r");
+    if (groupfile) {
+       while ((grp = fgetgrent(groupfile))) {
+         for (mem = grp->gr_mem; *mem; mem++) {
+            if (!strcasecmp(*mem, identifier)) break;
+         }
+
+         if (*mem || (pwd && pwd->pw_gid == grp->gr_gid)) {
+            newstate->ngroups++;
+            newstate->group = (char **)xrealloc((char *)newstate->group,
+                                                newstate->ngroups * sizeof(char *));
+            newstate->group[newstate->ngroups-1] = xstrdup(grp->gr_name);
+         }
+       }
+       fclose(groupfile);
+    } 
 #endif /* HAVE_GETGROUPLIST */
 
     return newstate;

--- NEW FILE: KOLAB_cyrus-imapd_Logging.patch ---
Provides improved logging for the cyrus imapd server [Version: 2.3.9]

diff -r e60d8aee10e9 imap/append.c
--- a/imap/append.c	Thu Oct 25 08:30:15 2007 +0200
+++ b/imap/append.c	Thu Oct 25 08:30:23 2007 +0200
@@ -648,6 +648,9 @@ int append_fromstage(struct appendstate 
 
     /* ok, we've successfully added a message */
     as->quota_used += message_index.size;
+
+    syslog(LOG_DEBUG, "append_fromstage: message %d added to %s",
+	   message_index.uid, mailbox->name );
 
     return 0;
 }
diff -r e60d8aee10e9 imap/imapd.c
--- a/imap/imapd.c	Thu Oct 25 08:30:15 2007 +0200
+++ b/imap/imapd.c	Thu Oct 25 08:30:23 2007 +0200
@@ -3510,17 +3510,19 @@ void cmd_close(char *tag)
 	if (!r) sync_log_mailbox(imapd_mailbox->name);
     }
 
+    if (r) {
+	prot_printf(imapd_out, "%s NO %s\r\n", tag, error_message(r));
+    }
+    else {
+	prot_printf(imapd_out, "%s OK %s\r\n", tag,
+		    error_message(IMAP_OK_COMPLETED));
+	syslog(LOG_DEBUG, "cmd_expunge: user %s, mailbox %s, sequence %s",
+	       imapd_userid, imapd_mailbox->name, "''");
+    }
+
     index_closemailbox(imapd_mailbox);
     mailbox_close(imapd_mailbox);
     imapd_mailbox = 0;
-
-    if (r) {
-	prot_printf(imapd_out, "%s NO %s\r\n", tag, error_message(r));
-    }
-    else {
-	prot_printf(imapd_out, "%s OK %s\r\n", tag,
-		    error_message(IMAP_OK_COMPLETED));
-    }
 }    
 
 /*
diff -r e60d8aee10e9 imap/mailbox.c
--- a/imap/mailbox.c	Thu Oct 25 08:30:15 2007 +0200
+++ b/imap/mailbox.c	Thu Oct 25 08:30:23 2007 +0200
@@ -2520,6 +2520,8 @@ int mailbox_expunge(struct mailbox *mail
 	*(fname->tail)++ = '/';
 	fname->len++;
 	for (msgno = 0; msgno < numdeleted; msgno++) {
+	    syslog(LOG_DEBUG, "mailbox_expunge: removing mail %s:%d",
+		   mailbox->name, deleted[msgno]);
 	    mailbox_message_get_fname(mailbox, deleted[msgno],
 				      fname->tail,
 				      sizeof(fname->buf) - fname->len);

--- NEW FILE: KOLAB_cyrus-imapd_UID.patch ---
Allows login by uid rather than the mail address on the cyrus imapd server [Version: 2.3.9]

diff -r d62bf3b0902d configure
--- a/configure	Thu Oct 25 08:30:57 2007 +0200
+++ b/configure	Thu Oct 25 08:31:06 2007 +0200
@@ -18119,7 +18119,7 @@ done
 done
 
 IMAP_COM_ERR_LIBS="${COM_ERR_LIBS}"
-IMAP_LIBS="${LIB_SASL} ${LIBS}"
+IMAP_LIBS="${LIB_SASL} -lldap -llber ${LIBS}"
 
 
 
diff -r d62bf3b0902d imap/global.c
--- a/imap/global.c	Thu Oct 25 08:30:57 2007 +0200
+++ b/imap/global.c	Thu Oct 25 08:31:06 2007 +0200
@@ -52,6 +52,9 @@
 #include <netinet/in.h>
 #include <sys/stat.h>
 
+#include <ldap.h>
+#include <lber.h>
+
 #if HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -362,6 +365,18 @@ char *canonify_userid(char *user, char *
     char *domain = NULL;
     int len = strlen(user);
     char buf[81];
+    const char *uri;
+    const char *base;
+    const char *binddn;
+    const char *bindpw;
+    struct timeval timeout;
+    char filter[255];
+    LDAP *handle;
+    LDAPMessage *res;
+    LDAPMessage *entry;
+    char ** vals;
+
+    int rc;
 
     /* check for domain */
     if (config_virtdomains &&
@@ -380,6 +395,47 @@ char *canonify_userid(char *user, char *
     }
 
     if (config_virtdomains) {
+        if (config_virtdomains == IMAP_ENUM_VIRTDOMAINS_LDAP) {
+           uri = config_getstring(IMAPOPT_LDAP_URI);
+           base = config_getstring(IMAPOPT_LDAP_BASE);
+           binddn = config_getstring(IMAPOPT_LDAP_BIND_DN);
+           bindpw = config_getstring(IMAPOPT_LDAP_PASSWORD);
+           timeout.tv_sec = config_getint(IMAPOPT_LDAP_TIME_LIMIT);
+           timeout.tv_usec = 0;
+           sprintf(filter, "(uid=%s)", user);
+           rc = ldap_initialize(&handle, uri);
+           if (rc != LDAP_SUCCESS) {
+                syslog(LOG_ERR, "ldap_initialize failed (%s)", uri);
+           } else {
+	        rc = ldap_simple_bind_s(handle, binddn, bindpw);
+	        if (rc != LDAP_SUCCESS) {
+                     syslog(LOG_ERR, "ldap_simple_bind() failed %d (%s)", rc, ldap_err2string(rc));
+	        } else {
+	             rc = ldap_search_st(handle, base, LDAP_SCOPE_SUBTREE, filter, NULL, 0, &timeout, &res);
+                     if (rc != LDAP_SUCCESS) {
+                          syslog(LOG_ERR, "ldap_search_st failed %d (%s)", rc, ldap_err2string(rc));
+                     } else {
+	                  if ( (entry = ldap_first_entry(handle, res)) != NULL ) {
+			       // read mail attribute from entry
+			       if ( (vals = ldap_get_values(handle, entry, "mail")) ) {
+  				    if (strchr(vals[0], '@')) {
+				        static char buf[81]; /* same size as in auth_canonifyid */
+					strncpy( buf, vals[0], sizeof(buf) );
+					buf[80] = '\0'; /* make sure it's null-terminated */
+					ldap_value_free( vals );
+				        ldap_msgfree( res );
+					ldap_unbind_s(handle); /* also frees handle */
+				        return auth_canonifyid( buf, 0) ;
+				    }
+				    ldap_value_free( vals );
+			       }			       	
+   	                  }
+			  ldap_msgfree( res );
+                     }
+                }
+		ldap_unbind_s(handle); /* also frees handle */
+           }
+        }
 	if (domain) {
 	    if (config_defdomain && !strcasecmp(config_defdomain, domain+1)) {
 		*domain = '\0'; /* trim the default domain */
@@ -392,7 +448,7 @@ char *canonify_userid(char *user, char *
 		user = buf;
 	    }
 	}
-	else if (config_virtdomains != IMAP_ENUM_VIRTDOMAINS_USERID) {
+	else if (config_virtdomains != IMAP_ENUM_VIRTDOMAINS_USERID && config_virtdomains != IMAP_ENUM_VIRTDOMAINS_LDAP) {
 	    socklen_t salen;
 	    int error;
 	    struct sockaddr_storage localaddr;
diff -r d62bf3b0902d lib/imapoptions
--- a/lib/imapoptions	Thu Oct 25 08:30:57 2007 +0200
+++ b/lib/imapoptions	Thu Oct 25 08:31:06 2007 +0200
@@ -1034,7 +1034,7 @@ are listed with ``<none>''.
    mailbox hierarchy.  The default is to use the netnews separator
    character '.'. */
 
-{ "virtdomains", "off", ENUM("off", "userid", "on") }
+{ "virtdomains", "off", ENUM("off", "userid", "ldap", "on") }
 /* Enable virtual domain support.  If enabled, the user's domain will
    be determined by splitting a fully qualified userid at the last '@'
    or '%' symbol.  If the userid is unqualified, and the virtdomains





More information about the commits mailing list