Hi there,
as part of an exercise to make use of event notifications for the
purposes of auditing (non-syslog), I wanted to add an event notification
for ACL changes.
Please find attached a patch for your review, an aggregate of the work
in dev/acl-change-notification[1].
I have a couple of things I myself am pondering as well;
- ACL change notifications are not a part of any RFC as such (but for
[2]), and therefore the fields aclSubject / aclRights may need a
'vnd.cmu' prefix? Does the event name "AclChange" need a similar prefix?
- In relation to the previous consideration, this change (in part) could
relate to "Access Control List Changes in IMAP NOTIFY"[2].
- The event (type) could perhaps use a separate "event_groups" in
imapd.conf(5), but for now I stuffed them under "access" - the fields
themselves could also be subject to inclusion in event_extra_params
instead, perhaps.
Thanks, in advance,
Kind regards,
Jeroen van Meeuwen
[1]
http://git.cyrusimap.org/cyrus-imapd/log/?h=dev/acl-change-notification
[2] http://tools.ietf.org/html/rfc5465#section-5.9
--
Systems Architect, Kolab Systems AG
e: vanmeeuwen at kolabsys.com
m: +44 74 2516 3817
w: http://www.kolabsys.com
pgp: 9342 BF08
diff --git a/imap/mboxevent.c b/imap/mboxevent.c
index db45821..2ad0fc7 100644
--- a/imap/mboxevent.c
+++ b/imap/mboxevent.c
@@ -72,7 +72,7 @@
#define MAILBOX_EVENTS (EVENT_MAILBOX_CREATE|EVENT_MAILBOX_DELETE|\
EVENT_MAILBOX_RENAME|EVENT_MAILBOX_SUBSCRIBE|\
- EVENT_MAILBOX_UNSUBSCRIBE)
+ EVENT_MAILBOX_UNSUBSCRIBE|EVENT_ACL_CHANGE)
#define QUOTA_EVENTS (EVENT_QUOTA_EXCEED|EVENT_QUOTA_WITHIN|EVENT_QUOTA_CHANGE)
@@ -120,6 +120,8 @@ static struct mboxevent event_template =
{ EVENT_FLAG_NAMES, "flagNames", EVENT_PARAM_STRING, 0, 0 },
{ EVENT_USER, "user", EVENT_PARAM_STRING, 0, 0 },
{ EVENT_MESSAGE_SIZE, "messageSize", EVENT_PARAM_INT, 0, 0 },
+ { EVENT_ACL_SUBJECT, "aclSubject", EVENT_PARAM_STRING, 0, 0 },
+ { EVENT_ACL_RIGHTS, "aclRights", EVENT_PARAM_STRING, 0, 0 },
/* always at end to let the parser to easily truncate this part */
{ EVENT_BODYSTRUCTURE, "bodyStructure", EVENT_PARAM_STRING, 0, 0 },
{ EVENT_MESSAGE_CONTENT, "messageContent", EVENT_PARAM_STRING, 0, 0 }
@@ -169,7 +171,7 @@ EXPORTED void mboxevent_init(void)
enabled_events |= FLAGS_EVENTS;
if (groups & IMAP_ENUM_EVENT_GROUPS_ACCESS)
- enabled_events |= (EVENT_LOGIN|EVENT_LOGOUT);
+ enabled_events |= (EVENT_LOGIN|EVENT_LOGOUT|EVENT_ACL_CHANGE);
if (groups & IMAP_ENUM_EVENT_GROUPS_MAILBOX)
enabled_events |= MAILBOX_EVENTS;
@@ -360,6 +362,10 @@ static int mboxevent_expected_param(enum event_type type, enum event_param param
return extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_SERVICE;
case EVENT_TIMESTAMP:
return extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_TIMESTAMP;
+ case EVENT_ACL_SUBJECT:
+ return type & EVENT_ACL_CHANGE;
+ case EVENT_ACL_RIGHTS:
+ return type & EVENT_ACL_CHANGE;
case EVENT_UIDNEXT:
if (!(extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_UIDNEXT))
return 0;
@@ -621,6 +627,16 @@ EXPORTED void mboxevent_set_access(struct mboxevent *event,
}
}
+EXPORTED void mboxevent_set_acl(struct mboxevent *event, const char *identifier,
+ const char *rights)
+{
+ if (!event)
+ return;
+
+ FILL_STRING_PARAM(event, EVENT_ACL_SUBJECT, xstrdup(identifier));
+ FILL_STRING_PARAM(event, EVENT_ACL_RIGHTS, xstrdup(rights));
+}
+
EXPORTED void mboxevent_extract_record(struct mboxevent *event, struct mailbox *mailbox,
struct index_record *record)
{
@@ -979,6 +995,8 @@ static const char *event_to_name(enum event_type type)
return "MailboxSubscribe";
case EVENT_MAILBOX_UNSUBSCRIBE:
return "MailboxUnSubscribe";
+ case EVENT_ACL_CHANGE:
+ return "AclChange";
default:
fatal("Unknown message event", EC_SOFTWARE);
}
@@ -1178,6 +1196,12 @@ EXPORTED void mboxevent_set_access(struct mboxevent *event __attribute__((unused
{
}
+EXPORTED void mboxevent_set_acl(struct mboxevent *event __attribute__((unused)),
+ const char *identifier __attribute__((unused)),
+>.......>.......>.......>.......const char *rights __attribute__((unused)))
+{
+}
+
EXPORTED void mboxevent_extract_record(struct mboxevent *event __attribute__((unused)),
struct mailbox *mailbox __attribute__((unused)),
struct index_record *record __attribute__((unused)))
diff --git a/imap/mboxevent.h b/imap/mboxevent.h
index 1171bd2..9a85927 100644
--- a/imap/mboxevent.h
+++ b/imap/mboxevent.h
@@ -79,10 +79,11 @@ enum event_type {
EVENT_MAILBOX_DELETE = (1<<16),
EVENT_MAILBOX_RENAME = (1<<17),
EVENT_MAILBOX_SUBSCRIBE = (1<<18),
- EVENT_MAILBOX_UNSUBSCRIBE = (1<<19)
+ EVENT_MAILBOX_UNSUBSCRIBE = (1<<19),
+ EVENT_ACL_CHANGE = (1<<20),
};
-#define MAX_PARAM 21 /* messageContent number that is always the last */
+#define MAX_PARAM 23 /* messageContent number that is always the last */
/*
* event parameters defined in RFC 5423 - Internet Message Store Events
@@ -110,6 +111,8 @@ enum event_param {
EVENT_FLAG_NAMES,
EVENT_USER,
EVENT_MESSAGE_SIZE,
+ EVENT_ACL_SUBJECT,
+ EVENT_ACL_RIGHTS,
EVENT_BODYSTRUCTURE,
EVENT_MESSAGE_CONTENT
};
@@ -207,6 +210,13 @@ void mboxevent_add_flag(struct mboxevent *event, const char *flag);
void mboxevent_set_access(struct mboxevent *event,
const char *serveraddr, const char *clientaddr,
const char *userid, const char *mailboxname);
+
+/*
+ * Shortcut to setting event notification parameters
+ */
+void mboxevent_set_acl(struct mboxevent *event, const char *identifier,
+ const char *rights);
+
/*
* Extract data from the given record to fill these event parameters :
* - uidset from UID
diff --git a/imap/mboxlist.c b/imap/mboxlist.c
index e0579e5..87bcd81 100644
--- a/imap/mboxlist.c
+++ b/imap/mboxlist.c
@@ -1638,6 +1638,15 @@ EXPORTED int mboxlist_setacl(struct namespace *namespace, const char *name,
name, cyrusdb_strerror(r));
r = IMAP_IOERROR;
}
+
+ /* send a AclChange event notification */
+ struct mboxevent *mboxevent = mboxevent_new(EVENT_ACL_CHANGE);
+ mboxevent_extract_mailbox(mboxevent, mailbox);
+ mboxevent_set_acl(mboxevent, identifier, rights);
+
+ mboxevent_notify(mboxevent);
+ mboxevent_free(&mboxevent);
+
}
/* 4. Change backup copy (cyrus.header) */