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