ShellBanner
System:Linux MiraNet 3.0.0-14-generic-pae #23-Ubuntu SMP Mon Nov 21 22:07:10 UTC 2011 i686
Software:Apache. PHP/5.3.6-13ubuntu3.10
ID:uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
Safe Mode:OFF
Open_Basedir:OFF
Freespace:25.62 GB of 70.42 GB (36.38%)
MySQL: ON MSSQL: OFF Oracle: OFF PostgreSQL: OFF Curl: OFF Sockets: ON Fetch: OFF Wget: ON Perl: ON
Disabled Functions: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

/ usr/ src/ courier-0.66.1/ maildir/ - drwxrwxrwx

Directory:
Viewing file:     maildiraclt.c (22.54 KB)      -rw-rw-rw-
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 2003-2004 Double Precision, Inc.
** See COPYING for distribution information.
*/

#include    "maildiraclt.h"
#include    "maildirmisc.h"
#include    "maildircreate.h"
#include    <time.h>
#if    HAVE_UNISTD_H
#include    <unistd.h>
#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#define NAMLEN(dirent) strlen((dirent)->d_name)
#else
#define dirent direct
#define NAMLEN(dirent) (dirent)->d_namlen
#if HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif
#if HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif
#if HAVE_NDIR_H
#include <ndir.h>
#endif
#endif
#include    <string.h>
#include    <errno.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <assert.h>


int maildir_acl_disabled=0;

static int compar_aclt(const void *a, const void *b)
{
    char ca=*(const char *)a;
    char cb=*(const char *)b;

    return (int)(unsigned char)ca - (int)(unsigned char)cb;
}

/* Post-op fixup of an aclt: collate, remove dupes. */

static void fixup(maildir_aclt *aclt)
{
    char *a, *b;

    qsort(*aclt, strlen(*aclt), 1, compar_aclt);

    for (a=b=*aclt; *a; a++)
    {
        if (*a == a[1])
            continue;
        if ((int)(unsigned char)*a <= ' ')
            continue; /* Silently drop bad access rights */

        *b++= *a;
    }
    *b=0;
}

static int validacl(const char *p)
{
    while (*p)
    {
        if ((int)(unsigned char)*p <= ' ')
        {
            errno=EINVAL;
            return -1;
        }
        ++p;
    }

    return 0;
}

int maildir_aclt_init(maildir_aclt *aclt,
              const char *initvalue_cstr,
              const maildir_aclt *initvalue_cpy)
{
    if (initvalue_cpy)
        initvalue_cstr= *initvalue_cpy;

    *aclt=NULL;

    if (!initvalue_cstr || !*initvalue_cstr)
        return 0;

    if (validacl(initvalue_cstr) < 0)
        return -1;

    if ( (*aclt=strdup(initvalue_cstr)) == NULL)
        return -1;
    fixup(aclt);
    return 0;
}

/* Destroy an aclt after it is no longer used. */

void maildir_aclt_destroy(maildir_aclt *aclt)
{
    if (*aclt)
        free(*aclt);
}


/* Add or remove access chars. */

int maildir_aclt_add(maildir_aclt *aclt,
             const char *add_strs,
             const maildir_aclt *add_aclt)
{
    if (add_aclt)
        add_strs= *add_aclt;

    if (!add_strs || !*add_strs)
        return 0;

    if (validacl(add_strs) < 0)
        return -1;

    if (*aclt)
    {
        char *p=realloc(*aclt, strlen(*aclt)+strlen(add_strs)+1);

        if (!p)
            return -1;
        strcat(p, add_strs);
        *aclt=p;

    }
    else if ( ((*aclt)=strdup(add_strs)) == NULL)
        return -1;

    fixup(aclt);
    return 0;
}

