]> code.citadel.org Git - citadel.git/blob - citadel/imap_acl.c
a9756ba2d6155cca9d661981e189f416516ed1b7
[citadel.git] / citadel / imap_acl.c
1 /*
2  * $Id:  $
3  *
4  * Functions which implement RFC2086/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, SUBSCRIBE mailbox)
85          * r - read (SELECT the mailbox, perform STATUS)
86          * s - keep seen/unseen information across sessions (set or clear \SEEN flag
87          *     via STORE, also set \SEEN during APPEND/COPY/ FETCH BODY[...])
88          * e - perform EXPUNGE and expunge as a part of CLOSE
89          */
90         if (    (ra & UA_KNOWN)                                 /* known rooms */
91            ||   ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED))     /* zapped rooms */
92            ) {
93                 strcat(rights, "l");
94                 strcat(rights, "r");
95                 strcat(rights, "s");
96                 strcat(rights, "e");
97
98                 /* Only output the remaining flags if the room is known */
99
100                 /* w - write (set or clear arbitrary flags; not supported in Citadel) */
101
102                 /* i - insert (perform APPEND, COPY into mailbox) */
103                 /* p - post (send mail to submission address for mailbox - not enforced) */
104                 if (ra & UA_POSTALLOWED) {
105                         strcat(rights, "i");
106                         strcat(rights, "p");
107                 }
108
109                 /* k - create mailboxes in this hierarchy */
110
111                 /* t - delete messages (set/clear \Deleted flag) */
112                 if (ra & UA_DELETEALLOWED) {
113                         strcat(rights, "t");
114                 }
115
116                 /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
117                 /* x - delete mailbox (DELETE mailbox, old mailbox name in RENAME) */
118                 if (ra & UA_ADMINALLOWED) {
119                         /*
120                          * This is the correct place to put the "a" flag.  We are leaving
121                          * it commented out for now, because it implies that we could
122                          * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS.  Since these
123                          * commands are not yet implemented, omitting the flag should
124                          * theoretically prevent compliant clients from attempting to
125                          * perform them.
126                          */
127                         /* strcat(rights, "a"); * commented out */
128                         strcat(rights, "x");
129                 }
130         }
131 }
132
133
134 /*
135  * Implements the GETACL command.
136  */
137 void imap_getacl(int num_parms, char *parms[]) {
138         char roomname[ROOMNAMELEN];
139         char savedroom[ROOMNAMELEN];
140         int msgs, new;
141         int ret;
142         struct ctdluser temp;
143         struct cdbdata *cdbus;
144         int ra;
145         char rights[32];
146
147         if (num_parms != 3) {
148                 cprintf("%s BAD usage error\r\n", parms[0]);
149                 return;
150         }
151
152         /*
153          * Search for the specified room or folder
154          */
155         ret = imap_grabroom(roomname, parms[2], 0);
156         if (ret != 0) {
157                 cprintf("%s NO Invalid mailbox name or access denied\r\n",
158                         parms[0]);
159                 return;
160         }
161
162         /*
163          * usergoto() formally takes us to the desired room.  (If another
164          * folder is selected, save its name so we can return there!!!!!)
165          */
166         if (IMAP->selected) {
167                 strcpy(savedroom, CC->room.QRname);
168         }
169         usergoto(roomname, 0, 0, &msgs, &new);
170
171         cprintf("* ACL");
172         cprintf(" ");
173         imap_strout(parms[2]);
174
175         /*
176          * Traverse the userlist
177          */
178         cdb_rewind(CDB_USERS);
179         while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
180                 memset(&temp, 0, sizeof temp);
181                 memcpy(&temp, cdbus->ptr, sizeof temp);
182                 cdb_free(cdbus);
183
184                 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
185                 if (strlen(temp.fullname) > 0) {
186                         imap_acl_flags(rights, ra);
187                         if (strlen(rights) > 0) {
188                                 cprintf(" ");
189                                 imap_strout(temp.fullname);
190                                 cprintf(" %s", rights);
191                         }
192                 }
193         }
194
195         cprintf("\r\n");
196
197         /*
198          * If another folder is selected, go back to that room so we can resume
199          * our happy day without violent explosions.
200          */
201         if (IMAP->selected) {
202                 usergoto(savedroom, 0, 0, &msgs, &new);
203         }
204
205         cprintf("%s OK GETACL completed\r\n", parms[0]);
206 }
207
208
209 /*
210  * Implements the LISTRIGHTS command.
211  */
212 void imap_listrights(int num_parms, char *parms[]) {
213         char roomname[ROOMNAMELEN];
214         char savedroom[ROOMNAMELEN];
215         int msgs, new;
216         int ret;
217         struct recptypes *valid;
218         struct ctdluser temp;
219
220         if (num_parms != 4) {
221                 cprintf("%s BAD usage error\r\n", parms[0]);
222                 return;
223         }
224
225         /*
226          * Search for the specified room/folder
227          */
228         ret = imap_grabroom(roomname, parms[2], 0);
229         if (ret != 0) {
230                 cprintf("%s NO Invalid mailbox name or access denied\r\n",
231                         parms[0]);
232                 return;
233         }
234
235         /*
236          * Search for the specified user
237          */
238         ret = (-1);
239         valid = validate_recipients(parms[3]);
240         if (valid != NULL) {
241                 if (valid->num_local == 1) {
242                         ret = getuser(&temp, valid->recp_local);
243                 }
244                 free(valid);
245         }
246         if (ret != 0) {
247                 cprintf("%s NO Invalid user name or access denied\r\n",
248                         parms[0]);
249                 return;
250         }
251
252         /*
253          * usergoto() formally takes us to the desired room.  (If another
254          * folder is selected, save its name so we can return there!!!!!)
255          */
256         if (IMAP->selected) {
257                 strcpy(savedroom, CC->room.QRname);
258         }
259         usergoto(roomname, 0, 0, &msgs, &new);
260
261
262         /*
263          * Now output the list of rights
264          */
265         cprintf("* LISTRIGHTS ");
266         imap_strout(parms[2]);
267         cprintf(" ");
268         imap_strout(parms[3]);
269         cprintf(" ");
270         imap_strout("");                /* FIXME ... do something here */
271         cprintf("\r\n");
272
273
274         /*
275          * If another folder is selected, go back to that room so we can resume
276          * our happy day without violent explosions.
277          */
278         if (IMAP->selected) {
279                 usergoto(savedroom, 0, 0, &msgs, &new);
280         }
281
282         cprintf("%s OK LISTRIGHTS completed\r\n", parms[0]);
283         return;
284 }
285
286
287 /*
288  * Implements the MYRIGHTS command.
289  */
290 void imap_myrights(int num_parms, char *parms[]) {
291         char roomname[ROOMNAMELEN];
292         char savedroom[ROOMNAMELEN];
293         int msgs, new;
294         int ret;
295         int ra;
296         char rights[32];
297
298         if (num_parms != 3) {
299                 cprintf("%s BAD usage error\r\n", parms[0]);
300                 return;
301         }
302
303         ret = imap_grabroom(roomname, parms[2], 0);
304         if (ret != 0) {
305                 cprintf("%s NO Invalid mailbox name or access denied\r\n",
306                         parms[0]);
307                 return;
308         }
309
310         /*
311          * usergoto() formally takes us to the desired room.  (If another
312          * folder is selected, save its name so we can return there!!!!!)
313          */
314         if (IMAP->selected) {
315                 strcpy(savedroom, CC->room.QRname);
316         }
317         usergoto(roomname, 0, 0, &msgs, &new);
318
319         CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
320         imap_acl_flags(rights, ra);
321
322         cprintf("* MYRIGHTS ");
323         imap_strout(parms[2]);
324         cprintf(" %s\r\n", rights);
325
326         /*
327          * If a different folder was previously selected, return there now.
328          */
329         if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
330                 usergoto(savedroom, 0, 0, &msgs, &new);
331         }
332
333         cprintf("%s OK MYRIGHTS completed\r\n", parms[0]);
334         return;
335 }
336
337