commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-691-g89d93a7


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-691-g89d93a7
Date: Fri, 05 Dec 2014 22:33:14 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=89d93a75c4abec10b9cfe0041eaf654d00f0a0ee

The branch, master has been updated
       via  89d93a75c4abec10b9cfe0041eaf654d00f0a0ee (commit)
      from  6074d4d856c861d0a5df9b39d7421bc186ce2056 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 89d93a75c4abec10b9cfe0041eaf654d00f0a0ee
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 6 00:15:41 2014 +0200

    Fix the use of erad-only maildir folders. Imap4d improvements.
    
    New imap4d statement "retain-groups" instructs it to retain the
    named supplementary user groups when switching to the user
    privileges (previously, imap4d just switched to <user>:mail).
    Read-only mailboxes are handled graciously: SELECT succeeds on
    such mailboxes, bug marks them explicitly as read-only.
    
    * imap4d/imap4d.c (user_retain_groups): New global.
    New config statement "retain-groups".
    (mu_get_user_groups): New function.
    (imap4d_session_setup0): Use mu_switch_to_privs instead of
    just setuid.
    * imap4d/list.c (imap4d_list): Fix handling of
      LIST "" "/path/to/mbox"
    * imap4d/select.c (imap4d_select0): Retry opening in read-only
    mode if failed to open for read-write.
    * libproto/maildir/mbox.c (maildir_mkfilename)
    (mk_info_filename): Change return value and signature. All uses
    changed.
    (maildir_scan0): Don't shuffle messages if mailbox is opened
    read-only.
    * libproto/maildir/folder.c: Update call to maildir_mkfilename.
    * libproto/maildir/maildir.h (maildir_mkfilename): Change
    prototype.

-----------------------------------------------------------------------

Summary of changes:
 imap4d/imap4d.c            |  115 +++++++++++++++++++++++++++++++++-
 imap4d/list.c              |   26 ++++++--
 imap4d/select.c            |    8 ++-
 libproto/maildir/folder.c  |    9 ++-
 libproto/maildir/maildir.h |    4 +-
 libproto/maildir/mbox.c    |  149 +++++++++++++++++++++++++++++--------------
 6 files changed, 249 insertions(+), 62 deletions(-)

diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index 6ce0864..156d407 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -35,6 +35,8 @@ enum tls_mode tls_mode;
 int login_disabled;             /* Disable LOGIN command */
 int create_home_dir;            /* Create home directory if it does not
                                   exist */
+mu_list_t user_retain_groups;
+
 int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
 
 int mailbox_mode[NS_MAX];
@@ -246,7 +248,32 @@ cb_mailbox_mode (void *data, mu_config_value_t *val)
     mu_error (_("invalid mode string near %s"), p);
   return 0;
 }
+
+static int
+cb2_group (const char *gname, void *data)
+{
+  mu_list_t list = data;
+  struct group *group;
+  
+  group = getgrnam (gname);
+  if (!group)
+    mu_error (_("unknown group: %s"), gname);
+  else
+    mu_list_append (list, (void*)group->gr_gid);
+  return 0;
+}
+  
+static int
+cb_group (void *data, mu_config_value_t *arg)
+{
+  mu_list_t *plist = data;
+
+  if (!*plist)
+    mu_list_create (plist);
+  return mu_cfg_string_value_cb (arg, cb2_group, *plist);
+}
 
+
 struct imap4d_srv_config
 {
   struct mu_srv_config m_cfg;
@@ -392,6 +419,9 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
   { "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode,
     N_("File mode for creating user home directories (octal)."),
     N_("mode") },
+  { "retain-groups", mu_cfg_callback, &user_retain_groups, 0, cb_group,
+    N_("Retain these supplementary groups when switching to user privileges"),
+    N_("groups: list of string") },
 #ifdef WITH_TLS
   { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls,
     N_("Kind of TLS encryption to use") },
@@ -424,6 +454,48 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
 };
 
 int