int maildir_aclt_del(maildir_aclt *aclt,
             const char *del_strs,
             const maildir_aclt *del_aclt)
{
    char *a, *b;

    if (del_aclt)
        del_strs= *del_aclt;

    if (!del_strs)
        return 0;

    if (!*aclt)
        return 0;

    for (a=b=*aclt; *a; a++)
    {
        if (strchr(del_strs, *a))
            continue;
        *b++= *a;
    }
    *b=0;

    if (**aclt == 0)
    {
        free(*aclt);
        *aclt=NULL;
    }
    return 0;
}

/* -------------------------------------------------------------------- */


void maildir_aclt_list_init(maildir_aclt_list *aclt_list)
{
    aclt_list->head=NULL;
    aclt_list->tail=NULL;
}

void maildir_aclt_list_destroy(maildir_aclt_list *aclt_list)
{
    struct maildir_aclt_node *p;

    for (p=aclt_list->head; p; )
    {
        struct maildir_aclt_node *q=p->next;

        free(p->identifier);
        maildir_aclt_destroy(&p->acl);
        free(p);
        p=q;
    }
    maildir_aclt_list_init(aclt_list);
}


/* Add an <identifier,acl> pair.  Returns 0 on success, -1 on failure */

int maildir_aclt_list_add(maildir_aclt_list *aclt_list,
              const char *identifier,
              const char *aclt_str,
              maildir_aclt *aclt_cpy)
{
    struct maildir_aclt_node *p;
    const char *q;

    /* Check for valid identifiers */

    for (q=identifier; *q; q++)
        if ( (int)(unsigned char)*q <= ' ')
        {
            errno=EINVAL;
            return -1;
        }

    if (*identifier == 0)
    {
        errno=EINVAL;
        return -1;
    }

    if (aclt_cpy && *aclt_cpy)
        aclt_str= *aclt_cpy;

    for (p=aclt_list->head; p; p=p->next)
    {
        if (strcmp(p->identifier, identifier) == 0)
        {
            maildir_aclt_destroy(&p->acl);
            return maildir_aclt_init(&p->acl, aclt_str, NULL);
        }
    }

    if ((p=malloc(sizeof(*p))) == NULL ||
        (p->identifier=strdup(identifier)) == NULL)
    {
        if (p) free(p);
        return -1;
    }

    if (maildir_aclt_init(&p->acl, aclt_str, NULL) < 0)
    {
        free(p->identifier);
        free(p);
        return -1;
    }

    p->next=NULL;
    if ((p->prev=aclt_list->tail) != NULL)
        p->prev->next=p;
    else
        aclt_list->head=p;
    aclt_list->tail=p;
    return 0;
}

/*
** Remove 'identifier' from the ACL list.
*/

int maildir_aclt_list_del(maildir_aclt_list *aclt_list,
              const char *identifier)
{
    struct maildir_aclt_node *p;

    for (p=aclt_list->head; p; p=p->next)
    {
        if (strcmp(p->identifier, identifier) == 0)
        {
            if (p->prev)
                p->prev->next=p->next;
            else aclt_list->head=p->next;

            if (p->next)
                p->next->prev=p->prev;
            else aclt_list->tail=p->prev;

            maildir_aclt_destroy(&p->acl);
            free(p->identifier);
            free(p);
            return 0;
        }
    }
    return 0;
}

/*
** Generic enumeration.
*/

int maildir_aclt_list_enum(maildir_aclt_list *aclt_list,
               int (*cb_func)(const char *identifier,
                      const maildir_aclt *acl,
                      void *cb_arg),
               void *cb_arg)
{
    struct maildir_aclt_node *p;
    int rc;

    for (p=aclt_list->head; p; p=p->next)
    {
        rc= (*cb_func)(p->identifier, &p->acl, cb_arg);

        if (rc)
            return rc;
    }
    return 0;
}

const maildir_aclt *maildir_aclt_list_find(maildir_aclt_list *aclt_list,
                       const char *identifier)
{
    struct maildir_aclt_node *p;

    for (p=aclt_list->head; p; p=p->next)
    {
        if (strcmp(p->identifier, identifier) == 0)
            return &p->acl;
    }
    return NULL;
}

/* ---------------------------------------------------------------------- */

