Commit 35baeb22 35baeb22c0864d1f73c31a36742c0af7a7ad7e22 by Sergey Poznyakoff

Allow to set file permissions of the local mailboxes during creation.

* include/mailutils/stream.h (MU_STREAM_IRGRP, MU_STREAM_IWGRP)
(MU_STREAM_IROTH, MU_STREAM_IWOTH, MU_STREAM_IMASK): New defines.
* include/mailutils/mutil.h (mu_stream_flags_to_mode): New
prototype.
* libproto/maildir/mbox.c (maildir_create, maildir_flush)
(maildir_scan0): Consider mailbox flags	to determine its file
mode.
* mailbox/amd.c (amd_open, amd_message_stream_open): Likewise.
* mailbox/file_stream.c (_file_open): Likewise.
* mailbox/mutil.c (mu_stream_flags_to_mode): New file.

* imap4d/namespace.c (namespace_getfullpath)
(namespace_checkfullpath): Return the namespace number in the last
argument (if not null).
* imap4d/append.c, imap4d/copy.c, imap4d/delete.c, imap4d/list.c,
imap4d/rename.c, imap4d/select.c, imap4d/status.c: Update calls to
namespace_getfullpath.
* imap4d/create.c (imap4d_create): Set mailbox flags depending on
the namespace it is created in.
* imap4d/imap4d.c (mailbox_mode): New variable.
(parse_mode_spec): New function.
(imap4d_cfg_param): New statements other-mailbox-mode and
shared-mailbox-mode.
* imap4d/imap4d.h (mailbox_mode): New proto.
(namespace_getfullpath, namespace_checkfullpath): Add a parameter.

