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