static int maildir_acl_read_check(maildir_aclt_list *aclt_list,
                 const char *maildir,
                 const char *path);

int maildir_acl_read(maildir_aclt_list *aclt_list,
             const char *maildir,
             const char *path)
{
    int rc=maildir_acl_read_check(aclt_list, maildir, path);
    char *p, *q;

    if (rc)
        maildir_aclt_list_destroy(aclt_list);

    if (rc <= 0)
        return rc;

    /*
    ** If the ACL config file for this folder was not found,
    ** check for the ACL config file for its parent folder.
    */

    if ((p=strdup(path)) == NULL)
        return -1;

    strcpy(p, path);

    q=strrchr(p, '.');

    if (!q)
    {
        free(p);
        errno=EIO; /* Should not happen */
        return -1;
    }

    *q=0;

    rc=maildir_acl_read(aclt_list, maildir, p);
    if (rc == 0)
    {
        /* Make sure to save the default acl list */

        rc=maildir_acl_write(aclt_list, maildir, path, NULL, NULL);
        if (rc >= 0) /* Ok if rc=1 */
            rc=0;
        if (rc)
            maildir_aclt_list_destroy(aclt_list);
    }
    free(p);
    return rc;
}

/*
** Attempt to retrieve the ACL set for the specified folder.
**
** Returns -1 if error.
** Returns 0 if the ACL was retrieved.
** Returns 1 if the ACL configuration file does not exist.
*/

static int maildir_aclt_add_default_admin(maildir_aclt_list *aclt_list);

static int maildir_acl_read_check(maildir_aclt_list *aclt_list,
                  const char *maildir,
                  const char *path)
{
    char *p, *q;
    FILE *fp;
    char buffer[BUFSIZ];

    maildir_aclt_list_init(aclt_list);

    if (!maildir || !*maildir)
        maildir=".";
    if (!path || !*path)
        path=".";

    if (strchr(path, '/') || *path != '.')
    {
        errno=EINVAL;
        return -1;
    }

    if (maildir_acl_disabled)
    {
        if (maildir_aclt_list_add(aclt_list, "owner",
                      ACL_LOOKUP ACL_READ
                      ACL_SEEN ACL_WRITE ACL_INSERT
                      ACL_CREATE
                      ACL_DELETEFOLDER
                      ACL_DELETEMSGS ACL_EXPUNGE,
                      NULL) < 0 ||
            maildir_aclt_add_default_admin(aclt_list))
        {
            maildir_aclt_list_destroy(aclt_list);
            return -1;
        }
        return 0;
    }

    p=malloc(strlen(maildir)+strlen(path)+2);

    if (!p)
        return -1;

    strcat(strcat(strcpy(p, maildir), "/"), path);

    q=malloc(strlen(p)+sizeof("/" ACLFILE));
    if (!q)
    {
        free(p);
        return -1;
    }
    fp=fopen(strcat(strcpy(q, p), "/" ACLFILE), "r");
    free(p);
    free(q);

    if (fp == NULL)
    {
        if (strcmp(path, ".") == 0)
        {
            /* INBOX ACL default */

            if (maildir_aclt_list_add(aclt_list, "owner",
                          ACL_ALL, NULL) < 0 ||
                maildir_aclt_add_default_admin(aclt_list))
            {
                return -1;
            }
            return 0;
        }

        q=malloc(strlen(maildir)+sizeof("/" ACLHIERDIR "/") +
             strlen(path));
        if (!q)
            return -1;

        strcat(strcat(strcpy(q, maildir), "/" ACLHIERDIR "/"),
               path+1);

        fp=fopen(q, "r");
        free(q);
    }

    if (!fp && errno != ENOENT)
        return -1;

    if (!fp)
        return 1;

    errno=0;

    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        char *p=strchr(buffer, '\n');

        if (p) *p=0;

        for (p=buffer; *p; p++)
            if (*p == ' ')
            {
                *p=0;
                do
                {
                    ++p;
                } while (*p && *p == ' ');
                break;
            }

        if (maildir_aclt_list_add(aclt_list, buffer, p, NULL) < 0)
        {
            if (errno != EINVAL)
                return -1;
            /* Sweep crap in the ACL file under the carpet */
        }
    }
    if (ferror(fp))
    {
        fclose(fp);
        return -1;
    }
    fclose(fp);
    if (maildir_aclt_add_default_admin(aclt_list))
        return -1;
    return 0;
}

