Esempio n. 1
0
/* convert a string to an acl bit vector
 */
int cyrus_acl_strtomask(const char *str)
{
    const char *deleteright = libcyrus_config_getstring(CYRUSOPT_DELETERIGHT);
    long legacy_create = 0;
    long legacy_delete = 0;
    long result = 0;

    while (*str) {
	switch (*str) {
	    case 'l': result |= ACL_LOOKUP; break;
	    case 'r': result |= ACL_READ; break;
	    case 's': result |= ACL_SEEN; break;
	    case 'w': result |= ACL_WRITE; break;
	    case 'i': result |= ACL_INSERT; break;
	    case 'p': result |= ACL_POST; break;
	    case 'c': /* legacy CREATE macro - build member rights */
		legacy_create = ACL_CREATE; break;
	    case 'k': result |= ACL_CREATE; break;
	    case 'x': result |= ACL_DELETEMBOX; break;
	    case 't': result |= ACL_DELETEMSG; break;
	    case 'e': result |= ACL_EXPUNGE; break;
	    case 'd': /* legacy DELETE macro - build member rights */
		legacy_delete = (ACL_DELETEMSG | ACL_EXPUNGE); break;
	    case 'a': result |= ACL_ADMIN; break;
	    case '0': result |= ACL_USER0; break;
	    case '1': result |= ACL_USER1; break;
	    case '2': result |= ACL_USER2; break;
	    case '3': result |= ACL_USER3; break;
	    case '4': result |= ACL_USER4; break;
	    case '5': result |= ACL_USER5; break;
	    case '6': result |= ACL_USER6; break;
	    case '7': result |= ACL_USER7; break;
	    case '8': result |= ACL_USER8; break;
	    case '9': result |= ACL_USER9; break;
	}

	if (*str++ == *deleteright) {
	    switch (*deleteright) {
	    case 'c': /* legacy CREATE macro - build member rights */
		legacy_create |= ACL_DELETEMBOX; break;
	    case 'd': /* legacy DELETE macro - build member rights */
		legacy_delete |= ACL_DELETEMBOX; break;
	    default: result |= ACL_DELETEMBOX; break;
	    }
	}
    }

    /* If the rights string contained a legacy macro, but none of its
       member rights, then we add all of the member rights for the macro.
       Otherwise, we ignore the legacy macro.
    */
    if (!(result & legacy_create)) result |= legacy_create;
    if (!(result & legacy_delete)) result |= legacy_delete;

    return (result);
}
Esempio n. 2
0
/* convert an acl bit vector to a string
 */
char *cyrus_acl_masktostr(int acl, char *str)
{
    char *pos = str;
    const char *deleteright = libcyrus_config_getstring(CYRUSOPT_DELETERIGHT);
    int legacy_create = ACL_CREATE;
    int legacy_delete = (ACL_DELETEMSG | ACL_EXPUNGE);

    switch (*deleteright) {
    case 'c': legacy_create |= ACL_DELETEMBOX; break;
    case 'd': legacy_delete |= ACL_DELETEMBOX; break;
    default: /* XXX  we have backwards compatibility problems */ break;
    }

    if (acl & ACL_LOOKUP) *pos++ = 'l';
    if (acl & ACL_READ) *pos++ = 'r';
    if (acl & ACL_SEEN) *pos++ = 's';
    if (acl & ACL_WRITE) *pos++ = 'w';
    if (acl & ACL_INSERT) *pos++ = 'i';
    if (acl & ACL_POST) *pos++ = 'p';
    if (acl & ACL_CREATE) *pos++ = 'k';
    if (acl & ACL_DELETEMBOX) *pos++ = 'x';
    if (acl & ACL_DELETEMSG) *pos++ = 't';
    if (acl & ACL_EXPUNGE) *pos++ = 'e';
    if (acl & legacy_create) {
	/* legacy CREATE macro member right(s) - add macro */
	*pos++ = 'c';
    }
    if (acl & legacy_delete) {
	/* legacy DELETE macro member right(s) - add macro */
	*pos++ = 'd';
    }
    if (acl & ACL_ADMIN) *pos++ = 'a';
    if (acl & ACL_USER0) *pos++ = '0';
    if (acl & ACL_USER1) *pos++ = '1';
    if (acl & ACL_USER2) *pos++ = '2';
    if (acl & ACL_USER3) *pos++ = '3';
    if (acl & ACL_USER4) *pos++ = '4';
    if (acl & ACL_USER5) *pos++ = '5';
    if (acl & ACL_USER6) *pos++ = '6';
    if (acl & ACL_USER7) *pos++ = '7';
    if (acl & ACL_USER8) *pos++ = '8';
    if (acl & ACL_USER9) *pos++ = '9';
    *pos = '\0';

    return (str);
}
Esempio n. 3
0
EXPORTED void cyrusdb_init(void)
{
    int i, r;
    char dbdir[1024];
    const char *confdir = libcyrus_config_getstring(CYRUSOPT_CONFIG_DIR);
    int initflags = libcyrus_config_getint(CYRUSOPT_DB_INIT_FLAGS);

    strcpy(dbdir, confdir);
    strcat(dbdir, FNAME_DBDIR);

    for(i=0; _backends[i]; i++) {
	r = (_backends[i])->init(dbdir, initflags);
	if(r) {
	    syslog(LOG_ERR, "DBERROR: init() on %s",
		   _backends[i]->name);
	}
    }
}
Esempio n. 4
0
static struct auth_mech *auth_fromname()
{
    int i;
    const char *name = libcyrus_config_getstring(CYRUSOPT_AUTH_MECH);
    static struct auth_mech *auth = NULL;

