1 // Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
3 // Copyright (c) 2007-2023 by the citadel.org team
5 // This program is open source software. Use, duplication or disclosure
6 // are subject to the terms of the GNU General Public License, version 3.
8 #include "../../sysdep.h"
16 #include <sys/types.h>
22 #include <libcitadel.h>
23 #include "../../citadel_defs.h"
24 #include "../../server.h"
25 #include "../../sysdep_decls.h"
26 #include "../../citserver.h"
27 #include "../../support.h"
28 #include "../../config.h"
29 #include "../../user_ops.h"
30 #include "../../database.h"
31 #include "../../msgbase.h"
32 #include "../../internet_addressing.h"
33 #include "serv_imap.h"
34 #include "imap_tools.h"
35 #include "imap_fetch.h"
36 #include "imap_misc.h"
37 #include "../../genstamp.h"
38 #include "../../ctdl_module.h"
41 // Implements the SETACL command.
42 void imap_setacl(int num_parms, ConstStr *Params) {
43 IReply("BAD not yet implemented FIXME");
48 // Implements the DELETEACL command.
49 void imap_deleteacl(int num_parms, ConstStr *Params) {
50 IReply("BAD not yet implemented FIXME");
55 // Given the bits returned by CtdlRoomAccess(), populate a string buffer
56 // with IMAP ACL format flags. This code is common to GETACL and MYRIGHTS.
57 void imap_acl_flags(StrBuf *rights, int ra) {
60 // l - lookup (mailbox is visible to LIST/LSUB commands)
61 // r - read (SELECT the mailbox, perform STATUS et al)
62 // s - keep seen/unseen information across sessions (STORE SEEN flag)
63 if ( (ra & UA_KNOWN) // known rooms
64 || ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED)) // zapped rooms
66 StrBufAppendBufPlain(rights, HKEY("l"), 0);
67 StrBufAppendBufPlain(rights, HKEY("r"), 0);
68 StrBufAppendBufPlain(rights, HKEY("s"), 0);
70 // Only output the remaining flags if the room is known
72 // w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel
74 // i - insert (perform APPEND, COPY into mailbox)
75 // p - post (send mail to submission address for mailbox - not enforced)
76 // c - create (CREATE new sub-mailboxes)
77 if (ra & UA_POSTALLOWED) {
78 StrBufAppendBufPlain(rights, HKEY("i"), 0);
79 StrBufAppendBufPlain(rights, HKEY("p"), 0);
80 StrBufAppendBufPlain(rights, HKEY("c"), 0);
83 // d - delete messages (STORE DELETED flag, perform EXPUNGE)
84 if (ra & UA_DELETEALLOWED) {
85 StrBufAppendBufPlain(rights, HKEY("d"), 0);
88 // a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS)
89 if (ra & UA_ADMINALLOWED) {
90 // This is the correct place to put the "a" flag. We are leaving
91 // it commented out for now, because it implies that we could
92 // perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS. Since these
93 // commands are not yet implemented, omitting the flag should
94 // theoretically prevent compliant clients from attempting to
97 // StrBufAppendBufPlain(rights, HKEY("a"), 0);
103 // Implements the GETACL command.
104 void imap_getacl(int num_parms, ConstStr *Params) {
105 char roomname[ROOMNAMELEN];
106 char savedroom[ROOMNAMELEN];
109 struct ctdluser temp;
110 struct cdbdata *cdbus;
114 if (num_parms != 3) {
115 IReply("BAD usage error");
119 // Search for the specified room or folder
120 ret = imap_grabroom(roomname, Params[2].Key, 1);
122 IReply("NO Invalid mailbox name or access denied");
126 // CtdlUserGoto() formally takes us to the desired room. (If another
127 // folder is selected, save its name so we can return there!!!!!)
128 if (IMAP->selected) {
129 strcpy(savedroom, CC->room.QRname);
131 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
136 // Traverse the userlist
137 rights = NewStrBuf();
138 cdb_rewind(CDB_USERS);
139 while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
140 memset(&temp, 0, sizeof temp);
141 memcpy(&temp, cdbus->ptr, sizeof temp);
144 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
145 if (!IsEmptyStr(temp.fullname)) {
146 imap_acl_flags(rights, ra);
147 if (StrLength(rights) > 0) {
149 IPutStr(temp.fullname, strlen(temp.fullname));
151 iaputs(SKEY( rights));
158 // If another folder is selected, go back to that room so we can resume
159 // our happy day without violent explosions.
160 if (IMAP->selected) {
161 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
164 IReply("OK GETACL completed");
168 // Implements the LISTRIGHTS command.
169 void imap_listrights(int num_parms, ConstStr *Params) {
170 char roomname[ROOMNAMELEN];
171 char savedroom[ROOMNAMELEN];
174 struct recptypes *valid;
175 struct ctdluser temp;
177 if (num_parms != 4) {
178 IReply("BAD usage error");
182 // Search for the specified room/folder
183 ret = imap_grabroom(roomname, Params[2].Key, 1);
185 IReply("NO Invalid mailbox name or access denied");
189 // Search for the specified user
191 valid = validate_recipients(Params[3].Key, NULL, 0);
193 if (valid->num_local == 1) {
194 ret = CtdlGetUser(&temp, valid->recp_local);
196 free_recipients(valid);
199 IReply("NO Invalid user name or access denied");
203 // CtdlUserGoto() formally takes us to the desired room. (If another
204 // folder is selected, save its name so we can return there!!!!!)
205 if (IMAP->selected) {
206 strcpy(savedroom, CC->room.QRname);
208 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
210 // Now output the list of rights
211 IAPuts("* LISTRIGHTS ");
216 IPutStr(HKEY("")); // FIXME ... do something here
219 // If another folder is selected, go back to that room so we can resume
220 // our happy day without violent explosions.
221 if (IMAP->selected) {
222 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
225 IReply("OK LISTRIGHTS completed");
230 // Implements the MYRIGHTS command.
231 void imap_myrights(int num_parms, ConstStr *Params) {
232 char roomname[ROOMNAMELEN];
233 char savedroom[ROOMNAMELEN];
239 if (num_parms != 3) {
240 IReply("BAD usage error");
244 ret = imap_grabroom(roomname, Params[2].Key, 1);
246 IReply("NO Invalid mailbox name or access denied");
250 // CtdlUserGoto() formally takes us to the desired room. (If another
251 // folder is selected, save its name so we can return there!!!!!)
252 if (IMAP->selected) {
253 strcpy(savedroom, CC->room.QRname);
255 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
257 CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
258 rights = NewStrBuf();
259 imap_acl_flags(rights, ra);
261 IAPuts("* MYRIGHTS ");
264 IPutStr(SKEY(rights));
269 // If a different folder was previously selected, return there now.
270 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
271 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
274 IReply("OK MYRIGHTS completed");