/*
** Add the default ACL permissions to the administrators group.
**
** Make sure that the ACL entry for "administrators" includes all
** rights.
**
** Make sure that any ACL entries for "-administrators" or
** "-group=administrators" do not have LOOKUP and ADMIN.
*/

static int maildir_aclt_add_default_admin(maildir_aclt_list *aclt_list)
{
    const maildir_aclt *old_acl;

    static const char * const drop_acls[]={"-administrators",
                           "-group=administrators"};
    size_t i;

    if ((old_acl=maildir_aclt_list_find(aclt_list, "group=administrators"))
        != NULL)
    {
        maildir_aclt new_acl;

        if (maildir_aclt_init(&new_acl, ACL_ALL, NULL))
            return -1;

        if (maildir_aclt_add(&new_acl, NULL, old_acl) ||
            maildir_aclt_list_add(aclt_list, "group=administrators",
                      NULL, &new_acl))
        {
            maildir_aclt_destroy(&new_acl);
            return -1;
        }
        maildir_aclt_destroy(&new_acl);
    }
    else
    {
        maildir_aclt new_acl;

        old_acl=maildir_aclt_list_find(aclt_list, "administrators");

        if (maildir_aclt_init(&new_acl, ACL_ALL, NULL))
            return -1;

        if (maildir_aclt_add(&new_acl, NULL, old_acl) ||
            maildir_aclt_list_add(aclt_list, "administrators",
                      NULL, &new_acl))
        {
            maildir_aclt_destroy(&new_acl);
            return -1;
        }
        maildir_aclt_destroy(&new_acl);
    }

    for (i=0; i<2; i++)
    {
        const char *n=drop_acls[i];
        if (maildir_aclt_list_del(aclt_list, n) < 0)
            return -1;
    }

    return 0;
}

int maildir_acl_delete(const char *maildir,
               const char *path)
{
    char *p, *q;

#if 0
    if (strcmp(path, SHARED) == 0)
        return 0;

    if (strncmp(path, SHARED ".", sizeof(SHARED)) == 0)
        return 0;
#endif
    if (!maildir || !*maildir)
        maildir=".";
    if (!path || !*path)
        path=".";

    if (strchr(path, '/') || *path != '.')
    {
        errno=EINVAL;
        return -1;
    }

    p=malloc(strlen(maildir)+strlen(path)+2);

    if (!p)
        return -1;

    strcat(strcat(strcpy(p, maildir), "/"), path);

    q=malloc(strlen(p)+sizeof("/" ACLFILE));
    if (!q)
    {
        free(p);
        return -1;
    }

    unlink(strcat(strcpy(q, p), "/" ACLFILE));
    free(p);
    free(q);

    if (strcmp(path, ".") == 0)
    {
        /* INBOX ACL default */

        return 0;
    }

    q=malloc(strlen(maildir)+sizeof("/" ACLHIERDIR "/") +
         strlen(path));
    if (!q)
    {
        free(p);
        return -1;
    }
    strcat(strcat(strcpy(q, maildir), "/" ACLHIERDIR "/"),
           path+1);

    unlink(q);
    free(q);
    return 0;
}

static int save_acl(const char *identifier, const maildir_aclt *acl,
            void *cb_arg);


static int is_owner(const char *isme, void *void_arg)
{
    if (void_arg && strcmp(isme, (const char *)void_arg) == 0)
        return 1;

    return strcmp(isme, "owner") == 0;
}

static int is_admin(const char *isme, void *void_arg)
{
    return strcmp(isme, "administrators") == 0;

    /* We don't need to check for group=administrators, see chk_admin() */
}