    if (auth)
        return auth;

    for (i = 0; auth_mechs[i]; i++) {
	if (!strcmp(auth_mechs[i]->name, name)) {
	    auth = auth_mechs[i]; break;
	}
    }
    if (!auth) {
	char errbuf[1024];
	snprintf(errbuf, sizeof(errbuf),
		 "Authorization mechanism %s not supported", name);
	fatal(errbuf, EC_CONFIG);
    }

    return auth;
}
Esempio n. 5
0
/* Returns 0 on success */
static int ptload(const char *identifier, struct auth_state **state)
{
    struct auth_state *fetched = NULL;
    size_t id_len;
    const char *data = NULL;
    size_t dsize;
    const char *fname = NULL;
    char *tofree = NULL;
    struct db *ptdb;
    int s;
    struct sockaddr_un srvaddr;
    int r, rc=0;
    static char response[1024];
    struct iovec iov[10];
    int niov, n;
    unsigned int start;
    const char *config_dir =
        libcyrus_config_getstring(CYRUSOPT_CONFIG_DIR);

    /* xxx this sucks, but it seems to be the only way to satisfy the linker */
    if(the_ptscache_db == NULL) {
        the_ptscache_db = libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB);
    }

    if(!state || *state) {
        fatal("bad state pointer passed to ptload()", EC_TEMPFAIL);
    }

    fname = libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB_PATH);

    if (!fname) {
        tofree = strconcat(config_dir, PTS_DBFIL, (char *)NULL);
        fname = tofree;
    }
    r = cyrusdb_open(the_ptscache_db, fname, CYRUSDB_CREATE, &ptdb);
    if (r != 0) {
        syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
               cyrusdb_strerror(ret));
        free(tofree);
        *state = NULL;
        return -1;
    }
    free(tofree);
    tofree = NULL;

    id_len = strlen(identifier);
    if(id_len > PTS_DB_KEYSIZE) {
        syslog(LOG_ERR, "identifier too long in auth_newstate");
        *state = NULL;
        return -1;
    }

    /* fetch the current record for the user */
    r = cyrusdb_fetch(ptdb, identifier, id_len,
                               &data, &dsize, NULL);
    if (r && r != CYRUSDB_NOTFOUND) {
        syslog(LOG_ERR, "auth_newstate: error fetching record: %s",
               cyrusdb_strerror(r));

        rc = -1;
        goto done;
    }

    /* if it's expired (or nonexistent),
     * ask the ptloader to reload it and reread it */
    fetched = (struct auth_state *) data;

    if(fetched) {
        time_t now = time(NULL);
        int timeout = libcyrus_config_getint(CYRUSOPT_PTS_CACHE_TIMEOUT);

        syslog(LOG_DEBUG,
               "ptload(): fetched cache record (%s)" \
               "(mark %ld, current %ld, limit %ld)", identifier,
               fetched->mark, now, now - timeout);

        if (fetched->mark > (now - timeout)) {
            /* not expired; let's return it */
            goto done;
        }
    }

    syslog(LOG_DEBUG, "ptload(): pinging ptloader");

    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s == -1) {
        syslog(LOG_ERR,
               "ptload(): unable to create socket for ptloader: %m");
        rc = -1;
        goto done;
    }

    fname = libcyrus_config_getstring(CYRUSOPT_PTLOADER_SOCK);
    if (!fname) {
        tofree = strconcat(config_dir, PTS_DBSOCKET, (char *)NULL);
        fname = tofree;
    }

    if (strlen(fname) >= sizeof(srvaddr.sun_path)) {
        syslog(LOG_ERR, "ptload(): socket filename %s too long for " SIZE_T_FMT "-byte buffer",
                        fname, sizeof(srvaddr.sun_path));
        rc = -1;
        goto done;
    }

    memset((char *)&srvaddr, 0, sizeof(srvaddr));
    srvaddr.sun_family = AF_UNIX;
    strlcpy(srvaddr.sun_path, fname, sizeof(srvaddr.sun_path));
    r = nb_connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr), PT_TIMEOUT_SEC);
    free(tofree);

    if (r == -1) {
        syslog(LOG_ERR, "ptload(): can't connect to ptloader server: %m");
        close(s);
        rc = -1;
        goto done;
    }

    syslog(LOG_DEBUG, "ptload(): connected");
    niov = 0;
    WRITEV_ADD_TO_IOVEC(iov, niov, (char *) &id_len, sizeof(id_len));
    WRITEV_ADD_TO_IOVEC(iov, niov, (char *) identifier, id_len);

    if (timeout_select(s, TS_WRITE, PT_TIMEOUT_SEC) < 0) {
      syslog(LOG_ERR, "timeoutselect: writing to ptloader %m");
      rc = -1;
      goto done;
    }
    retry_writev(s, iov, niov);
    syslog(LOG_DEBUG, "ptload sent data");

    start = 0;
    while (start < sizeof(response) - 1) {
      if (timeout_select(s, TS_READ, PT_TIMEOUT_SEC) < 0) {
        syslog(LOG_ERR, "timeout_select: reading from ptloader: %m");
        rc = -1;
        goto done;
      }
      n = read(s, response+start, sizeof(response) - 1 - start);
      if (n < 1) break;
      start += n;
    }
    response[sizeof(response)-1] = '\0';

    close(s);
    syslog(LOG_DEBUG, "ptload read data back");

    if (start <= 1 || strncmp(response, "OK", 2)) {
       if(start > 1) {
           syslog(LOG_ERR,
                  "ptload(): bad response from ptloader server: %s", response);
       } else {
           syslog(LOG_ERR, "ptload(): empty response from ptloader server");
       }
       rc = -1;
       goto done;
    }

    /* fetch the current record for the user */
    r = cyrusdb_fetch(ptdb, identifier, id_len,
                               &data, &dsize, NULL);
    if (r != 0 || !data) {
        syslog(LOG_ERR, "ptload(): error fetching record: %s"
               "(did ptloader add the record?)",
               cyrusdb_strerror(r));
      data = NULL;
      rc = -1;
      goto done;
    }

 done:
    /* ok, we got real data, let's use it */
    if (data != NULL) {
      fetched = (struct auth_state *) data;
    }

    if (fetched == NULL) {
      *state = NULL;
      syslog(LOG_DEBUG, "No data available at all from ptload()");
    } else  {
      /* copy it into our structure */
      *state = (struct auth_state *)xmalloc(dsize);
      memcpy(*state, fetched, dsize);
      syslog(LOG_DEBUG, "ptload returning data");
    }

    /* close and unlock the database */
    (cyrusdb_close)(ptdb);

    return rc;
}