Back to index

courier  0.68.2
acl.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2004-2011 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 
00007 /*
00008 */
00009 #include      <stdio.h>
00010 #include      <string.h>
00011 #include      <stdlib.h>
00012 #include      <ctype.h>
00013 #include      <fcntl.h>
00014 #include      <errno.h>
00015 #include      <courierauth.h>
00016 #include      "config.h"
00017 #include      "sqwebmail.h"
00018 #include      "maildir.h"
00019 #include      "cgi/cgi.h"
00020 #include      "pref.h"
00021 #include      "sqconfig.h"
00022 #include      "auth.h"
00023 #include      "acl.h"
00024 #include      "maildir/maildirquota.h"
00025 #include      "maildir/maildirrequota.h"
00026 #include      "maildir/maildirgetquota.h"
00027 #include      "maildir/maildirmisc.h"
00028 #include      "maildir/maildircreate.h"
00029 #include      "maildir/maildirwatch.h"
00030 #include      "unicode/unicode.h"
00031 #include      "htmllibdir.h"
00032 
00033 #if    HAVE_UNISTD_H
00034 #include      <unistd.h>
00035 #endif
00036 
00037 #if    HAVE_DIRENT_H
00038 #include      <dirent.h>
00039 #define       NAMLEN(dirent)       strlen(dirent->d_name)
00040 #else
00041 #define       dirent direct
00042 #define       NAMLEN(dirent)       ((dirent)->d_namlen)
00043 #if    HAVE_SYS_NDIR_H
00044 #include      <sys/ndir.h>
00045 #endif
00046 #if    HAVE_SYS_DIR_H
00047 #include      <sys/dir.h>
00048 #endif
00049 #if    HAVE_NDIR_H
00050 #include      <ndir.h>
00051 #endif
00052 #endif
00053 
00054 #include      <sys/types.h>
00055 #include      <sys/stat.h>
00056 #if    HAVE_UTIME_H
00057 #include      <utime.h>
00058 #endif
00059 
00060 #include      "unicode/unicode.h"
00061 
00062 #include      "strftime.h"
00063 
00064 
00065 /* ACL support stuff */
00066 
00067 extern const char *sqwebmail_folder;
00068 extern void output_urlencoded(const char *p);
00069 extern void output_attrencoded(const char *p);
00070 extern void output_scriptptrget();
00071 extern void output_scriptptr();
00072 extern void output_scriptptrpostinfo();
00073 
00074 extern dev_t sqwebmail_homedir_dev;
00075 extern ino_t sqwebmail_homedir_ino;
00076 
00077 extern const char *sqwebmail_content_charset;
00078 int verify_shared_index_file=0;
00079 
00080 int maildir_info_suppress(const char *maildir)
00081 {
00082        struct stat stat_buf;
00083 
00084        if (stat(maildir, &stat_buf) < 0 ||
00085 
00086            (stat_buf.st_dev == sqwebmail_homedir_dev &&
00087             stat_buf.st_ino == sqwebmail_homedir_ino))
00088               return 1;
00089        return 0;
00090 }
00091 
00092 const char *maildir_shared_index_file()
00093 {
00094        static char *filenamep=NULL;
00095 
00096        if (filenamep == NULL)
00097        {
00098               const char *p=getenv("SQWEBMAIL_SHAREDINDEXFILE");
00099 
00100               if (!p || !*p)
00101                      p=SHAREDINDEXFILE;
00102 
00103               if (p && *p)
00104               {
00105                      const char *q=auth_getoptionenv("sharedgroup");
00106 
00107                      if (!q) q="";
00108 
00109                      filenamep=malloc(strlen(p)+strlen(q)+1);
00110 
00111                      if (!filenamep)
00112                             enomem();
00113 
00114                      strcat(strcpy(filenamep, p), q);
00115               }
00116        }
00117 
00118        if (filenamep && verify_shared_index_file)
00119        {
00120               struct stat stat_buf;
00121 
00122               if (stat(filenamep, &stat_buf))
00123               {
00124                      fprintf(stderr, "ERR: ");
00125                      perror(filenamep);
00126               }
00127        }
00128 
00129        return filenamep;
00130 }
00131 
00132 int acl_read(maildir_aclt_list *l, const char *folder,
00133             char **owner)
00134 {
00135        struct maildir_info minfo;
00136        int rc;
00137 
00138        if (maildir_info_imap_find(&minfo, folder,
00139                                login_returnaddr())<0)
00140        {
00141               return -1;
00142        }
00143 
00144        rc=acl_read2(l, &minfo, owner);
00145        maildir_info_destroy(&minfo);
00146        return rc;
00147 }
00148 
00149 int acl_read2(maildir_aclt_list *l,
00150              struct maildir_info *minfo,
00151              char **owner)
00152 {
00153        int rc;
00154        char *p;
00155 
00156        if (minfo->mailbox_type == MAILBOXTYPE_OLDSHARED)
00157        {
00158               /* Legacy shared., punt. */
00159 
00160               maildir_aclt_list_init(l);
00161               if (maildir_aclt_list_add(l, "anyone",
00162                                      ACL_LOOKUP ACL_READ
00163                                      ACL_SEEN ACL_WRITE
00164                                      ACL_INSERT
00165                                      ACL_DELETEMSGS ACL_EXPUNGE, NULL) < 0
00166                   || (*owner=strdup("vendor=courier.internal")) == NULL)
00167               {
00168                      maildir_aclt_list_destroy(l);
00169                      return -1;
00170               }
00171               return 0;
00172        }
00173 
00174        if (minfo->homedir == NULL || minfo->maildir == NULL)
00175               return -1;
00176 
00177        p=maildir_name2dir(".", minfo->maildir);
00178 
00179        if (!p)
00180               return -1;
00181 
00182        rc=maildir_acl_read(l, minfo->homedir,
00183                          strncmp(p, "./", 2) == 0 ? p+2:p);
00184        free(p);
00185        if (owner && rc == 0)
00186        {
00187               *owner=minfo->owner;
00188               minfo->owner=NULL;
00189        }
00190        return rc;
00191 }
00192 
00193 void acl_computeRightsOnFolder(const char *folder, char *rights)
00194 {
00195        maildir_aclt_list l;
00196        char *owner;
00197 
00198        if (acl_read(&l, folder, &owner) < 0)
00199        {
00200               *rights=0;
00201               return;
00202        }
00203        acl_computeRights(&l, rights, owner);
00204        if (owner)
00205               free(owner);
00206        maildir_aclt_list_destroy(&l);
00207 }
00208 
00209 void acl_computeRights(maildir_aclt_list *l, char *rights,
00210                      const char *owner)
00211 {
00212        char *p, *q;
00213 
00214        maildir_aclt a;
00215 
00216        if (maildir_acl_computerights(&a, l, login_returnaddr(), owner) < 0)
00217        {
00218               *rights=0;
00219               return;
00220        }
00221 
00222        for (p=q=rights; *p; p++)
00223        {
00224               if (strchr(maildir_aclt_ascstr(&a), *p))
00225                      *q++ = *p;
00226        }
00227        *q=0;
00228        maildir_aclt_destroy(&a);
00229 }
00230 
00231 static void showrights(const char *buf)
00232 {
00233        size_t i;
00234        char buf2[40];
00235 
00236        for (i=0; buf[i]; i++)
00237        {
00238               const char *p;
00239 
00240               if (i)
00241                      printf(", ");
00242 
00243               sprintf(buf2, "ACL_%c", buf[i]);
00244 
00245               p=getarg(buf2);
00246               if (p && *p)
00247                      printf("%s", p);
00248               else
00249               {
00250                      buf2[0]=buf[i];
00251                      buf2[1]=0;
00252 
00253                      printf(getarg("ACL_unknown"), buf2);
00254               }
00255        }
00256 }
00257 
00258 static void doupdate();
00259 
00260 void listrights()
00261 {
00262        maildir_aclt_list l;
00263        char buf[40];
00264        char *owner;
00265 
00266        if (*cgi("do.update") || *cgi("delentity"))
00267        {
00268               struct maildir_info minfo;
00269 
00270               if (maildir_info_imap_find(&minfo, sqwebmail_folder,
00271                                       login_returnaddr()) == 0)
00272               {
00273                      if (minfo.homedir)
00274                      {
00275                             struct maildirwatch *w;
00276                             char *lock;
00277                             int tryanyway;
00278 
00279                             w=maildirwatch_alloc(minfo.homedir);
00280 
00281                             if (!w)
00282                             {
00283                                    maildir_info_destroy(&minfo);
00284                                    enomem();
00285                                    return;
00286                             }
00287 
00288                             lock=maildir_lock(minfo.homedir, w,
00289                                             &tryanyway);
00290 
00291                             maildir_info_destroy(&minfo);
00292 
00293                             if (lock == NULL)
00294                             {
00295                                    if (!tryanyway)
00296                                    {
00297                                           printf("%s",
00298                                                  getarg("ACL_noaccess"));
00299                                           return;
00300                                    }
00301                             }
00302                             doupdate();
00303                             if (lock)
00304                             {
00305                                    unlink(lock);
00306                                    free(lock);
00307                             }
00308                             maildirwatch_free(w);
00309                      }
00310               }
00311        }
00312 
00313        if (acl_read(&l, sqwebmail_folder, &owner) < 0)
00314        {
00315               printf("%s", getarg("ACL_cantread"));
00316               return;
00317        }
00318        buf[0]=0;
00319        strncat(buf, getarg("ACL_all"), sizeof(buf)-2);
00320        acl_computeRights(&l, buf, owner);
00321        maildir_aclt_list_destroy(&l);
00322        if (owner)
00323               free(owner);
00324 
00325        if (!maildir_acl_canlistrights(buf))
00326        {
00327               printf("%s", getarg("ACL_cantread"));
00328               return;
00329        }
00330 
00331        showrights(buf);
00332 }
00333 
00334 static void doupdate()
00335 {
00336        maildir_aclt_list l;
00337        char *owner;
00338        char buf[2];
00339        char *p;
00340        struct maildir_info minfo;
00341 
00342        if (maildir_info_imap_find(&minfo, sqwebmail_folder,
00343                                login_returnaddr()) < 0)
00344               return;
00345 
00346        if (acl_read2(&l, &minfo, &owner) < 0)
00347        {
00348               maildir_info_destroy(&minfo);
00349               return;
00350        }
00351 
00352        strcpy(buf, ACL_ADMINISTER);
00353        acl_computeRights(&l, buf, owner);
00354        if (!*buf)
00355        {
00356               if (owner)
00357                      free(owner);
00358               maildir_aclt_list_destroy(&l);
00359               maildir_info_destroy(&minfo);
00360               return;
00361        }
00362 
00363        if (*cgi("delentity"))
00364        {
00365               if (maildir_aclt_list_del(&l, cgi("delentity")))
00366                      printf("%s", getarg("ACL_failed"));
00367        }
00368 
00369        if (*cgi("do.update"))
00370        {
00371               char *entity=NULL;
00372               const char *p;
00373               char new_acl[40];
00374 
00375               p=cgi("entitytype");
00376 
00377               if (strcmp(p, "anonymous") == 0 ||
00378                   strcmp(p, "owner") == 0)
00379                      entity=strdup(p);
00380               else if (strcmp(p, "user") == 0)
00381               {
00382                      p=cgi("entity");
00383 
00384                      if (*p)
00385                      {
00386                             entity=malloc(sizeof("user=")+strlen(p));
00387                             if (entity)
00388                                    strcat(strcpy(entity, "user="), p);
00389                      }
00390               }
00391               else if (strcmp(p, "group") == 0)
00392               {
00393                      p=cgi("entity");
00394 
00395                      if (*p)
00396                      {
00397                             entity=malloc(sizeof("group=")+strlen(p));
00398                             if (entity)
00399                                    strcat(strcpy(entity, "group="), p);
00400                      }
00401               }
00402               else
00403               {
00404                      entity=strdup(cgi("entity"));
00405               }
00406 
00407               if (*cgi("negate") == '-' && entity)
00408               {
00409                      char *p=malloc(strlen(entity)+2);
00410 
00411                      if (p)
00412                             strcat(strcpy(p, "-"), entity);
00413                      free(entity);
00414                      entity=p;
00415               }
00416 
00417               if (entity)
00418               {
00419                      char *val=
00420                             libmail_u_convert_toutf8(entity,
00421                                                   sqwebmail_content_charset,
00422                                                   NULL);
00423 
00424 
00425                      if (val)
00426                      {
00427                             free(entity);
00428                             entity=val;
00429                      }
00430               }
00431               p=getarg("ACL_all");
00432 
00433               new_acl[0]=0;
00434 
00435               while (*p && strlen(new_acl) < sizeof(new_acl)-2)
00436               {
00437                      char b[40];
00438 
00439                      sprintf(b, "acl_%c", *p);
00440 
00441                      if (*cgi(b))
00442                      {
00443                             b[0]=*p;
00444                             b[1]=0;
00445                             strcat(new_acl, b);
00446                      }
00447                      ++p;
00448               }
00449 
00450               if (!entity || !*entity ||
00451                   maildir_aclt_list_add(&l, entity, new_acl, NULL) < 0)
00452                      printf("%s", getarg("ACL_failed"));
00453 
00454               if (entity)
00455                      free(entity);
00456        }
00457 
00458        p=maildir_name2dir(".", minfo.maildir);
00459 
00460        if (p)
00461        {
00462               const char *err_ident;
00463 
00464               if (maildir_acl_write(&l, minfo.homedir,
00465                                   strncmp(p, "./", 2) == 0 ? p+2:p,
00466                                   owner, &err_ident))
00467                      printf("%s", getarg("ACL_failed"));
00468               free(p);
00469        }
00470 
00471        if (owner)
00472               free(owner);
00473        maildir_aclt_list_destroy(&l);
00474        maildir_info_destroy(&minfo);
00475 }
00476 
00477 static void p_ident_name(const char *identifier)
00478 {
00479        char *val=libmail_u_convert_fromutf8(identifier,
00480                                         sqwebmail_content_charset,
00481                                         NULL);
00482 
00483        if (val)
00484        {
00485               output_attrencoded(val);
00486               free(val);
00487               return;
00488        }
00489 
00490        output_attrencoded(identifier);
00491 }
00492 
00493 static int getacl_cb(const char *identifier, const maildir_aclt *acl,
00494                    void *dummy)
00495 {
00496        printf("<tr><td>");
00497        p_ident_name(identifier);
00498        printf("</td><td>");
00499        showrights(maildir_aclt_ascstr(acl));
00500 
00501 
00502 
00503        printf("<span class=\"folder-acl-list-action\">&nbsp;(<a href=\"");
00504        output_scriptptrget();
00505        printf("&amp;form=acl&amp;editentity=");
00506        output_urlencoded(identifier);
00507        printf("&amp;editaccess=");
00508        output_urlencoded(maildir_aclt_ascstr(acl));
00509        printf("\">%s</a>)&nbsp;(<a href=\"", getarg("EDIT"));
00510        output_scriptptrget();
00511        printf("&amp;form=acl&amp;delentity=");
00512        output_urlencoded(identifier);
00513        printf("\">%s</a>)</td></tr>\n", getarg("DELETE"));
00514        return 0;
00515 }
00516 
00517 void getacl()
00518 {
00519        maildir_aclt_list l;
00520        char buf[2];
00521        char *owner;
00522        const char *a;
00523        const char *editentity=cgi("editentity");
00524        const char *editaccess=cgi("editaccess");
00525 
00526        const char *entitytype="";
00527        const char *entityval="";
00528        int negate=0;
00529 
00530        if (acl_read(&l, sqwebmail_folder, &owner) < 0)
00531        {
00532               printf("%s", getarg("ACL_noaccess"));
00533               return;
00534        }
00535        strcpy(buf, ACL_ADMINISTER);
00536        acl_computeRights(&l, buf, owner);
00537        if (owner)
00538               free(owner);
00539 
00540        if (buf[0] == 0)
00541        {
00542               maildir_aclt_list_destroy(&l);
00543               return;
00544        }
00545 
00546        printf("<form method=\"post\" name=\"form1\" action=\"");
00547        output_scriptptr();
00548        printf("\">");
00549        output_scriptptrpostinfo();
00550        printf("<input type=\"hidden\" name=\"update\" value=\"1\" />\n"
00551               "<input type=\"hidden\" name=\"form\" value=\"acl\" />\n");
00552        printf("<table class=\"folder-acl-list\"><tbody>"
00553               "<tr><th align=\"left\">%s</th><th align=\"left\">%s</th></tr>\n",
00554               getarg("ENTITY"),
00555               getarg("ACCESSRIGHTS"));
00556 
00557        maildir_aclt_list_enum(&l, getacl_cb, NULL);
00558 
00559        if (*editentity == '-')
00560        {
00561               ++editentity;
00562               negate=1;
00563        }
00564 
00565        if (*editentity)
00566        {
00567               if (strncmp(editentity, "user=", 5) == 0)
00568               {
00569                      entitytype="user";
00570                      entityval=editentity+5;
00571               }
00572               else if (strncmp(editentity, "group=", 6) == 0)
00573               {
00574                      entitytype="group";
00575                      entityval=editentity+6;
00576               }
00577               else if (strcmp(editentity, "owner") == 0 ||
00578                       strcmp(editentity, "anonymous") == 0)
00579               {
00580                      entitytype=editentity;
00581               }
00582               else
00583               {
00584                      entitytype="other";
00585                      entityval=editentity;
00586               }
00587        }
00588 
00589        printf("<tr><td colspan=\"2\"><hr width=\"90%%\" />");
00590        printf("<table><tbody>\n");
00591        printf("<tr><th colspan=\"2\" align=\"left\">%s</th></tr>\n",
00592               getarg("UPDATEHDR"));
00593        printf("<tr align=\"top\"><td>"
00594               "<select name=\"negate\" id=\"negate\">\n"
00595               "<option value=\"\" > </option>\n"
00596               "<option value=\"-\" %s>-</option>\n"
00597               "</select>\n"
00598               "<select name=\"entitytype\" id=\"entitytype\" "
00599               "onchange=\"javascript:updent()\" >\n"
00600               "<option value=\"user\" %s >%s</option>\n"
00601               "<option value=\"group\" %s >%s</option>\n"
00602               "<option value=\"owner\" %s >%s</option>\n"
00603               "<option value=\"anonymous\" %s >%s</option>\n"
00604               "<option value=\"administrators\" %s >%s</option>\n"
00605               "<option value=\"other\" %s >%s</option>\n"
00606               "</select><input type=\"text\" name=\"entity\" "
00607               " id=\"entity\" value=\"",
00608               negate ? "selected=\"selected\"":"",
00609               strcmp(entitytype, "user") == 0 ? "selected=\"selected\"":"",
00610               getarg("USER"),
00611 
00612               strcmp(entitytype, "group") == 0 ? "selected=\"selected\"":"",
00613               getarg("GROUP"),
00614 
00615               strcmp(entitytype, "owner") == 0 ? "selected=\"selected\"":"",
00616               getarg("OWNER"),
00617 
00618               strcmp(entitytype, "anonymous") == 0 ? "selected=\"selected\"":"",
00619               getarg("ANONYMOUS"),
00620 
00621               strcmp(entitytype, "administrators") == 0 ? "selected=\"selected\"":"",
00622               getarg("ADMINISTRATORS"),
00623 
00624               strcmp(entitytype, "other") == 0 ? "selected=\"selected\"":"",
00625               getarg("OTHER"));
00626 
00627        p_ident_name(entityval);
00628 
00629        printf("\"/></td><td><table><tbody>");
00630 
00631        a=getarg("ACL_all");
00632 
00633        while (*a)
00634        {
00635               char buf2[40];
00636 
00637               sprintf(buf2, "ACL_%c", *a);
00638 
00639               printf("<tr><td><input type=\"checkbox\" name=\"acl_%c\" "
00640                      "id=\"acl_%c\" %s />"
00641                      "</td><td>%s</td></tr>\n",
00642                      *a, *a,
00643                      strchr(editaccess, *a) ? "checked=\"checked\"":"",
00644                      getarg(buf2));
00645               ++a;
00646        }
00647 
00648        printf("</tbody></table></td></tr>\n"
00649               "<tr><td>&nbsp;</td>"
00650               "<td><input type=\"submit\" name=\"do.update\" value=\"%s\" />"
00651               "</td>"
00652               "</table></tbody></td></tr>\n",
00653               getarg("UPDATE"));
00654 
00655        printf("</tbody></table></form>\n");
00656 }
00657