static int check_adminrights(maildir_aclt *list)
{
    if (strchr(maildir_aclt_ascstr(list), ACL_LOOKUP[0]) == NULL ||
        strchr(maildir_aclt_ascstr(list), ACL_ADMINISTER[0]) == NULL)
    {
        maildir_aclt_destroy(list);
        return -1;
    }

    maildir_aclt_destroy(list);
    return 0;
}

static int check_allrights(maildir_aclt *list)
{
    const char *all=ACL_ALL;

    while (*all)
    {
        if (strchr(maildir_aclt_ascstr(list), *all) == NULL)
        {
            maildir_aclt_destroy(list);
            return -1;
        }
        ++all;
    }

    maildir_aclt_destroy(list);
    return 0;
}

static int maildir_acl_compute_chkowner(maildir_aclt *aclt,
                    maildir_aclt_list *aclt_list,
                    int (*cb_func)(const char *isme,
                               void *void_arg),
                    void *void_arg,
                    int chkowner);

int maildir_acl_write(maildir_aclt_list *aclt_list,
              const char *maildir,
              const char *path,

              const char *owner,
              const char **err_failedrights)
{
    int trycreate;
    struct maildir_tmpcreate_info tci;
    FILE *fp;
    char *p, *q;
    const char *dummy_string;
    maildir_aclt chkacls;

    if (!err_failedrights)
        err_failedrights= &dummy_string;

    if (!maildir || !*maildir)
        maildir=".";
    if (!path || !*path)
        path=".";

    if (strchr(path, '/') || *path != '.')
    {
        errno=EINVAL;
        return -1;
    }

    if (strcmp(path, ".")) /* Sanity check */
        for (dummy_string=path; *dummy_string; dummy_string++)
            if (*dummy_string == '.' &&
                (dummy_string[1] == '.' ||
                 dummy_string[1] == 0))
            {
                errno=EINVAL;
                return -1;
            }


    if (maildir_acl_compute_chkowner(&chkacls, aclt_list, is_owner, NULL,
                     0))
    {
        maildir_aclt_destroy(&chkacls);
        errno=EINVAL;
        return -1;
    }

    if (check_adminrights(&chkacls))
    {
        *err_failedrights="owner";
        errno=EINVAL;
        return -1;
    }

    if (owner)
    {
        if (maildir_acl_compute_chkowner(&chkacls, aclt_list, is_owner,
                         (void *)owner, 0))
        {
            maildir_aclt_destroy(&chkacls);
            errno=EINVAL;
            return -1;
        }
        if (check_adminrights(&chkacls))
        {
            *err_failedrights=owner;
            errno=EINVAL;
            return -1;
        }
    }

    if (maildir_acl_compute(&chkacls, aclt_list, is_admin, NULL))
    {
        maildir_aclt_destroy(&chkacls);
        errno=EINVAL;
        return -1;
    }
    if (check_allrights(&chkacls))
    {
        errno=EINVAL;
        return -1;
    }

    p=malloc(strlen(maildir)+strlen(path)+2);

    if (!p)
        return -1;

    strcat(strcat(strcpy(p, maildir), "/"), path);

    maildir_tmpcreate_init(&tci);

    tci.maildir=p;
    tci.uniq="acl";
    tci.doordie=1;

    fp=maildir_tmpcreate_fp(&tci);

    trycreate=0;

    if (fp)
    {
        q=malloc(strlen(p) + sizeof("/" ACLFILE));
        if (!q)
        {
            fclose(fp);
            unlink(tci.tmpname);
            maildir_tmpcreate_free(&tci);
            free(p);
            return -1;
        }
        strcat(strcpy(q, p), "/" ACLFILE);
        free(tci.newname);
        tci.newname=q;
        free(p);
    }
    else
    {
        free(p);

        q=malloc(strlen(maildir)+sizeof("/" ACLHIERDIR "/") +
             strlen(path));
        if (!q)
        {
            maildir_tmpcreate_free(&tci);
            return -1;
        }
        strcat(strcat(strcpy(q, maildir), "/" ACLHIERDIR "/"), path+1);

        tci.maildir=maildir;
        tci.uniq="acl";
        tci.doordie=1;

        fp=maildir_tmpcreate_fp(&tci);

        if (!fp)
        {
            free(q);
            maildir_tmpcreate_free(&tci);
            return -1;
        }
        free(tci.newname);
        tci.newname=q;
        trycreate=1;
    }

    if (maildir_aclt_list_enum(aclt_list, save_acl, fp) < 0 ||
        ferror(fp) || fflush(fp) < 0)
    {
        fclose(fp);
        unlink(tci.tmpname);
        maildir_tmpcreate_free(&tci);
        return -1;
    }
    fclose(fp);

    if (rename(tci.tmpname, tci.newname) < 0)
    {
        /* Perhaps ACLHIERDIR needs to be created? */

        if (!trycreate)
        {
            unlink(tci.tmpname);
            maildir_tmpcreate_free(&tci);
            return -1;
        }

        p=strrchr(tci.newname, '/');
        *p=0;
        mkdir(tci.newname, 0755);
        *p='/';

        if (rename(tci.tmpname, tci.newname) < 0)
        {
            unlink(tci.tmpname);
            maildir_tmpcreate_free(&tci);
            return -1;
        }
    }
    maildir_tmpcreate_free(&tci);
    return 0;
}

