Back to index

citadel  8.12
imap_acl.c
Go to the documentation of this file.
00001 /*
00002  * Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
00003  *
00004  *
00005  * Copyright (c) 2007-2011 by the citadel.org team
00006  *
00007  *  This program is open source software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 3 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include "sysdep.h"
00023 #include <stdlib.h>
00024 #include <unistd.h>
00025 #include <stdio.h>
00026 #include <fcntl.h>
00027 #include <signal.h>
00028 #include <pwd.h>
00029 #include <errno.h>
00030 #include <sys/types.h>
00031 
00032 #if TIME_WITH_SYS_TIME
00033 # include <sys/time.h>
00034 # include <time.h>
00035 #else
00036 # if HAVE_SYS_TIME_H
00037 #  include <sys/time.h>
00038 # else
00039 #  include <time.h>
00040 # endif
00041 #endif
00042 
00043 #include <sys/wait.h>
00044 #include <ctype.h>
00045 #include <string.h>
00046 #include <limits.h>
00047 #include <libcitadel.h>
00048 #include "citadel.h"
00049 #include "server.h"
00050 #include "sysdep_decls.h"
00051 #include "citserver.h"
00052 #include "support.h"
00053 #include "config.h"
00054 #include "user_ops.h"
00055 #include "database.h"
00056 #include "msgbase.h"
00057 #include "internet_addressing.h"
00058 #include "serv_imap.h"
00059 #include "imap_tools.h"
00060 #include "imap_fetch.h"
00061 #include "imap_misc.h"
00062 #include "genstamp.h"
00063 #include "ctdl_module.h"
00064 
00065 
00066 /*
00067  * Implements the SETACL command.
00068  */
00069 void imap_setacl(int num_parms, ConstStr *Params) {
00070 
00071        IReply("BAD not yet implemented FIXME");
00072        return;
00073 }
00074 
00075 
00076 /*
00077  * Implements the DELETEACL command.
00078  */
00079 void imap_deleteacl(int num_parms, ConstStr *Params) {
00080 
00081        IReply("BAD not yet implemented FIXME");
00082        return;
00083 }
00084 
00085 
00086 /*
00087  * Given the bits returned by CtdlRoomAccess(), populate a string buffer
00088  * with IMAP ACL format flags.   This code is common to GETACL and MYRIGHTS.
00089  */
00090 void imap_acl_flags(StrBuf *rights, int ra)
00091 {
00092        FlushStrBuf(rights);
00093 
00094        /* l - lookup (mailbox is visible to LIST/LSUB commands)
00095         * r - read (SELECT the mailbox, perform STATUS et al)
00096         * s - keep seen/unseen information across sessions (STORE SEEN flag)
00097         */
00098        if (   (ra & UA_KNOWN)                                  /* known rooms */
00099           ||  ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED))      /* zapped rooms */
00100        ) {
00101               StrBufAppendBufPlain(rights, HKEY("l"), 0);
00102               StrBufAppendBufPlain(rights, HKEY("r"), 0);
00103               StrBufAppendBufPlain(rights, HKEY("s"), 0);
00104 
00105               /* Only output the remaining flags if the room is known */
00106 
00107               /* w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel */
00108 
00109               /* i - insert (perform APPEND, COPY into mailbox) */
00110               /* p - post (send mail to submission address for mailbox - not enforced) */
00111               /* c - create (CREATE new sub-mailboxes) */
00112               if (ra & UA_POSTALLOWED) {
00113                      StrBufAppendBufPlain(rights, HKEY("i"), 0);
00114                      StrBufAppendBufPlain(rights, HKEY("p"), 0);
00115                      StrBufAppendBufPlain(rights, HKEY("c"), 0);
00116               }
00117 
00118               /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
00119               if (ra & UA_DELETEALLOWED) {
00120                      StrBufAppendBufPlain(rights, HKEY("d"), 0);
00121               }
00122 
00123               /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
00124               if (ra & UA_ADMINALLOWED) {
00125                      /*
00126                       * This is the correct place to put the "a" flag.  We are leaving
00127                       * it commented out for now, because it implies that we could
00128                       * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS.  Since these
00129                       * commands are not yet implemented, omitting the flag should
00130                       * theoretically prevent compliant clients from attempting to
00131                       * perform them.
00132                       *
00133                       * StrBufAppendBufPlain(rights, HKEY("a"), 0);
00134                       */
00135               }
00136        }
00137 }
00138 
00139 
00140 /*
00141  * Implements the GETACL command.
00142  */
00143 void imap_getacl(int num_parms, ConstStr *Params) {
00144        char roomname[ROOMNAMELEN];
00145        char savedroom[ROOMNAMELEN];
00146        int msgs, new;
00147        int ret;
00148        struct ctdluser temp;
00149        struct cdbdata *cdbus;
00150        int ra;
00151        StrBuf *rights;
00152 
00153        if (num_parms != 3) {
00154               IReply("BAD usage error");
00155               return;
00156        }
00157 
00158        /*
00159         * Search for the specified room or folder
00160         */
00161        ret = imap_grabroom(roomname, Params[2].Key, 1);
00162        if (ret != 0) {
00163               IReply("NO Invalid mailbox name or access denied");
00164               return;
00165        }
00166 
00167        /*
00168         * CtdlUserGoto() formally takes us to the desired room.  (If another
00169         * folder is selected, save its name so we can return there!!!!!)
00170         */
00171        if (IMAP->selected) {
00172               strcpy(savedroom, CC->room.QRname);
00173        }
00174        CtdlUserGoto(roomname, 0, 0, &msgs, &new);
00175 
00176        IAPuts("* ACL ");
00177        IPutCParamStr(2);
00178 
00179        /*
00180         * Traverse the userlist
00181         */
00182        rights = NewStrBuf();
00183        cdb_rewind(CDB_USERS);
00184        while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) 
00185        {
00186               memset(&temp, 0, sizeof temp);
00187               memcpy(&temp, cdbus->ptr, sizeof temp);
00188               cdb_free(cdbus);
00189 
00190               CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
00191               if (!IsEmptyStr(temp.fullname)) {
00192                      imap_acl_flags(rights, ra);
00193                      if (StrLength(rights) > 0) {
00194                             IAPuts(" ");
00195                             plain_imap_strout(temp.fullname);
00196                             IAPuts(" ");
00197                             iaputs(SKEY( rights));
00198                      }
00199               }
00200        }
00201        FreeStrBuf(&rights);
00202        IAPuts("\r\n");
00203 
00204        /*
00205         * If another folder is selected, go back to that room so we can resume
00206         * our happy day without violent explosions.
00207         */
00208        if (IMAP->selected) {
00209               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
00210        }
00211 
00212        IReply("OK GETACL completed");
00213 }
00214 
00215 
00216 /*
00217  * Implements the LISTRIGHTS command.
00218  */
00219 void imap_listrights(int num_parms, ConstStr *Params) {
00220        char roomname[ROOMNAMELEN];
00221        char savedroom[ROOMNAMELEN];
00222        int msgs, new;
00223        int ret;
00224        struct recptypes *valid;
00225        struct ctdluser temp;
00226 
00227        if (num_parms != 4) {
00228               IReply("BAD usage error");
00229               return;
00230        }
00231 
00232        /*
00233         * Search for the specified room/folder
00234         */
00235        ret = imap_grabroom(roomname, Params[2].Key, 1);
00236        if (ret != 0) {
00237               IReply("NO Invalid mailbox name or access denied");
00238               return;
00239        }
00240 
00241        /*
00242         * Search for the specified user
00243         */
00244        ret = (-1);
00245        valid = validate_recipients(Params[3].Key, NULL, 0);
00246        if (valid != NULL) {
00247               if (valid->num_local == 1) {
00248                      ret = CtdlGetUser(&temp, valid->recp_local);
00249               }
00250               free_recipients(valid);
00251        }
00252        if (ret != 0) {
00253               IReply("NO Invalid user name or access denied");
00254               return;
00255        }
00256 
00257        /*
00258         * CtdlUserGoto() formally takes us to the desired room.  (If another
00259         * folder is selected, save its name so we can return there!!!!!)
00260         */
00261        if (IMAP->selected) {
00262               strcpy(savedroom, CC->room.QRname);
00263        }
00264        CtdlUserGoto(roomname, 0, 0, &msgs, &new);
00265 
00266        /*
00267         * Now output the list of rights
00268         */
00269        IAPuts("* LISTRIGHTS ");
00270        IPutCParamStr(2);
00271        IAPuts(" ");
00272        IPutCParamStr(3);
00273        IAPuts(" ");
00274        IPutStr(HKEY(""));          /* FIXME ... do something here */
00275        IAPuts("\r\n");
00276 
00277        /*
00278         * If another folder is selected, go back to that room so we can resume
00279         * our happy day without violent explosions.
00280         */
00281        if (IMAP->selected) {
00282               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
00283        }
00284 
00285        IReply("OK LISTRIGHTS completed");
00286        return;
00287 }
00288 
00289 
00290 /*
00291  * Implements the MYRIGHTS command.
00292  */
00293 void imap_myrights(int num_parms, ConstStr *Params) {
00294        char roomname[ROOMNAMELEN];
00295        char savedroom[ROOMNAMELEN];
00296        int msgs, new;
00297        int ret;
00298        int ra;
00299        StrBuf *rights;
00300 
00301        if (num_parms != 3) {
00302               IReply("BAD usage error");
00303               return;
00304        }
00305 
00306        ret = imap_grabroom(roomname, Params[2].Key, 1);
00307        if (ret != 0) {
00308               IReply("NO Invalid mailbox name or access denied");
00309               return;
00310        }
00311 
00312        /*
00313         * CtdlUserGoto() formally takes us to the desired room.  (If another
00314         * folder is selected, save its name so we can return there!!!!!)
00315         */
00316        if (IMAP->selected) {
00317               strcpy(savedroom, CC->room.QRname);
00318        }
00319        CtdlUserGoto(roomname, 0, 0, &msgs, &new);
00320 
00321        CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
00322        rights = NewStrBuf();
00323        imap_acl_flags(rights, ra);
00324 
00325        IAPuts("* MYRIGHTS ");
00326        IPutCParamStr(2);
00327        IAPuts(" ");
00328        IPutStr(SKEY(rights));
00329        IAPuts("\r\n");
00330 
00331        FreeStrBuf(&rights);
00332 
00333        /*
00334         * If a different folder was previously selected, return there now.
00335         */
00336        if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
00337               CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
00338        }
00339 
00340        IReply("OK MYRIGHTS completed");
00341        return;
00342 }