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) */

Reply via email to