static int save_acl(const char *identifier, const maildir_aclt *acl,
            void *cb_arg)
{
    if (fprintf((FILE *)cb_arg, "%s %s\n",
            identifier,
            maildir_aclt_ascstr(acl)) < 0)
        return -1;
    return 0;
}

struct maildir_acl_resetList {
    struct maildir_acl_resetList *next;
    char *mbox;
};

/*
** When a maildir is opened check for stale entries in Maildir/ACLHIERDIR.
**
** Maildir/ACLHIERDIR/folder.subfolder should be removed unless there exists
** Maildir/.folder.subfolder.subsubfolder
**
**
** acl_check_cb is the callback function for maildir_list, which receives
** INBOX.folder.subfolder.subsubfolder.  It goes through the link list with
** Maildir/ACLHIERDIR's contents, and removes folder.subfolder if its found.
**
** After maildir_list is done, anything that's left in the list can be safely
** removed.
*/

static void acl_check_cb(const char *mbox, void *voidarg)
{
    struct maildir_acl_resetList **l=
        (struct maildir_acl_resetList **)voidarg;

    if (strncmp(mbox, INBOX ".", sizeof(INBOX ".")-1))
        return; /* Huh? */

    mbox += sizeof(INBOX ".")-1;

    while (*l)
    {
        int cl= strlen( (*l)->mbox );

        if (strncmp(mbox, (*l)->mbox, cl) == 0 &&
            mbox[cl] == '.')
        {
            struct maildir_acl_resetList *p= *l;

            *l= p->next;
            free(p->mbox);
            free(p);
            continue;
        }

        l= &(*l)->next;
    }
}