+mu_get_user_groups (const char *user, mu_list_t retain, mu_list_t *pgrouplist)
+{
+  int rc;
+  struct group *gr;
+  mu_list_t list;
+       
+  if (!*pgrouplist)
+    {
+      rc = mu_list_create (pgrouplist);
+      if (rc)
+       {
+         mu_error(_("%s: cannot create list: %s"),
+                  "mu_get_user_groups", mu_strerror (rc));
+         return rc;
+       }
+    }
+
+  list = *pgrouplist;
+  setgrent ();
+  for (rc = 0; rc == 0 && (gr = getgrent ()); )
+    {
+      char **p;
+      for (p = gr->gr_mem; *p; p++)
+       if (strcmp (*p, user) == 0)
+         {
+           if (retain && mu_list_locate (retain, (void*)gr->gr_gid, NULL))
+             continue;
+             
+           /* FIXME: Avoid duplicating gids */
+           rc = mu_list_append (list, (void*)gr->gr_gid);
+           if (rc) 
+             mu_error(_("%s: cannot append to list: %s"),
+                      "mu_get_user_groups",
+                      mu_strerror (rc));
+           break;
+         }
+    }
+  endgrent ();
+  return rc;
+}
+
+int
 imap4d_session_setup0 ()
 {
   if (auth_deny_user_list &&
@@ -502,7 +574,48 @@ imap4d_session_setup0 ()
     }
   
   if (auth_data->change_uid)
-    setuid (auth_data->uid);
+    {
+      struct group *gr;
+      mu_list_t groups = NULL;
+      int rc;
+      uid_t uid;
+
+      uid = getuid ();
+      if (uid != auth_data->uid)
+       {
+         rc = mu_list_create (&groups);
+         if (rc)
+           {
+             mu_error(_("cannot create list: %s"), mu_strerror (rc));
+             free (imap4d_homedir);
+             free (real_homedir);
+             return 1;
+           }
+         mu_list_append (groups, (void*)auth_data->gid);
+
+         rc = mu_get_user_groups (auth_data->name, user_retain_groups,
+                                  &groups);
+         if (rc)
+           {
+             /* FIXME: When mu_get_user_groups goes to the library, add a
+                diag message here */
+             free (imap4d_homedir);
+             free (real_homedir);
+             return 1;
+           }
+         gr = getgrnam ("mail");
+         rc = mu_switch_to_privs (auth_data->uid, gr->gr_gid, groups);
+         mu_list_destroy (&groups);
+         if (rc)
+           {
+             mu_error (_("can't switch to user %s privileges: %s"),
+                       auth_data->name, mu_strerror (rc));
+             free (imap4d_homedir);
+             free (real_homedir);
+             return 1;
+           }
+       }
+    }
 
   util_chdir (imap4d_homedir);
   namespace_init_session (imap4d_homedir);
diff --git a/imap4d/list.c b/imap4d/list.c
index bbb7730..50c672d 100644
--- a/imap4d/list.c
+++ b/imap4d/list.c
@@ -157,9 +157,10 @@ imap4d_list (struct imap4d_session *session,
                              "LIST (\\NoSelect) \"%c\" \"\"",
                              MU_HIERARCHY_DELIMITER);
     }
+  
   /* There is only one mailbox in the "INBOX" hierarchy ... INBOX.  */
   else if (mu_c_strcasecmp (ref, "INBOX") == 0
-          || (ref[0] == 0 && mu_c_strcasecmp (wcard, "INBOX") == 0))
+      || (ref[0] == 0 && mu_c_strcasecmp (wcard, "INBOX") == 0))
     {
       io_untagged_response (RESP_NONE, "LIST (\\NoInferiors) NIL INBOX");
     }
