示例#1
0
/* Called before a cyrus application starts (but after command line parameters
 * are read) */
int cyrus_init(const char *alt_config, const char *ident, unsigned flags)
{
    char *p;
    const char *val;
    const char *prefix;
    int umaskval = 0;

    if(cyrus_init_run != NOT_RUNNING) {
        fatal("cyrus_init called twice!", EC_CONFIG);
    } else {
        cyrus_init_run = RUNNING;
    }

    cyrus_init_nodb = (flags & CYRUSINIT_NODB);

    initialize_imap_error_table();
    initialize_mupd_error_table();

    if(!ident)
        fatal("service name was not specified to cyrus_init", EC_CONFIG);

    config_ident = ident;

    /* xxx we lose here since we can't have the prefix until we load the
     * config file */
    openlog(config_ident, LOG_PID, SYSLOG_FACILITY);

    /* Load configuration file.  This will set config_dir when it finds it */
    config_read(alt_config);

    prefix = config_getstring(IMAPOPT_SYSLOG_PREFIX);

    /* Reopen the log with the new prefix, if needed  */
    if(prefix) {
        int size = strlen(prefix) + 1 + strlen(ident) + 1;
        char *ident_buf = xmalloc(size);

        strlcpy(ident_buf, prefix, size);
        strlcat(ident_buf, "/", size);
        strlcat(ident_buf, ident, size);

        closelog();
        openlog(ident_buf, LOG_PID, SYSLOG_FACILITY);

        /* don't free the openlog() string! */
    }

    /* Look up default partition */
    config_defpartition = config_getstring(IMAPOPT_DEFAULTPARTITION);
    for (p = (char *)config_defpartition; p && *p; p++) {
        if (!Uisalnum(*p))
            fatal("defaultpartition option contains non-alphanumeric character",
                  EC_CONFIG);
        if (Uisupper(*p)) *p = tolower((unsigned char) *p);
    }

    /* Look up umask */
    val = config_getstring(IMAPOPT_UMASK);
    while (*val) {
        if (*val >= '0' && *val <= '7') umaskval = umaskval*8 + *val - '0';
        val++;
    }
    umask(umaskval);

    config_fulldirhash = config_getswitch(IMAPOPT_FULLDIRHASH);

    /* look up and canonify the implicit rights of mailbox owners */
    config_implicitrights =
        cyrus_acl_strtomask(config_getstring(IMAPOPT_IMPLICIT_OWNER_RIGHTS));

    config_metapartition_files = config_getbitfield(IMAPOPT_METAPARTITION_FILES);

    if (!cyrus_init_nodb) {
        /* lookup the database backends */
        config_mboxlist_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_MBOXLIST_DB));
        config_quota_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_QUOTA_DB));
        config_subscription_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_SUBSCRIPTION_DB));
        config_annotation_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_ANNOTATION_DB));
        config_seenstate_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_SEENSTATE_DB));
        config_mboxkey_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_MBOXKEY_DB));
        config_duplicate_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_DUPLICATE_DB));
        config_tlscache_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_TLSCACHE_DB));
        config_ptscache_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_PTSCACHE_DB));
        config_statuscache_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_STATUSCACHE_DB));
        config_userdeny_db =
            cyrusdb_fromname(config_getstring(IMAPOPT_USERDENY_DB));

        /* configure libcyrus as needed */
        libcyrus_config_setstring(CYRUSOPT_CONFIG_DIR, config_dir);
        libcyrus_config_setswitch(CYRUSOPT_AUTH_UNIX_GROUP_ENABLE,
                                  config_getswitch(IMAPOPT_UNIX_GROUP_ENABLE));
        libcyrus_config_setswitch(CYRUSOPT_USERNAME_TOLOWER,
                                  config_getswitch(IMAPOPT_USERNAME_TOLOWER));
        libcyrus_config_setswitch(CYRUSOPT_SKIPLIST_UNSAFE,
                                  config_getswitch(IMAPOPT_SKIPLIST_UNSAFE));
        libcyrus_config_setstring(CYRUSOPT_TEMP_PATH,
                                  config_getstring(IMAPOPT_TEMP_PATH));
        libcyrus_config_setint(CYRUSOPT_PTS_CACHE_TIMEOUT,
                               config_getint(IMAPOPT_PTSCACHE_TIMEOUT));
        libcyrus_config_setswitch(CYRUSOPT_FULLDIRHASH,
                                  config_getswitch(IMAPOPT_FULLDIRHASH));
        libcyrus_config_setstring(CYRUSOPT_PTSCACHE_DB,
                                  config_getstring(IMAPOPT_PTSCACHE_DB));
        libcyrus_config_setstring(CYRUSOPT_PTSCACHE_DB_PATH,
                                  config_getstring(IMAPOPT_PTSCACHE_DB_PATH));
        libcyrus_config_setstring(CYRUSOPT_PTLOADER_SOCK,
                                  config_getstring(IMAPOPT_PTLOADER_SOCK));
        libcyrus_config_setswitch(CYRUSOPT_VIRTDOMAINS,
                                  config_getenum(IMAPOPT_VIRTDOMAINS));
        libcyrus_config_setint(CYRUSOPT_BERKELEY_CACHESIZE,
                               config_getint(IMAPOPT_BERKELEY_CACHESIZE));
        libcyrus_config_setstring(CYRUSOPT_AUTH_MECH,
                                  config_getstring(IMAPOPT_AUTH_MECH));
        libcyrus_config_setint(CYRUSOPT_BERKELEY_LOCKS_MAX,
                               config_getint(IMAPOPT_BERKELEY_LOCKS_MAX));
        libcyrus_config_setint(CYRUSOPT_BERKELEY_TXNS_MAX,
                               config_getint(IMAPOPT_BERKELEY_TXNS_MAX));
        libcyrus_config_setstring(CYRUSOPT_DELETERIGHT,
                                  config_getstring(IMAPOPT_DELETERIGHT));
        libcyrus_config_setstring(CYRUSOPT_SQL_DATABASE,
                                  config_getstring(IMAPOPT_SQL_DATABASE));
        libcyrus_config_setstring(CYRUSOPT_SQL_ENGINE,
                                  config_getstring(IMAPOPT_SQL_ENGINE));
        libcyrus_config_setstring(CYRUSOPT_SQL_HOSTNAMES,
                                  config_getstring(IMAPOPT_SQL_HOSTNAMES));
        libcyrus_config_setstring(CYRUSOPT_SQL_USER,
                                  config_getstring(IMAPOPT_SQL_USER));
        libcyrus_config_setstring(CYRUSOPT_SQL_PASSWD,
                                  config_getstring(IMAPOPT_SQL_PASSWD));
        libcyrus_config_setswitch(CYRUSOPT_SQL_USESSL,
                                  config_getswitch(IMAPOPT_SQL_USESSL));

        /* Not until all configuration parameters are set! */
        libcyrus_init();
    }

    return 0;
}
示例#2
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;
    int dsize;
    char fnamebuf[1024];
    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 =
	    cyrusdb_fromname(libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB));
    }

    if(!state || *state) {
	fatal("bad state pointer passed to ptload()", EC_TEMPFAIL);
    }
    
    strcpy(fnamebuf, config_dir);
    strcat(fnamebuf, PTS_DBFIL);
    r = (the_ptscache_db->open)(fnamebuf, CYRUSDB_CREATE, &ptdb);
    if (r != 0) {
	syslog(LOG_ERR, "DBERROR: opening %s: %s", fnamebuf,
	       cyrusdb_strerror(ret));
        *state = NULL;
	return -1;
    }

    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 = the_ptscache_db->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 nonexistant),
     * 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;
    }
        
    if (libcyrus_config_getstring(CYRUSOPT_PTLOADER_SOCK))
        strcpy(fnamebuf, libcyrus_config_getstring(CYRUSOPT_PTLOADER_SOCK));
    else {
        strcpy(fnamebuf, config_dir);
        strcat(fnamebuf, PTS_DBSOCKET);
    }

    memset((char *)&srvaddr, 0, sizeof(srvaddr));
    srvaddr.sun_family = AF_UNIX;
    strcpy(srvaddr.sun_path, fnamebuf);
    r = nb_connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr), PT_TIMEOUT_SEC);

    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;
    }
        
    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 = the_ptscache_db->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 */
    (the_ptscache_db->close)(ptdb);

    return rc;
}
示例#3
0
EXPORTED int cyrusdb_open(const char *backend, const char *fname,
		 int flags, struct db **ret)
{
    const char *realname;
    struct db *db = xzmalloc(sizeof(struct db));
    int r;

    if (!backend) backend = DEFAULT_BACKEND; /* not used yet, later */
    db->backend = cyrusdb_fromname(backend);

    /* This whole thing is a fricking critical section.  We don't have the API
     * in place for a safe rename of a locked database, so the choices are
     * basically:
     * a) convert each DB layer to support locked database renames while still
     *    in the transaction.  Best, but lots of work.
     * b) rename and hope... unreliable
     * c) global lock around this block of code.  Safest and least efficient.
     */

    /* check if it opens normally.  Horray */
    r = db->backend->open(fname, flags, &db->engine);
    if (r == CYRUSDB_NOTFOUND) goto done; /* no open flags */
    if (!r) goto done;

    /* magic time - we need to work out if the file was created by a different
     * backend and convert if possible */

    realname = cyrusdb_detect(fname);
    if (!realname) {
	syslog(LOG_ERR, "DBERROR: failed to detect DB type for %s (backend %s) (r was %d)",
	       fname, backend, r);
	/* r is still set */
	goto done;
    }

    /* different type */
    if (strcmp(realname, backend)) {
	if (flags & CYRUSDB_CONVERT) {
	    r = cyrusdb_convert(fname, fname, realname, backend);
	    if (r) {
		syslog(LOG_ERR, "DBERROR: failed to convert %s from %s to %s, maybe someone beat us",
		       fname, realname, backend);
	    }
	    else {
		syslog(LOG_NOTICE, "cyrusdb: converted %s from %s to %s",
		       fname, realname, backend);
	    }
	}
	else {
	    syslog(LOG_NOTICE, "cyrusdb: opening %s with backend %s (requested %s)",
		   fname, realname, backend);
	    db->backend = cyrusdb_fromname(realname);
	}
    }
    
    r = db->backend->open(fname, flags, &db->engine);

done:

    if (r) free(db);
    else *ret = db;

    return r;
}