int maildir_acl_reset(const char *maildir)
{
    DIR *dirp;
    struct dirent *de;
    char *p;
    struct maildir_acl_resetList *rl=NULL;
    struct maildir_acl_resetList *r;
    time_t now;
    struct stat stat_buf;

    p=malloc(strlen(maildir) + sizeof("/" ACLHIERDIR));
    if (!p)
        return -1;

    strcat(strcpy(p, maildir), "/" ACLHIERDIR);

    dirp=opendir(p);

    if (!dirp)
    {
        mkdir(p, 0755);
        dirp=opendir(p);
    }
    free(p);

    while (dirp && (de=readdir(dirp)) != NULL)
    {
        if (de->d_name[0] == '.')
            continue;

        if ((r=malloc(sizeof(struct maildir_acl_resetList))) == NULL
            || (r->mbox=strdup(de->d_name)) == NULL)
        {
            if (r)
                free(r);

            while (rl)
            {
                r=rl;
                rl=r->next;
                free(r->mbox);
                free(r);
            }
            closedir(dirp);
            return -1;
        }

        r->next=rl;
        rl=r;
    }
    if (dirp) closedir(dirp);

    maildir_list(maildir, acl_check_cb, &rl);

    time(&now);

    while (rl)
    {
        r=rl;
        rl=r->next;

        p=malloc(strlen(maildir)+strlen(r->mbox) +
             sizeof("/" ACLHIERDIR "/"));
        if (p)
        {
            strcat(strcat(strcpy(p, maildir),
                      "/" ACLHIERDIR "/"), r->mbox);

            /* Only unlink stale entries after 1 hour (race) */

            if (stat(p, &stat_buf) == 0 &&
                stat_buf.st_mtime < now - 60*60)
                unlink(p);
            free(p);
        }
        free(r->mbox);
        free(r);
    }
    return 0;
}

/*
** An ACL entry for "administrators" or "group=administrators" will match
** either one.
*/

static int chk_admin(int (*cb_func)(const char *isme,
                    void *void_arg),
             const char *identifier,
             void *void_arg)
{
    if (strcmp(identifier, "administrators") == 0 ||
        strcmp(identifier, "group=administrators") == 0)
    {
        int rc=(*cb_func)("administrators", void_arg);

        if (rc == 0)
            rc=(*cb_func)("group=administrators", void_arg);
        return rc;
    }

    return (*cb_func)(identifier, void_arg);
}

#define ISIDENT(s) \
    (MAILDIR_ACL_ANYONE(s) ? 1: chk_admin(cb_func, (s), void_arg))

static int maildir_acl_compute_chkowner(maildir_aclt *aclt,
                    maildir_aclt_list *aclt_list,
                    int (*cb_func)(const char *isme,
                               void *void_arg),
                    void *void_arg,
                    int chkowner)
{
    struct maildir_aclt_node *p;
    int rc;

    if (maildir_aclt_init(aclt, "", NULL) < 0)
        return -1;

    for (p=aclt_list->head; p; p=p->next)
    {
        if (p->identifier[0] == '-')
            continue;

        rc= ISIDENT(p->identifier);

        if (rc < 0)
        {
            maildir_aclt_destroy(aclt);
            return rc;
        }

        if (rc == 0)
            continue;

        if (maildir_aclt_add(aclt, NULL, &p->acl) < 0)
        {
            maildir_aclt_destroy(aclt);
            return rc;
        }
    }

    for (p=aclt_list->head; p; p=p->next)
    {
        if (p->identifier[0] != '-')
            continue;

        rc= ISIDENT(p->identifier+1);

        if (rc < 0)
        {
            maildir_aclt_destroy(aclt);
            return rc;
        }

        if (rc == 0)
            continue;

        if (maildir_aclt_del(aclt, NULL, &p->acl) < 0)
        {
            maildir_aclt_destroy(aclt);
            return rc;
        }
    }

    /*
    ** In our scheme, the owner always gets admin rights.
    */

    rc=chkowner ? (*cb_func)("owner", void_arg):0;

    if (maildir_acl_disabled)
        rc=0;    /* Except when ACLs are disabled */

    if (rc < 0)
    {
        maildir_aclt_destroy(aclt);
        return rc;
    }

    if (rc)
    {
        if (maildir_aclt_add(aclt, ACL_ADMINISTER, NULL) < 0)
        {
            maildir_aclt_destroy(aclt);
            return rc;
        }
    }
    return 0;
}

int maildir_acl_compute(maildir_aclt *aclt, maildir_aclt_list *aclt_list,
            int (*cb_func)(const char *isme,
                       void *void_arg), void *void_arg)
{
    return maildir_acl_compute_chkowner(aclt, aclt_list, cb_func, void_arg,
                        1);
}

static int chk_array(const char *identifier, void *void_arg);

