gunnar: server/patches/cyrus-imapd/cyrus-imapd-2.3.11 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
Tue Dec 11 11:34:52 CET 2007


Author: gunnar

Update of /kolabrepository/server/patches/cyrus-imapd/cyrus-imapd-2.3.11
In directory doto:/tmp/cvs-serv15983/cyrus-imapd-2.3.11

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:
cyrus-imapd-2.3.11 has been released upstream. Patches updated and patch directory restructured according to kolab-devel discussion.

--- 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 2007/12/11 10:34:48 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 a83b43bb79a3 imap/mboxname.c
--- a/imap/mboxname.c	Tue Dec 11 11:22:14 2007 +0100
+++ b/imap/mboxname.c	Tue Dec 11 11:22:22 2007 +0100
@@ -712,8 +712,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 5f6f7a246f32 lib/auth_unix.c
--- a/lib/auth_unix.c	Tue Dec 11 11:20:37 2007 +0100
+++ b/lib/auth_unix.c	Tue Dec 11 11:22:01 2007 +0100
@@ -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"
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+/*
+ * __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 = 10;
 #else
     char **mem;
+    FILE *groupfile;
 #endif
 
     identifier = mycanonifyid(identifier, 0);
@@ -283,20 +424,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 6162fc947b22 imap/append.c
--- a/imap/append.c	Tue Dec 11 11:22:03 2007 +0100
+++ b/imap/append.c	Tue Dec 11 11:22:13 2007 +0100
@@ -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 6162fc947b22 imap/imapd.c
--- a/imap/imapd.c	Tue Dec 11 11:22:03 2007 +0100
+++ b/imap/imapd.c	Tue Dec 11 11:22:13 2007 +0100
@@ -3509,17 +3509,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 6162fc947b22 imap/mailbox.c
--- a/imap/mailbox.c	Tue Dec 11 11:22:03 2007 +0100
+++ b/imap/mailbox.c	Tue Dec 11 11:22:13 2007 +0100
@@ -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