summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraaron <aaron@7b491191-dbf0-0310-aff6-d879d4d69008>2006-08-14 17:46:47 +0000
committeraaron <aaron@7b491191-dbf0-0310-aff6-d879d4d69008>2006-08-14 17:46:47 +0000
commit5065b5c0d78990db6e30fdaac750ee1ec498edf6 (patch)
treeec4f1564648487f3fd7c6724dfe7f248a90b6306
parentb7cc57dade6c9cc541739add39ec532214ef8f42 (diff)
* dbmailtypes.h, db.h, db.c:
Added source argument to the db_create_mailbox_with_parents function to determine if permission checks should be skipped or not. * main.c, man/dbmail-smtp.txt: Added -M flag, like -m, but skip all permission checks and Sieve scripts (closes bug #391 and bug #393). * imapcommands.c, sort.c: Updated calls to the lower level mailbox creation and delivery functions with the additional source arguments. * debug.h, debug.c: Added argument to the newtrace function to know if it was called from the trace or TRACE macro. git-svn-id: https://svn.ic-s.nl/svn/dbmail/trunk/dbmail@2224 7b491191-dbf0-0310-aff6-d879d4d69008
-rw-r--r--ChangeLog15
-rw-r--r--db.c31
-rw-r--r--db.h5
-rw-r--r--dbmailtypes.h1
-rw-r--r--debug.c30
-rw-r--r--debug.h8
-rw-r--r--imapcommands.c2
-rw-r--r--main.c27
-rw-r--r--man/dbmail-smtp.txt11
-rw-r--r--sort.c95
10 files changed, 145 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index 2c85b6a8..bf179ef7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-08-14 Aaron Stone <aaron@serendipity.cx>
+
+ * dbmailtypes.h, db.h, db.c:
+ Added source argument to the db_create_mailbox_with_parents function
+ to determine if permission checks should be skipped or not.
+ * main.c, man/dbmail-smtp.txt:
+ Added -M flag, like -m, but skip all permission checks and Sieve
+ scripts (closes bug #391 and bug #393).
+ * imapcommands.c, sort.c:
+ Updated calls to the lower level mailbox creation and delivery
+ functions with the additional source arguments.
+ * debug.h, debug.c:
+ Added argument to the newtrace function to know if it was called from
+ the trace or TRACE macro.
+
2006-08-13 Aaron Stone <aaron@serendipity.cx>
* export.c:
diff --git a/db.c b/db.c
index 13232850..047f20f5 100644
--- a/db.c
+++ b/db.c
@@ -2919,8 +2919,8 @@ egeneral:
* DM_EGENERAL Cannot create mailbox
* DM_EQUERY Database error
*/
-int db_mailbox_create_with_parents(const char * mailbox, u64_t owner_idnr,
- u64_t * mailbox_idnr, const char * * message)
+int db_mailbox_create_with_parents(const char * mailbox, mailbox_source_t source,
+ u64_t owner_idnr, u64_t * mailbox_idnr, const char * * message)
{
int parent_right_to_create = -1;
int other_namespace = 0;
@@ -2932,37 +2932,31 @@ int db_mailbox_create_with_parents(const char * mailbox, u64_t owner_idnr,
assert(mailbox);
assert(mailbox_idnr);
assert(message);
+
+ TRACE(TRACE_INFO, "Creating mailbox [%s] source [%d] for user [%llu]",
+ mailbox, source, owner_idnr);
/* check if new name is valid */
if (!checkmailboxname(mailbox)) {
*message = "New mailbox name contains invalid characters";
+ TRACE(TRACE_MESSAGE, "New mailbox name contains invalid characters. Aborting create.");
return DM_EGENERAL;
}
/* There used to be a removal of slashes here. Why? */
if (db_findmailbox(mailbox, owner_idnr, mailbox_idnr) == 1) {
*message = "Mailbox already exists";
+ TRACE(TRACE_ERROR, "Asked to create mailbox which already exists. Aborting create.");
return DM_EGENERAL;
}
if (db_imap_split_mailbox(mailbox, owner_idnr,
&mailboxes, message) != DM_SUCCESS) {
- // Message was set by the function.
+ TRACE(TRACE_ERROR, "Negative return code from db_imap_split_mailbox.");
+ // Message pointer was set by the function.
return DM_EGENERAL;
}
- /* FIXME: Change these to TRACE calls.
- printf("\n");
- GList *mailboxes_temp;
- mailboxes_temp = g_list_first(mailboxes);
- while (mailboxes_temp) {
- mailbox_t *mbox = (mailbox_t *)mailboxes_temp->data;
- printf("%s\n", mbox->name);
- mailboxes_temp = g_list_next(mailboxes_temp);
- }
- printf("\n");
- */
-
mailboxes = g_list_first(mailboxes);
while (mailboxes) {
mailbox_t *mbox = (mailbox_t *)mailboxes->data;
@@ -3006,6 +3000,10 @@ int db_mailbox_create_with_parents(const char * mailbox, u64_t owner_idnr,
skip_and_free = DM_EGENERAL;
}
+ } else if (source == BOX_BRUTEFORCE) {
+ TRACE(TRACE_INFO, "Mailbox requested with BRUTEFORCE creation status; "
+ "pretending that all permissions have been granted to create it.");
+ parent_right_to_create = 1;
} else {
/* Mailbox does exist, failure if no_inferiors flag set. */
if ( ((result = db_noinferiors(mbox->uid)) == DM_EGENERAL) ) {
@@ -3138,10 +3136,11 @@ int db_find_create_mailbox(const char *name, mailbox_source_t source,
if (db_findmailbox(name, owner_idnr, &mboxidnr) != 1) {
/* Who specified this mailbox? */
if (source == BOX_COMMANDLINE
+ || source == BOX_BRUTEFORCE
|| source == BOX_SORTING
|| source == BOX_DEFAULT) {
/* Did we fail to create the mailbox? */
- if (db_mailbox_create_with_parents(name, owner_idnr, &mboxidnr, &message) != DM_SUCCESS) {
+ if (db_mailbox_create_with_parents(name, source, owner_idnr, &mboxidnr, &message) != DM_SUCCESS) {
TRACE(TRACE_ERROR, "could not create mailbox [%s] because [%s]",
name, message);
return DM_EQUERY;
diff --git a/db.h b/db.h
index ad27e1e7..6a4ad996 100644
--- a/db.h
+++ b/db.h
@@ -982,6 +982,7 @@ int db_createmailbox(const char *name, u64_t owner_idnr,
/**
* \brief Create a mailbox, recursively creating its parents.
* \param mailbox Name of the mailbox to create
+ * \param source Upstream source of this mailbox spec
* \param owner_idnr Owner of the mailbox
* \param mailbox_idnr Fills the pointer with the mailbox id
* \param message Fills the pointer with a static pointer to a message
@@ -990,8 +991,8 @@ int db_createmailbox(const char *name, u64_t owner_idnr,
* - 1 on failure
* - -1 on error
*/
-int db_mailbox_create_with_parents(const char * mailbox, u64_t owner_idnr,
- u64_t * mailbox_idnr, const char * * message);
+int db_mailbox_create_with_parents(const char * mailbox, mailbox_source_t source,
+ u64_t owner_idnr, u64_t * mailbox_idnr, const char * * message);
/**
* \brief Splits a mailbox name into pieces on '/'
diff --git a/dbmailtypes.h b/dbmailtypes.h
index 3dd7a48d..10377c0a 100644
--- a/dbmailtypes.h
+++ b/dbmailtypes.h
@@ -428,6 +428,7 @@ typedef enum {
BOX_NONE, /* No mailbox yet. */
BOX_UNKNOWN, /* Not gonna create. */
BOX_ADDRESSPART, /* Not gonna create. */
+ BOX_BRUTEFORCE, /* Autocreate, no perms checks and skip Sieve scripts. */
BOX_COMMANDLINE, /* Autocreate. */
BOX_SORTING, /* Autocreate. */
BOX_DEFAULT /* Autocreate. */
diff --git a/debug.c b/debug.c
index 5fbd54cf..239e0bd4 100644
--- a/debug.c
+++ b/debug.c
@@ -71,7 +71,7 @@ static const char * trace_to_text(trace_t level)
*
*/
-void newtrace(trace_t level, const char * module,
+void newtrace(int isnew, trace_t level, const char * module,
const char * file, const char * function,
char *formatstring, ...)
{
@@ -82,8 +82,8 @@ void newtrace(trace_t level, const char * module,
va_start(argp, formatstring);
- /* TODO: make use of the module, file, function arguments.
- if (TRACE_SYSLOG >= 5) {
+ /*
+ if (isnew && TRACE_SYSLOG >= 5) {
// If the global trace level is really high
formatstring_verbose = g_strdup_printf("from %s, %s, %s: %s",
module, file, function, formatstring);
@@ -100,7 +100,12 @@ void newtrace(trace_t level, const char * module,
l = strlen(message);
if (level <= TRACE_STDERR) {
- fprintf(stderr, "%s %s", trace_to_text(level), message);
+ if (isnew) {
+ // FIXME: Add file, function, etc.
+ fprintf(stderr, "%s %s", trace_to_text(level), message);
+ } else {
+ fprintf(stderr, "%s %s", trace_to_text(level), message);
+ }
if (message[l] != '\n')
fprintf(stderr, "\n");
fflush(stderr);
@@ -111,9 +116,20 @@ void newtrace(trace_t level, const char * module,
message[l] = '\0';
if (level <= TRACE_WARNING) {
/* set LOG_ALERT at warnings */
- syslog(LOG_ALERT, "%s %s", trace_to_text(level), message);
- } else
- syslog(LOG_NOTICE, "%s %s", trace_to_text(level), message);
+ if (isnew) {
+ // FIXME: Add file, function, etc.
+ syslog(LOG_ALERT, "%s %s", trace_to_text(level), message);
+ } else {
+ syslog(LOG_ALERT, "%s %s", trace_to_text(level), message);
+ }
+ } else {
+ if (isnew) {
+ // FIXME: Add file, function, etc.
+ syslog(LOG_NOTICE, "%s %s", trace_to_text(level), message);
+ } else {
+ syslog(LOG_NOTICE, "%s %s", trace_to_text(level), message);
+ }
+ }
}
g_free(message);
diff --git a/debug.h b/debug.h
index e87b2462..7ce30953 100644
--- a/debug.h
+++ b/debug.h
@@ -77,11 +77,11 @@ typedef enum {
void func_memtst(const char *filename, int line, int tst);
-#define trace(level, fmt...) newtrace(level, "", "", "", fmt)
-#define TRACE(level, fmt...) newtrace(level, THIS_MODULE, __FILE__, __func__, fmt)
-void newtrace(trace_t level, const char * module,
+#define trace(level, fmt...) newtrace(0, level, "", "", "", fmt)
+#define TRACE(level, fmt...) newtrace(1, level, THIS_MODULE, __FILE__, __func__, fmt)
+void newtrace(int isnew, trace_t level, const char * module,
const char * file, const char * function,
- char *formatstring, ...) PRINTF_ARGS(5, 6);
+ char *formatstring, ...) PRINTF_ARGS(6, 7);
void configure_debug(trace_t trace_syslog, trace_t trace_stderr);
diff --git a/imapcommands.c b/imapcommands.c
index 96e6a293..c33b09f6 100644
--- a/imapcommands.c
+++ b/imapcommands.c
@@ -331,7 +331,7 @@ int _ic_create(struct ImapSession *self)
return 1;
/* Create the mailbox and its parents. */
- result = db_mailbox_create_with_parents(self->args[0], ud->userid, &mboxid, &message);
+ result = db_mailbox_create_with_parents(self->args[0], BOX_COMMANDLINE, ud->userid, &mboxid, &message);
if (result > 0) {
dbmail_imap_session_printf(self, "%s NO %s\r\n", self->tag, message);
diff --git a/main.c b/main.c
index 3f3148df..445cf405 100644
--- a/main.c
+++ b/main.c
@@ -23,6 +23,7 @@
* main file for dbmail-smtp */
#include "dbmail.h"
+#define THIS_MODULE "smtp"
#define MESSAGEIDSIZE 100
#define NORMAL_DELIVERY 1
@@ -47,6 +48,7 @@ extern db_param_t _db_params; /* set up database login data */
deliver_to_user_t dsnuser;
//char *header = NULL;
+int brute_force = 0;
char *deliver_to_header = NULL;
char *deliver_to_mailbox = NULL;
@@ -61,7 +63,8 @@ int do_showhelp(void) {
printf(" -t [headerfield] for normal deliveries (default is \"delivered-to\")\n");
printf(" -d [addresses] for delivery without using scanner\n");
printf(" -u [usernames] for direct delivery to users\n");
- printf(" -m \"mailbox\" for delivery to a specific mailbox\n");
+ printf(" -m \"mailbox\" for delivery to a specific mailbox\n");
+ printf(" -M \"mailbox\" as -m, but skip permissions checks and Sieve scripts\n");
printf(" -r return path for address of bounces and other error reports\n");
printf("\nCommon options for all DBMail utilities:\n");
@@ -97,7 +100,7 @@ int main(int argc, char *argv[])
* with an immediately preceding option are return with option
* value '1'. We will use this to allow for multiple values to
* follow after each of the supported options. */
- while ((c = getopt(argc, argv, "-t::m:u:d:r: f:qnyvVh")) != EOF) {
+ while ((c = getopt(argc, argv, "-t::m:M:u:d:r: f:qnyvVh")) != EOF) {
/* Received an n-th value following the last option,
* so recall the last known option to be used in the switch. */
if (c == 1)
@@ -121,6 +124,15 @@ int main(int argc, char *argv[])
break;
+ case 'M':
+ TRACE(TRACE_INFO, "using BRUTE FORCE delivery");
+
+ if (brute_force) {
+ printf("Only one mailbox name may be specified.\n");
+ usage_error = 1;
+ } else
+ brute_force = 1;
+ /* Fall through. */
case 'm':
trace(TRACE_INFO, "%s,%s: using SPECIAL_DELIVERY to mailbox", __FILE__, __func__);
@@ -310,7 +322,11 @@ int main(int argc, char *argv[])
/* Loop through the dsnusers list, setting the destination mailbox. */
for (tmp = dm_list_getstart(&dsnusers); tmp != NULL; tmp = tmp->nextnode) {
((deliver_to_user_t *)tmp->data)->mailbox = dm_strdup(deliver_to_mailbox);
- ((deliver_to_user_t *)tmp->data)->source = BOX_COMMANDLINE;
+ if (brute_force) {
+ ((deliver_to_user_t *)tmp->data)->source = BOX_BRUTEFORCE;
+ } else {
+ ((deliver_to_user_t *)tmp->data)->source = BOX_COMMANDLINE;
+ }
}
}
@@ -365,7 +381,7 @@ int main(int argc, char *argv[])
g_list_foreach(userlist, (GFunc)g_free, NULL);
g_list_free(userlist);
- trace(TRACE_DEBUG, "%s,%s: they're all free. we're done.", __FILE__, __func__);
+ TRACE(TRACE_DEBUG, "they're all free. we're done.");
db_disconnect();
auth_disconnect();
@@ -373,6 +389,7 @@ int main(int argc, char *argv[])
g_mime_shutdown();
- trace(TRACE_DEBUG, "%s,%s: exit code is [%d].", __FILE__, __func__, exitcode);
+ TRACE(TRACE_DEBUG, "exit code is [%d].", exitcode);
return exitcode;
}
+
diff --git a/man/dbmail-smtp.txt b/man/dbmail-smtp.txt
index 5cbe4cca..165b431d 100644
--- a/man/dbmail-smtp.txt
+++ b/man/dbmail-smtp.txt
@@ -8,7 +8,7 @@ dbmail-smtp - inserts messages into the DBMail mailsystem.
SYNOPSIS
--------
-dbmail-smtp [-t headerfield] [-d addresses] [-u usernames] [-m mailboxname]
+dbmail-smtp [-t headerfield] [-d addresses] [-u usernames] [-m|-M mailboxname]
[-r return path] [-f configFile]
DESCRIPTION
@@ -35,7 +35,14 @@ OPTIONS
-m mailboxname::
Deliver messages to mailbox mailboxname of the recipient. If
- this mailbox does not exist yet, it is created.
+ this mailbox does not exist yet, it is created. Sieve scripts
+ will be run normally, possibly altering the destination mailbox.
+
+-M mailboxname::
+ Deliver messages to mailbox mailboxname of the recipient. If
+ this mailbox does not exist yet, it is created. Sieve scripts
+ are not run. Permission checks are not performed for mailbox creation
+ or message delivery.
-r returnpath::
Set return path for bounces and other error reports to return path.
diff --git a/sort.c b/sort.c
index 13416bb8..0ae508d7 100644
--- a/sort.c
+++ b/sort.c
@@ -24,7 +24,16 @@ dsn_class_t sort_and_deliver(struct DbmailMessage *message,
dsn_class_t ret;
field_t val;
- TRACE(TRACE_INFO, "destination [%s] useridnr [%llu], mailbox [%s], source [%d]",
+ /* Catch the brute force delivery right away.
+ * We skip the Sieve scripts, and down the call
+ * chain we don't check permissions on the mailbox. */
+ if (source == BOX_BRUTEFORCE) {
+ TRACE(TRACE_MESSAGE, "Beginning brute force delivery for user [%llu] to mailbox [%s].",
+ useridnr, mailbox);
+ return sort_deliver_to_mailbox(message, useridnr, mailbox, source, NULL);
+ }
+
+ TRACE(TRACE_INFO, "Destination [%s] useridnr [%llu], mailbox [%s], source [%d]",
destination, useridnr, mailbox, source);
/* This is the only condition when called from pipe.c, actually. */
@@ -45,8 +54,7 @@ dsn_class_t sort_and_deliver(struct DbmailMessage *message,
// FIXME: I forget who frees the mailbox.
mailbox = subaddress;
source = BOX_ADDRESSPART;
- trace(TRACE_INFO, "%s, %s: Setting BOX_ADDRESSPART mailbox to [%s]",
- __FILE__, __func__, mailbox);
+ TRACE(TRACE_INFO, "Setting BOX_ADDRESSPART mailbox to [%s]", mailbox);
}
}
@@ -57,8 +65,7 @@ dsn_class_t sort_and_deliver(struct DbmailMessage *message,
config_get_value("SIEVE", "DELIVERY", val);
if (strcasecmp(val, "yes") == 0
&& db_check_sievescript_active(useridnr) == 0) {
- trace(TRACE_INFO, "%s, %s: Calling for a Sieve sort",
- __FILE__, __func__);
+ TRACE(TRACE_INFO, "Calling for a Sieve sort");
sort_result_t *sort_result;
sort_result = sort_process(useridnr, message);
if (sort_result) {
@@ -83,20 +90,17 @@ dsn_class_t sort_and_deliver(struct DbmailMessage *message,
// This may necessarily imply that the message
// is being discarded -- dropped flat on the floor.
ret = DSN_CLASS_OK;
- trace(TRACE_INFO, "%s, %s: Keep was cancelled. Message may be discarded.",
- __FILE__, __func__);
+ TRACE(TRACE_INFO, "Keep was cancelled. Message may be discarded.");
} else {
ret = sort_deliver_to_mailbox(message, useridnr, mailbox, source, NULL);
- trace(TRACE_INFO, "%s, %s: Keep was not cancelled. Message will be delivered by default.",
- __FILE__, __func__);
+ TRACE(TRACE_INFO, "Keep was not cancelled. Message will be delivered by default.");
}
/* Reject probably implies cancelkeep,
* but we'll not assume that and instead
* just test this as a separate block. */
if (reject) {
- trace(TRACE_INFO, "%s, %s: Message will be rejected.",
- __FILE__, __func__);
+ TRACE(TRACE_INFO, "Message will be rejected.");
ret = DSN_CLASS_FAIL;
}
@@ -116,40 +120,45 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
TRACE(TRACE_ERROR, "mailbox [%s] not found", mailbox);
return DSN_CLASS_FAIL;
}
- // Check ACL's on the mailbox. It must be read-write,
- // it must not be no_select, and it may require an ACL for
- // the user whose Sieve script this is, since it's possible that
- // we've looked up a #Public or a #Users mailbox.
- TRACE(TRACE_DEBUG, "Checking if we have the right to post incoming messages");
-
- mailbox_t mbox;
- memset(&mbox, '\0', sizeof(mbox));
- mbox.uid = mboxidnr;
-
- switch (acl_has_right(&mbox, useridnr, ACL_RIGHT_POST)) {
- case -1:
- TRACE(TRACE_MESSAGE, "error retrieving right for [%llu] to deliver mail to [%s]",
- useridnr, mailbox);
- return DSN_CLASS_TEMP;
- case 0:
- // No right.
- TRACE(TRACE_MESSAGE, "user [%llu] does not have right to deliver mail to [%s]",
- useridnr, mailbox);
- // Switch to INBOX.
- if (strcmp(mailbox, "INBOX") == 0) {
- // Except if we've already been down this path.
- TRACE(TRACE_MESSAGE, "already tried to deliver to INBOX");
+
+ if (source == BOX_BRUTEFORCE) {
+ TRACE(TRACE_INFO, "Brute force delivery; skipping ACL checks on mailbox.");
+ } else {
+ // Check ACL's on the mailbox. It must be read-write,
+ // it must not be no_select, and it may require an ACL for
+ // the user whose Sieve script this is, since it's possible that
+ // we've looked up a #Public or a #Users mailbox.
+ TRACE(TRACE_DEBUG, "Checking if we have the right to post incoming messages");
+
+ mailbox_t mbox;
+ memset(&mbox, '\0', sizeof(mbox));
+ mbox.uid = mboxidnr;
+
+ switch (acl_has_right(&mbox, useridnr, ACL_RIGHT_POST)) {
+ case -1:
+ TRACE(TRACE_MESSAGE, "error retrieving right for [%llu] to deliver mail to [%s]",
+ useridnr, mailbox);
+ return DSN_CLASS_TEMP;
+ case 0:
+ // No right.
+ TRACE(TRACE_MESSAGE, "user [%llu] does not have right to deliver mail to [%s]",
+ useridnr, mailbox);
+ // Switch to INBOX.
+ if (strcmp(mailbox, "INBOX") == 0) {
+ // Except if we've already been down this path.
+ TRACE(TRACE_MESSAGE, "already tried to deliver to INBOX");
+ return DSN_CLASS_FAIL;
+ }
+ return sort_deliver_to_mailbox(message, useridnr, "INBOX", BOX_DEFAULT, msgflags);
+ case 1:
+ // Has right.
+ TRACE(TRACE_INFO, "user [%llu] has right to deliver mail to [%s]",
+ useridnr, mailbox);
+ break;
+ default:
+ TRACE(TRACE_ERROR, "invalid return value from acl_has_right");
return DSN_CLASS_FAIL;
}
- return sort_deliver_to_mailbox(message, useridnr, "INBOX", BOX_DEFAULT, msgflags);
- case 1:
- // Has right.
- TRACE(TRACE_INFO, "user [%llu] has right to deliver mail to [%s]",
- useridnr, mailbox);
- break;
- default:
- TRACE(TRACE_ERROR, "invalid return value from acl_has_right");
- return DSN_CLASS_FAIL;
}
// Ok, we have the ACL right, time to deliver the message.