/* 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); }
/* 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); }
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); } } }
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; }
/* 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; }