@@ -168,8 +169,8 @@ imap4d_list (struct imap4d_session *session,
       int status;
       mu_folder_t folder;
       char *cwd;
-      char *p, *q;
       struct refinfo refinfo;
+      size_t seglen;
       
       switch (*wcard)
        {
@@ -209,12 +210,10 @@ imap4d_list (struct imap4d_session *session,
       /* Move any directory not containing a wildcard into the reference
         So (ref = ~guest, wcard = Mail/folder1/%.vf) -->
         (ref = ~guest/Mail/folder1, wcard = %.vf).  */
-      for (p = wcard; (q = strpbrk (p, "/%*")) && *q == '/'; p = q + 1)
-       ;
+      seglen = strcspn (wcard, "%*");
 
-      if (p > wcard)
+      if (seglen)
        {
-         size_t seglen = p - wcard;
          size_t reflen = strlen (ref);
          int addslash = (reflen > 0 && ref[reflen-1] != '/'); 
          size_t len = seglen + reflen + addslash + 1;
@@ -235,6 +234,21 @@ imap4d_list (struct imap4d_session *session,
          return io_completion_response (command, RESP_NO,
                                      "The requested item could not be found.");
        }
+
+      /* FIXME */
+      if (wcard[0] == 0)
+       {
+         char *p = strrchr (ref, '/');
+         if (p && p[1])
+           {
+             *p++ = 0;
+             wcard = p;
+
+             p = strrchr (cwd, '/');
+             *p = 0;
+           }
+       }
+
       status = mu_folder_create (&folder, cwd);
       if (status)
        {
diff --git a/imap4d/select.c b/imap4d/select.c
index 1283d4f..0d68dd2 100644
--- a/imap4d/select.c
+++ b/imap4d/select.c
@@ -64,13 +64,17 @@ imap4d_select0 (struct imap4d_command *command, const char 
*mboxname,
   if (!mailbox_name)
     return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
 
-  if (flags & MU_STREAM_RDWR)
+  if (flags & MU_STREAM_WRITE)
     {
       status = manlock_open_mailbox (&mbox, mailbox_name, 1, flags);
+      if (status)
+       flags &= ~MU_STREAM_WRITE;
     }
-  else
+
+  if (!(flags & MU_STREAM_WRITE))
     {
       status = mu_mailbox_create_default (&mbox, mailbox_name);
+
       if (status)
        mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_default",
                         mailbox_name,
diff --git a/libproto/maildir/folder.c b/libproto/maildir/folder.c
index 4fd96d8..6471a02 100644
--- a/libproto/maildir/folder.c
+++ b/libproto/maildir/folder.c
@@ -40,8 +40,13 @@ static int
 dir_exists (const char *name, const char *suf)
 {
   struct stat st;
-  char *s = maildir_mkfilename (name, suf, NULL);
-      
+  int rc;
+  char *s;
+
+  rc = maildir_mkfilename (name, suf, NULL, &s);
+  if (rc)
+    return 0;/* FIXME: error message */
+  
   if (stat (s, &st) < 0)
     return 0;
 
diff --git a/libproto/maildir/maildir.h b/libproto/maildir/maildir.h
index db22049..d338d44 100644
--- a/libproto/maildir/maildir.h
+++ b/libproto/maildir/maildir.h
@@ -21,5 +21,5 @@
 #define CURSUF "cur"
 #define NEWSUF "new"
 
-extern char *maildir_mkfilename (const char *dir, const char *suffix,
-                                const char *name);
+int maildir_mkfilename (const char *dir, const char *suffix,
+                       const char *name, char **retname);
diff --git a/libproto/maildir/mbox.c b/libproto/maildir/mbox.c
index 9773143..58ab3a4 100644
--- a/libproto/maildir/mbox.c
+++ b/libproto/maildir/mbox.c
@@ -68,6 +68,7 @@
 #include <mailutils/sys/mailbox.h>
 #include <mailutils/sys/registrar.h>
 #include <mailutils/sys/amd.h>
+#include <mailutils/io.h>
 #include <maildir.h>
 
 #ifndef PATH_MAX 
@@ -237,8 +238,9 @@ read_random (void *buf, size_t size)
   return rc != size;
 }
 
-char *
-maildir_mkfilename (const char *directory, const char *suffix, const char 
*name)
+int
+maildir_mkfilename (const char *directory, const char *suffix, const char 
*name,
+                   char **ret_name)
 {
   size_t size = strlen (directory) + 1 + strlen (suffix) + 1;
   char *tmp;
@@ -247,22 +249,25 @@ maildir_mkfilename (const char *directory, const char 
*suffix, const char *name)
     size += 1 + strlen (name);
   
   tmp = malloc (size);
+  if (!tmp)
+    return errno;
   sprintf (tmp, "%s/%s", directory, suffix);
   if (name)
     {
       strcat (tmp, "/");
       strcat (tmp, name);
     }
-  return tmp;
+  *ret_name = tmp;
+  return 0;
 }
 
-static char *
-mk_info_filename (char *directory, char *suffix, char *name, int flags)
+static int
+mk_info_filename (char *directory, char *suffix, char *name, int flags,
+                 char **ret_name)
 {
   char fbuf[info_map_size + 1];
   char *tmp;
   int namelen;
-  size_t size;
 
   tmp = strchr (name, ':');
   if (!tmp)
@@ -270,16 +275,10 @@ mk_info_filename (char *directory, char *suffix, char 
*name, int flags)
   else
     namelen = tmp - name;
 
-  size = strlen (directory)
-          + 1 + strlen (suffix)
-          + 1 + namelen + 1;
-
   flags_to_info (flags, fbuf);
-  size += 3 + strlen (fbuf);
 
-  tmp = malloc (size);
-  sprintf (tmp, "%s/%s/%*.*s:2,%s", directory, suffix, namelen, namelen, name, 
fbuf);
-  return tmp;
+  return mu_asprintf (ret_name, "%s/%s/%*.*s:2,%s",
+                     directory, suffix, namelen, namelen, name, fbuf);
 }
 
 char *
@@ -335,8 +334,7 @@ static int
 maildir_cur_message_name (struct _amd_message *amsg, char **pname)
 {
   struct _maildir_message *msg = (struct _maildir_message *) amsg;
-  *pname = maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name);
-  return 0;
+  return maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name, pname);
 }
 
 static int
@@ -350,9 +348,11 @@ maildir_new_message_name (struct _amd_message *amsg, int 
flags, int expunge,
       *pname = NULL;
     }
   else if (strcmp (msg->dir, CURSUF) == 0)
-    *pname = mk_info_filename (amsg->amd->name, CURSUF, msg->file_name, flags);
+    return mk_info_filename (amsg->amd->name, CURSUF, msg->file_name, flags,
+                            pname);
   else
-    *pname = maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name);
+    return maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name,
+                              pname);
   return 0;
 }
 
@@ -388,7 +388,16 @@ static void
 maildir_delete_file (char *dirname, char *filename)
 {
   struct stat st;
-  char *name = maildir_mkfilename (dirname, filename, NULL);
+  char *name;
+  int rc;
+  
+  rc = maildir_mkfilename (dirname, filename, NULL, &name);
+  if (rc)
+    {
+      mu_error ("maildir: failed to create file name: %s",
+               mu_strerror (errno));
+      return;
+    }
 
   if (stat (name, &st) == 0)
     {
@@ -429,15 +438,21 @@ maildir_create (struct _amd_data *amd, int flags)
   for (i = 0; i < 3; i++)
     {
       DIR *dir;
-      char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL);
-      int rc = maildir_opendir (&dir, tmpname,
-                               PERMS |
-                               mu_stream_flags_to_mode (amd->mailbox->flags,
-                                                        1));
+      int rc;
+      char *tmpname;
+
+      rc = maildir_mkfilename (amd->name, dirs[i], NULL, &tmpname);
       if (rc)
        return rc;
-      closedir (dir);
+      
+      rc = maildir_opendir (&dir, tmpname,
+                           PERMS |
+                           mu_stream_flags_to_mode (amd->mailbox->flags,
+                                                    1));
       free (tmpname);
+      if (rc)
+       return rc;
+      closedir (dir);
     }
   return 0;
 }
@@ -454,10 +469,16 @@ maildir_msg_init (struct _amd_data *amd, struct 
_amd_message *amm)
   char *name, *fname;
   struct stat st;
   int i;
+  int rc;
   
   name = maildir_uniq (amd, -1);
-  fname = maildir_mkfilename (amd->name, NEWSUF, name);
-
+  rc = maildir_mkfilename (amd->name, NEWSUF, name, &fname);
+  if (rc)
+    {
+      free (name);
+      return rc;
+    }
+  
   msg->dir = TMPSUF;
   
   for (i = 0; i < NTRIES; i++)
@@ -483,35 +504,41 @@ maildir_msg_finish_delivery (struct _amd_data *amd, 
struct _amd_message *amm,
                             const mu_message_t orig_msg)
 {
   struct _maildir_message *msg = (struct _maildir_message *) amm;
-  char *oldname = maildir_mkfilename (amd->name, TMPSUF, msg->file_name);
-  char *newname;
+  char *oldname, *newname;
   mu_attribute_t attr;
   int flags;
+  int rc;
+  
+  rc = maildir_mkfilename (amd->name, TMPSUF, msg->file_name, &oldname);
+  if (rc)
+    return rc;
   
   if (mu_message_get_attribute (orig_msg, &attr) == 0
       && mu_attribute_is_read (attr)
       && mu_attribute_get_flags (attr, &flags) == 0)
     {
       msg->dir = CURSUF;
-      newname = mk_info_filename (amd->name, CURSUF, msg->file_name, flags);
+      rc = mk_info_filename (amd->name, CURSUF, msg->file_name, flags,
+                            &newname);
     }
   else
     {
       msg->dir = NEWSUF;
-      newname = maildir_mkfilename (amd->name, NEWSUF, msg->file_name);
+      rc = maildir_mkfilename (amd->name, NEWSUF, msg->file_name, &newname);
     }
-    
-  unlink (newname);
-  if (link (oldname, newname) == 0)
-    unlink (oldname);
-  else
+
+  if (rc == 0)
     {
-      return errno; /* FIXME? */
+      unlink (newname);
+      if (link (oldname, newname) == 0)
+       unlink (oldname);
+      else
+       rc = errno; /* FIXME? */
     }
-
+  
   free (oldname);
   free (newname);
-  return 0;
+  return rc;
 }
 
 
@@ -523,7 +550,11 @@ maildir_flush (struct _amd_data *amd)
   int rc;
   DIR *dir;
   struct dirent *entry;
-  char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL);
+  char *tmpname;
+
+  rc = maildir_mkfilename (amd->name, TMPSUF, NULL, &tmpname);
+  if (rc)
+    return rc;
 
   rc = maildir_opendir (&dir, tmpname,
                        PERMS |
@@ -561,16 +592,24 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir)
   while ((entry = readdir (dir)))
     {
       char *oldname, *newname;
-       
+      int rc;
+      
       switch (entry->d_name[0])
        {
        case '.':
          break;
 
        default:
-         oldname = maildir_mkfilename (amd->name, NEWSUF, entry->d_name);
-         newname = mk_info_filename (amd->name, CURSUF, entry->d_name, 0);
-         rename (oldname, newname);
+         rc = maildir_mkfilename (amd->name, NEWSUF, entry->d_name, &oldname);
+         if (rc)
+           return rc;
+         rc = mk_info_filename (amd->name, CURSUF, entry->d_name, 0, &newname);
+         if (rc)
+           {
+             free (oldname);
+             return rc;
+           }
+         rename (oldname, newname); /* FIXME: Error code? */
          free (oldname);
          free (newname);
        }
@@ -654,19 +693,27 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno 
MU_ARG_UNUSED,
   maildir_flush (amd);
 
   /* 2nd phase: Scan and deliver messages from new */
-  name = maildir_mkfilename (amd->name, NEWSUF, NULL);
-
+  status = maildir_mkfilename (amd->name, NEWSUF, NULL, &name);
+  if (status)
+    return status;
+  
   status = maildir_opendir (&dir, name,
                            PERMS |
                            mu_stream_flags_to_mode (mailbox->flags, 1));
   if (status == 0)
     {
-      maildir_deliver_new (amd, dir);
+      if (mailbox->flags & MU_STREAM_WRITE)
+       maildir_deliver_new (amd, dir);
+      else
+       status = maildir_scan_dir (amd, dir, NEWSUF);
       closedir (dir);
     }
   free (name);
 
-  name = maildir_mkfilename (amd->name, CURSUF, NULL);
+  status = maildir_mkfilename (amd->name, CURSUF, NULL, &name);
+  if (status)
+    return status;
+  
   /* 3rd phase: Scan cur/ */
   status = maildir_opendir (&dir, name,
                            PERMS |
@@ -746,7 +793,11 @@ maildir_remove (struct _amd_data *amd)
 
   for (i = 0; rc == 0 && i < 3; i++)
     {
-      char *name = maildir_mkfilename (amd->name, suf[i], NULL);
+      char *name;
+
+      rc = maildir_mkfilename (amd->name, suf[i], NULL, &name);
+      if (rc)
+       return rc;
       rc = amd_remove_dir (name);
       if (rc)
        mu_diag_output (MU_DIAG_WARNING,


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]