int maildir_acl_compute_array(maildir_aclt *aclt,
                  maildir_aclt_list *aclt_list,
                  const char * const *identifiers)
{
    return maildir_acl_compute(aclt, aclt_list, chk_array,
                   (void *)identifiers);
}

static int chk_array(const char *identifier, void *void_arg)
{
    const char * const *p=(const char * const *)void_arg;
    size_t i;

    for (i=0; p[i]; i++)
        if (strcmp(identifier, p[i]) == 0)
            return 1;
    return 0;
}

/* -------------------------------------------------------------------- */

int maildir_acl_canlistrights(const char *myrights)
{
    return (strchr(myrights, ACL_LOOKUP[0]) ||
        strchr(myrights, ACL_READ[0]) ||
        strchr(myrights, ACL_INSERT[0]) ||
        strchr(myrights, ACL_CREATE[0]) ||
        strchr(myrights, ACL_DELETEFOLDER[0]) ||
        strchr(myrights, ACL_EXPUNGE[0]) ||
        strchr(myrights, ACL_ADMINISTER[0]));
}

/* --------------------------------------------------------------------- */

/*
** Compute owner ACL identifiers applicable to a mailbox that's owned by
** 'mailbox_owner'.
*/

static int get_owner_list( int (*cb_func)(const char *, void *),
               const char *c,
               const char *mailbox_owner, void *arg)
{
    char *a;
    int rc;
    const char *p, *q;

    a=malloc(sizeof("user=")+strlen(c));
    if (!a)
        return -1;

    strcat(strcpy(a, "user="), c);

    rc=(*cb_func)(a, arg);

    if (rc == 0 && strcmp(a, mailbox_owner) == 0)
        rc=(*cb_func)("owner", arg);
    free(a);

    if (rc)
        return rc;

    c=getenv("OPTIONS");

    for (p=c; p && *p; )
    {
        if (*p == ',')
        {
            ++p;
            continue;
        }

        q=p;
        while (*p && *p != ',')
            ++p;

        if (strncmp(q, "group=", 6) == 0)
        {
            a=malloc(p-q+1);
            if (!a)
                return -1;

            memcpy(a, q, p-q);
            a[p-q]=0;
            rc=(*cb_func)(a, arg);
            free(a);
            if (rc)
                return rc;
        }
    }
    return 0;
}

static int count_owner_list(const char *o, void *arg)
{
    ++*(size_t *)arg;

    return 0;
}

static int save_owner_list(const char *o, void *arg)
{
    char ***p=(char ***)arg;

    **p=strdup(o);

    if (**p == NULL)
        return -1;

    ++*p;
    return 0;
}

int maildir_acl_computerights(maildir_aclt *rights,
                  maildir_aclt_list *acl_list,
                  const char *me,
                  const char *folder_owner)
{
    char **owner_array;
    size_t owner_cnt;
    char **p;
    int rc;

    owner_cnt=1;

    if (get_owner_list(count_owner_list, me, folder_owner,
               (void *)&owner_cnt) ||
        (owner_array=calloc(owner_cnt, sizeof(char *))) == NULL)
        return -1;

    p=owner_array;

    if (get_owner_list(save_owner_list, me, folder_owner, (void *)&p))
    {
        for (owner_cnt=0; owner_array[owner_cnt]; ++owner_cnt)
            free(owner_array[owner_cnt]);
        free(owner_array);
        return -1;
    }

    rc=maildir_acl_compute_array(rights, acl_list,
                     (const char * const *)owner_array);

    for (owner_cnt=0; owner_array[owner_cnt]; ++owner_cnt)
        free(owner_array[owner_cnt]);
    free(owner_array);
    return rc;
}
Command:
Quick Commands:
Upload:
[OK] Max size: 100MB
PHP Filesystem: <@ Ú
Search File:
regexp
Create File:
Overwrite [OK]
View File:
Mass Defacement:
[+] Main Directory: [+] Defacement Url:
LmfaoX Shell - Private Build [BETA] - v0.1 -; Generated: 0.2223 seconds