]> code.citadel.org Git - citadel.git/blob - citadel/imap_acl.c
Revert to RFC2086-style ACL flags.
[citadel.git] / citadel / imap_acl.c
1 /*
2  * $Id$
3  *
4  * Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
5  *
6  */
7
8
9 #include "sysdep.h"
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <pwd.h>
16 #include <errno.h>
17 #include <sys/types.h>
18
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
21 # include <time.h>
22 #else
23 # if HAVE_SYS_TIME_H
24 #  include <sys/time.h>
25 # else
26 #  include <time.h>
27 # endif
28 #endif
29
30 #include <sys/wait.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <limits.h>
34 #include "citadel.h"
35 #include "server.h"
36 #include "sysdep_decls.h"
37 #include "citserver.h"
38 #include "support.h"
39 #include "config.h"
40 #include "serv_extensions.h"
41 #include "room_ops.h"
42 #include "user_ops.h"
43 #include "policy.h"
44 #include "database.h"
45 #include "msgbase.h"
46 #include "tools.h"
47 #include "internet_addressing.h"
48 #include "serv_imap.h"
49 #include "imap_tools.h"
50 #include "imap_fetch.h"
51 #include "imap_misc.h"
52 #include "genstamp.h"
53
54
55
56 /*
57  * Implements the SETACL command.
58  */
59 void imap_setacl(int num_parms, char *parms[]) {
60
61         cprintf("%s BAD not yet implemented FIXME\r\n", parms[0]);
62         return;
63 }
64
65
66 /*
67  * Implements the DELETEACL command.
68  */
69 void imap_deleteacl(int num_parms, char *parms[]) {
70
71         cprintf("%s BAD not yet implemented FIXME\r\n", parms[0]);
72         return;
73 }
74
75
76 /*
77  * Given the bits returned by CtdlRoomAccess(), populate a string buffer
78  * with IMAP ACL format flags.   This code is common to GETACL and MYRIGHTS.
79  */
80 void imap_acl_flags(char *rights, int ra)
81 {
82         strcpy(rights, "");
83
84         /* l - lookup (mailbox is visible to LIST/LSUB commands)
85          * r - read (SELECT the mailbox, perform STATUS et al)
86          * s - keep seen/unseen information across sessions (STORE SEEN flag)
87          */
88         if (    (ra & UA_KNOWN)                                 /* known rooms */
89            ||   ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED))     /* zapped rooms */
90            ) {
91                 strcat(rights, "l");
92                 strcat(rights, "r");
93                 strcat(rights, "s");
94
95                 /* Only output the remaining flags if the room is known */
96
97                 /* w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel */
98
99                 /* i - insert (perform APPEND, COPY into mailbox) */
100                 /* p - post (send mail to submission address for mailbox - not enforced) */
101                 /* c - create (CREATE new sub-mailboxes) */
102                 if (ra & UA_POSTALLOWED) {
103                         strcat(rights, "i");
104                         strcat(rights, "p");
105                         strcat(rights, "c");
106                 }
107
108                 /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
109                 if (ra & UA_DELETEALLOWED) {
110                         strcat(rights, "d");
111                 }
112
113                 /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
114                 if (ra & UA_ADMINALLOWED) {
115                         /*
116                          * This is the correct place to put the "a" flag.  We are leaving
117                          * it commented out for now, because it implies that we could
118                          * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS.  Since these
119                          * commands are not yet implemented, omitting the flag should
120                          * theoretically prevent compliant clients from attempting to
121                          * perform them.
122                          */
123                         /* strcat(rights, "a"); * commented out */
124                 }
125         }
126 }
127
128
129 /*
130  * Implements the GETACL command.
131  */
132 void imap_getacl(int num_parms, char *parms[]) {
133         char roomname[ROOMNAMELEN];
134         char savedroom[ROOMNAMELEN];
135         int msgs, new;
136         int ret;
137         struct ctdluser temp;
138         struct cdbdata *cdbus;
139         int ra;
140         char rights[32];
141
142         if (num_parms != 3) {
143                 cprintf("%s BAD usage error\r\n", parms[0]);
144                 return;
145         }
146
147         /*
148          * Search for the specified room or folder
149          */
150         ret = imap_grabroom(roomname, parms[2], 0);
151         if (ret != 0) {
152                 cprintf("%s NO Invalid mailbox name or access denied\r\n",
153                         parms[0]);
154                 return;
155         }
156
157         /*
158          * usergoto() formally takes us to the desired room.  (If another
159          * folder is selected, save its name so we can return there!!!!!)
160          */
161         if (IMAP->selected) {
162                 strcpy(savedroom, CC->room.QRname);
163         }
164         usergoto(roomname, 0, 0, &msgs, &new);
165
166         cprintf("* ACL");
167         cprintf(" ");
168         imap_strout(parms[2]);
169
170         /*
171          * Traverse the userlist
172          */
173         cdb_rewind(CDB_USERS);
174         while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
175                 memset(&temp, 0, sizeof temp);
176                 memcpy(&temp, cdbus->ptr, sizeof temp);
177                 cdb_free(cdbus);
178
179                 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
180                 if (strlen(temp.fullname) > 0) {
181                         imap_acl_flags(rights, ra);
182                         if (strlen(rights) > 0) {
183                                 cprintf(" ");
184                                 imap_strout(temp.fullname);
185                                 cprintf(" %s", rights);
186                         }
187                 }
188         }
189
190         cprintf("\r\n");
191
192         /*
193          * If another folder is selected, go back to that room so we can resume
194          * our happy day without violent explosions.
195          */
196         if (IMAP->selected) {
197                 usergoto(savedroom, 0, 0, &msgs, &new);
198         }
199
200         cprintf("%s OK GETACL completed\r\n", parms[0]);
201 }
202
203
204 /*
205  * Implements the LISTRIGHTS command.
206  */
207 void imap_listrights(int num_parms, char *parms[]) {
208         char roomname[ROOMNAMELEN];
209         char savedroom[ROOMNAMELEN];
210         int msgs, new;
211         int ret;
212         struct recptypes *valid;
213         struct ctdluser temp;
214
215         if (num_parms != 4) {
216                 cprintf("%s BAD usage error\r\n", parms[0]);
217                 return;
218         }
219
220         /*
221          * Search for the specified room/folder
222          */
223         ret = imap_grabroom(roomname, parms[2], 0);
224         if (ret != 0) {
225                 cprintf("%s NO Invalid mailbox name or access denied\r\n",
226                         parms[0]);
227                 return;
228         }
229
230         /*
231          * Search for the specified user
232          */
233         ret = (-1);
234         valid = validate_recipients(parms[3]);
235         if (valid != NULL) {
236                 if (valid->num_local == 1) {
237                         ret = getuser(&temp, valid->recp_local);
238                 }
239                 free_recipients(valid);
240         }
241         if (ret != 0) {
242                 cprintf("%s NO Invalid user name or access denied\r\n",
243                         parms[0]);
244                 return;
245         }
246
247         /*
248          * usergoto() formally takes us to the desired room.  (If another
249          * folder is selected, save its name so we can return there!!!!!)
250          */
251         if (IMAP->selected) {
252                 strcpy(savedroom, CC->room.QRname);
253         }
254         usergoto(roomname, 0, 0, &msgs, &new);
255
256
257         /*
258          * Now output the list of rights
259          */
260         cprintf("* LISTRIGHTS ");
261         imap_strout(parms[2]);
262         cprintf(" ");
263         imap_strout(parms[3]);
264         cprintf(" ");
265         imap_strout("");                /* FIXME ... do something here */
266         cprintf("\r\n");
267
268
269         /*
270          * If another folder is selected, go back to that room so we can resume
271          * our happy day without violent explosions.
272          */
273         if (IMAP->selected) {
274                 usergoto(savedroom, 0, 0, &msgs, &new);
275         }
276
277         cprintf("%s OK LISTRIGHTS completed\r\n", parms[0]);
278         return;
279 }
280
281
282 /*
283  * Implements the MYRIGHTS command.
284  */
285 void imap_myrights(int num_parms, char *parms[]) {
286         char roomname[ROOMNAMELEN];
287         char savedroom[ROOMNAMELEN];
288         int msgs, new;
289         int ret;
290         int ra;
291         char rights[32];
292
293         if (num_parms != 3) {
294                 cprintf("%s BAD usage error\r\n", parms[0]);
295                 return;
296         }
297
298         ret = imap_grabroom(roomname, parms[2], 0);
299         if (ret != 0) {
300                 cprintf("%s NO Invalid mailbox name or access denied\r\n",
301                         parms[0]);
302                 return;
303         }
304
305         /*
306          * usergoto() formally takes us to the desired room.  (If another
307          * folder is selected, save its name so we can return there!!!!!)
308          */
309         if (IMAP->selected) {
310                 strcpy(savedroom, CC->room.QRname);
311         }
312         usergoto(roomname, 0, 0, &msgs, &new);
313
314         CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
315         imap_acl_flags(rights, ra);
316
317         cprintf("* MYRIGHTS ");
318         imap_strout(parms[2]);
319         cprintf(" %s\r\n", rights);
320
321         /*
322          * If a different folder was previously selected, return there now.
323          */
324         if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
325                 usergoto(savedroom, 0, 0, &msgs, &new);
326         }
327
328         cprintf("%s OK MYRIGHTS completed\r\n", parms[0]);
329         return;
330 }
331
332