* mailbox/progmailer.c (mu_progmailer_set_debug): Add missing
return statement.
1 parent 1c2596eb
2008-11-07 Sergey Poznyakoff <gray@gnu.org.ua>
Allow to set file permissions of the local mailboxes during
creation.
* include/mailutils/stream.h (MU_STREAM_IRGRP, MU_STREAM_IWGRP)
(MU_STREAM_IROTH, MU_STREAM_IWOTH, MU_STREAM_IMASK): New defines.
* include/mailutils/mutil.h (mu_stream_flags_to_mode): New
prototype.
* libproto/maildir/mbox.c (maildir_create, maildir_flush)
(maildir_scan0): Consider mailbox flags to determine its file
mode.
* mailbox/amd.c (amd_open, amd_message_stream_open): Likewise.
* mailbox/file_stream.c (_file_open): Likewise.
* mailbox/mutil.c (mu_stream_flags_to_mode): New file.
* imap4d/namespace.c (namespace_getfullpath)
(namespace_checkfullpath): Return the namespace number in the last
argument (if not null).
* imap4d/append.c, imap4d/copy.c, imap4d/delete.c, imap4d/list.c,
imap4d/rename.c, imap4d/select.c, imap4d/status.c: Update calls to
namespace_getfullpath.
* imap4d/create.c (imap4d_create): Set mailbox flags depending on
the namespace it is created in.
* imap4d/imap4d.c (mailbox_mode): New variable.
(parse_mode_spec): New function.
(imap4d_cfg_param): New statements other-mailbox-mode and
shared-mailbox-mode.
* imap4d/imap4d.h (mailbox_mode): New proto.
(namespace_getfullpath, namespace_checkfullpath): Add a parameter.
* mailbox/progmailer.c (mu_progmailer_set_debug): Add missing
return statement.
2008-11-05 Sergey Poznyakoff <gray@gnu.org.ua>
Implement forwarding functionality in Maidag.
......
......@@ -182,7 +182,7 @@ imap4d_append (struct imap4d_command *command, imap4d_tokbuf_t tok)
msg_text = imap4d_tokbuf_getarg (tok, i);
mboxname = namespace_getfullpath (mboxname, "/");
mboxname = namespace_getfullpath (mboxname, "/", NULL);
if (!mboxname)
return util_finish (command, RESP_NO, "Couldn't open mailbox");
......
......@@ -68,7 +68,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
int n = 0;
mu_mailbox_t cmbox = NULL;
int arg = IMAP4_ARG_1 + !!isuid;
if (imap4d_tokbuf_argc (tok) != arg + 2)
{
*err_text = "Invalid arguments";
......@@ -87,7 +87,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
return RESP_OK;
}
mailbox_name = namespace_getfullpath (name, delim);
mailbox_name = namespace_getfullpath (name, delim, NULL);
if (!mailbox_name)
{
......
......@@ -21,6 +21,7 @@
#define MKDIR_PERMISSIONS 0700
/* FIXME: take permissions as argument */
static int
mkdir_p (char *name, int delim)
{
......@@ -84,6 +85,7 @@ imap4d_create (struct imap4d_command *command, imap4d_tokbuf_t tok)
char *name;
const char *delim = "/";
int isdir = 0;
int ns;
int rc = RESP_OK;
const char *msg = "Completed";
......@@ -111,7 +113,7 @@ imap4d_create (struct imap4d_command *command, imap4d_tokbuf_t tok)
isdir = 1;
/* Allocates memory. */
name = namespace_getfullpath (name, delim);
name = namespace_getfullpath (name, delim, &ns);
if (!name)
return util_finish (command, RESP_NO, "Cannot create mailbox");
......@@ -139,7 +141,8 @@ imap4d_create (struct imap4d_command *command, imap4d_tokbuf_t tok)
msg = "Cannot create mailbox";
}
else if ((rc = mu_mailbox_open (mbox,
MU_STREAM_RDWR|MU_STREAM_CREAT)))
MU_STREAM_RDWR | MU_STREAM_CREAT
| mailbox_mode[ns])))
{
mu_diag_output (MU_DIAG_ERR,
_("Cannot open mailbox %s: %s"),
......
......@@ -49,7 +49,7 @@ imap4d_delete (struct imap4d_command *command, imap4d_tokbuf_t tok)
return util_finish (command, RESP_NO, "Already exist");
/* Allocates memory. */
name = namespace_getfullpath (name, delim);
name = namespace_getfullpath (name, delim, NULL);
if (!name)
return util_finish (command, RESP_NO, "Cannot remove");
......
......@@ -39,6 +39,8 @@ int create_home_dir; /* Create home directory if it does not
exist */
int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
int mailbox_mode[NS_MAX];
/* Saved command line. */
int imap4d_argc;
char **imap4d_argv;
......@@ -281,7 +283,107 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val)
}
return 0;
}
#define FILE_MODE_READ 0x1
#define FILE_MODE_WRITE 0x2
static int
parse_mode_bits (int *pmode, const char *str, const char **endp)
{
switch (*str)
{
case '+':
case '=':
str++;
break;
default:
*endp = str;
return 1;
}
for (; *str; str++)
{
switch (*str)
{
case 'r':
*pmode |= FILE_MODE_READ;
break;
case 'w':
*pmode |= FILE_MODE_WRITE;
break;
case ',':
*endp = str;
return 0;
default:
*endp = str;
return 1;
}
}
*endp = str;
return 0;
}
static int
parse_mode_spec (int *pmode, const char *str, const char **endp)
{
int mode = 0;
int f;
while (*str)
{
switch (*str)
{
case 'g':
if (parse_mode_bits (&f, str + 1, &str))
{
*endp = str;
return 1;
}
if (f & FILE_MODE_READ)
mode |= MU_STREAM_IRGRP;
if (f & FILE_MODE_WRITE)
mode |= MU_STREAM_IWGRP;
break;
case 'o':
if (parse_mode_bits (&f, str + 1, &str))
{
*endp = str;
return 1;
}
if (f & FILE_MODE_READ)
mode |= MU_STREAM_IROTH;
if (f & FILE_MODE_WRITE)
mode |= MU_STREAM_IWOTH;
break;
default:
*endp = str;
return 1;
}
if (*str == ',')
str++;
}
*pmode = mode;
*endp = str;
return 0;
}
static int
cb_mailbox_mode (mu_debug_t debug, void *data, mu_config_value_t *val)
{
char *p;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (parse_mode_spec ((int *)data, val->v.string, &p))
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("invalid mode string near %s"), p);
return 0;
}
static struct mu_cfg_param imap4d_cfg_param[] = {
{ "other-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_OTHER],
0, NULL,
......@@ -289,6 +391,12 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
{ "shared-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_SHARED],
0, NULL,
N_("Set shared namespace.") },
{ "other-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_OTHER], 0,
cb_mailbox_mode,
N_("File mode for mailboxes in other namespace.") },
{ "shared-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_SHARED], 0,
cb_mailbox_mode,
N_("File mode for mailboxes in shared namespace.") },
{ "login-disabled", mu_cfg_bool, &login_disabled, 0, NULL,
N_("Disable LOGIN command.") },
{ "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL,
......
......@@ -182,6 +182,8 @@ extern int is_virtual;
extern struct mu_auth_data *auth_data;
extern const char *program_version;
extern int mailbox_mode[NS_MAX];
extern int login_disabled;
extern int tls_required;
extern enum imap4d_preauth preauth_mode;
......@@ -281,9 +283,9 @@ extern mu_list_t namespace[NS_MAX];
extern int namespace_init_session (char *path);
extern void namespace_init (void);
extern char * namespace_getfullpath (char *name, const char *delim);
extern char * namespace_checkfullpath (char *name, const char *pattern,
const char *delim);
extern char *namespace_getfullpath (char *name, const char *delim, int *pns);
extern char *namespace_checkfullpath (char *name, const char *pattern,
const char *delim, int *pns);
int imap4d_session_setup (char *username);
int imap4d_session_setup0 (void);
......
......@@ -229,7 +229,7 @@ imap4d_list (struct imap4d_command *command, imap4d_tokbuf_t tok)
}
/* Allocates. */
cwd = namespace_checkfullpath (ref, wcard, delim);
cwd = namespace_checkfullpath (ref, wcard, delim, NULL);
if (!cwd)
{
free (ref);
......
......@@ -166,7 +166,8 @@ risky_pattern (const char *pattern, int delim)
}
char *
namespace_checkfullpath (char *name, const char *pattern, const char *delim)
namespace_checkfullpath (char *name, const char *pattern, const char *delim,
int *nspace)
{
struct namespace_info info;
char *p, *path = NULL;
......@@ -207,6 +208,8 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim)
return NULL;
}
if (nspace)
*nspace = info.ns;
if (scheme)
{
char *pathstr = malloc (strlen (scheme) + strlen (path) + 2);
......@@ -223,12 +226,16 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim)
}
char *
namespace_getfullpath (char *name, const char *delim)
namespace_getfullpath (char *name, const char *delim, int *nspace)
{
if (strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
name = strdup (auth_data->mailbox);
{
name = strdup (auth_data->mailbox);
if (nspace)
*nspace = NS_PRIVATE;
}
else
name = namespace_checkfullpath (name, NULL, delim);
name = namespace_checkfullpath (name, NULL, delim, nspace);
return name;
}
......
......@@ -55,7 +55,7 @@ imap4d_rename (struct imap4d_command *command, imap4d_tokbuf_t tok)
return util_finish (command, RESP_NO, "Name Inbox is reservered");
/* Allocates memory. */
newname = namespace_getfullpath (newname, delim);
newname = namespace_getfullpath (newname, delim, NULL);
if (!newname)
return util_finish (command, RESP_NO, "Permission denied");
......@@ -122,7 +122,7 @@ imap4d_rename (struct imap4d_command *command, imap4d_tokbuf_t tok)
return util_finish (command, RESP_OK, "Already exist");
}
oldname = namespace_getfullpath (oldname, delim);
oldname = namespace_getfullpath (oldname, delim, NULL);
/* It must exist. */
if (!oldname || rename (oldname, newname) != 0)
......
......@@ -57,7 +57,7 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname,
if (strcmp (mboxname, "INBOX") == 0)
flags |= MU_STREAM_CREAT;
mailbox_name = namespace_getfullpath (mboxname, "/");
mailbox_name = namespace_getfullpath (mboxname, "/", NULL);
if (!mailbox_name)
return util_finish (command, RESP_NO, "Couldn't open mailbox");
......
......@@ -82,7 +82,7 @@ imap4d_status (struct imap4d_command *command, imap4d_tokbuf_t tok)
name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
mailbox_name = namespace_getfullpath (name, delim);
mailbox_name = namespace_getfullpath (name, delim, NULL);
if (!mailbox_name)
return util_finish (command, RESP_NO, "Error opening mailbox");
......
......@@ -154,7 +154,10 @@ extern size_t mu_strftime (char *s, size_t max, const char *format,
extern int mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab,
int *perr);
extern int mu_stream_flags_to_mode (int flags);
#ifdef __cplusplus
}
#endif
......
......@@ -40,8 +40,14 @@ extern "C" { /*}*/
#define MU_STREAM_ALLOW_LINKS 0x00000200
#define MU_STREAM_NONLOCK 0x00000400
/* This one affects only mailboxes */
#define MU_STREAM_QACCESS 0x00000800
#define MU_STREAM_QACCESS 0x00000800
#define MU_STREAM_IRGRP 0x00001000
#define MU_STREAM_IWGRP 0x00002000
#define MU_STREAM_IROTH 0x00004000
#define MU_STREAM_IWOTH 0x00008000
#define MU_STREAM_IMASK 0x0000F000
/* Functions useful to users of the pre-defined stream types. */
extern int mu_file_stream_create (mu_stream_t *stream, const char* filename,
......
......@@ -433,7 +433,9 @@ maildir_create (struct _amd_data *amd, int flags)
{
DIR *dir;
char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL);
int rc = maildir_opendir (&dir, tmpname, PERMS);
int rc = maildir_opendir (&dir, tmpname,
PERMS |
mu_stream_flags_to_mode (amd->mailbox->flags));
if (rc)
return rc;
closedir (dir);
......@@ -525,7 +527,8 @@ maildir_flush (struct _amd_data *amd)
struct dirent *entry;
char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL);
rc = maildir_opendir (&dir, tmpname, PERMS);
rc = maildir_opendir (&dir, tmpname,
PERMS | mu_stream_flags_to_mode (amd->mailbox->flags));
if (rc)
{
free (tmpname);
......@@ -664,7 +667,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
/* 2nd phase: Scan and deliver messages from new */
name = maildir_mkfilename (amd->name, NEWSUF, NULL);
status = maildir_opendir (&dir, name, PERMS);
status = maildir_opendir (&dir, name,
PERMS | mu_stream_flags_to_mode (mailbox->flags));
if (status == 0)
{
maildir_deliver_new (amd, dir);
......@@ -674,7 +678,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
name = maildir_mkfilename (amd->name, CURSUF, NULL);
/* 3rd phase: Scan cur/ */
status = maildir_opendir (&dir, name, PERMS);
status = maildir_opendir (&dir, name,
PERMS | mu_stream_flags_to_mode (mailbox->flags));
if (status == 0)
{
status = maildir_scan_dir (amd, dir, CURSUF);
......
......@@ -337,7 +337,8 @@ amd_open (mu_mailbox_t mailbox, int flags)
{
int rc;
if (mkdir (amd->name, S_IRUSR|S_IWUSR|S_IXUSR))
if (mkdir (amd->name,
S_IRUSR|S_IWUSR|S_IXUSR|mu_stream_flags_to_mode (flags)))
return errno;
if (stat (amd->name, &st) < 0)
return errno;
......@@ -1453,6 +1454,7 @@ amd_message_stream_open (struct _amd_message *mhm)
flags |= MU_STREAM_RDWR;
else
flags |= MU_STREAM_READ;
flags |= (amd->mailbox->flags & MU_STREAM_IMASK);
status = mu_file_stream_create (&mhm->stream, filename, flags);
free (filename);
......
......@@ -446,7 +446,7 @@ _file_open (mu_stream_t stream)
const char *mode;
char* filename = 0;
int flags = 0;
if (!fs || !fs->filename)
return EINVAL;
......@@ -487,7 +487,8 @@ _file_open (mu_stream_t stream)
if (errno != ENOENT)
return errno;
/* Race condition here when creating the file ??. */
fd = open (filename, flg|O_CREAT|O_EXCL, 0600);
fd = open (filename, flg|O_CREAT|O_EXCL,
0600 | mu_stream_flags_to_mode (flags));
if (fd < 0)
return errno;
}
......
......@@ -33,8 +33,8 @@
#include <unistd.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/select.h>
......@@ -1490,3 +1490,17 @@ mu_sql_decode_password_type (const char *arg, enum mu_password_type *t)
return 0;
}
int
mu_stream_flags_to_mode (int flags)
{
int mode = 0;
if (flags & MU_STREAM_IRGRP)
mode |= S_IRGRP;
if (flags & MU_STREAM_IWGRP)
mode |= S_IWGRP;
if (flags & MU_STREAM_IROTH)
mode |= S_IROTH;
if (flags & MU_STREAM_IWOTH)
mode |= S_IWOTH;
return mode;
}
......
......@@ -99,6 +99,7 @@ mu_progmailer_set_debug (mu_progmailer_t pm, mu_debug_t debug)
if (!pm)
return EINVAL;
pm->debug = debug;
return 0;
}
void
......