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 <g...@gnu.org.ua> 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 _______________________________________________ Commit-mailutils mailing list Commit-mailutils@gnu.org https://lists.gnu.org/mailman/listinfo/commit-mailutils