/* * Parse a source route (at-domain-list) */ static int parseaddr_route(char **inp, char **routep) { int c; char *src = *inp; char *dst; SKIPWHITESPACE(src); *routep = dst = src; for (;;) { c = *src++; if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ',' || c == '@') { *dst++ = c; } else if (c == '.') { if (dst > *routep && dst[-1] != '.') *dst++ = c; } else if (Uisspace(c) || c == '(') { src--; SKIPWHITESPACE(src); } else { while (dst > *routep && (dst[-1] == '.' || dst[-1] == ',' || dst[-1] == '@')) dst--; *dst = '\0'; *inp = src; return c; } } }
/* * Parse a domain. If 'commentp' is non-nil, parses any trailing comment. * If the domain is invalid, set invalid to non-zero. */ static int parseaddr_domain(char **inp, char **domainp, char **commentp, int *invalid) { int c; char *src = *inp; char *dst; char *cdst; int comment; if (commentp) *commentp = 0; SKIPWHITESPACE(src); *domainp = dst = src; for (;;) { c = *src++; if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ':') { *dst++ = c; if (commentp) *commentp = 0; } else if (c == '.') { if (dst > *domainp && dst[-1] != '.') *dst++ = c; if (commentp) *commentp = 0; } else if (c == '(') { if (commentp) { *commentp = cdst = src; comment = 1; while (comment && (c = *src)) { src++; if (c == '(') comment++; else if (c == ')') comment--; else if (c == '\\' && (c = *src)) src++; if (comment) *cdst++ = c; } *cdst = '\0'; } else { src--; SKIPWHITESPACE(src); } } else if (c == '@') { /* This domain name is garbage. Continue eating up the characters * until we get to a sane state. */ *invalid = 1; *dst++ = c; if (commentp) *commentp = 0; } else if (!Uisspace(c)) { if (dst > *domainp && dst[-1] == '.') dst--; *dst = '\0'; *inp = src; return c; } } }
static void split_args(struct entry *e, char *buf) { char *p = buf, *q; char *key, *value; for (;;) { /* skip whitespace before arg */ while (Uisspace(*p)) p++; if (!*p) return; key = p; /* parse the key */ for (q = p ; Uisalnum(*q) ; q++) ; if (*q != '=') fatalf(EX_CONFIG, "configuration file %s: " "bad character '%c' in argument on line %d", MASTER_CONFIG_FILENAME, *q, e->lineno); *q++ = '\0'; /* parse the value */ if (*q == '"') { /* quoted string */ value = ++q; q = strchr(q, '"'); if (!q) fatalf(EX_CONFIG, "configuration file %s: missing \" on line %d", MASTER_CONFIG_FILENAME, e->lineno); *q++ = '\0'; } else { /* simple word */ value = q; while (*q && !Uisspace(*q)) q++; if (*q) *q++ = '\0'; } if (e->nargs == MAXARGS) fatalf(EX_CONFIG, "configuration file %s: too many arguments on line %d", MASTER_CONFIG_FILENAME, e->lineno); e->args[e->nargs].key = key; e->args[e->nargs].value = value; e->nargs++; p = q; } }
/* * Parse a domain. If 'commentp' is non-nil, parses any trailing comment */ static int parseaddr_domain(char **inp, char **domainp, char **commentp) { int c; char *src = *inp; char *dst; char *cdst; int comment; if (commentp) *commentp = 0; SKIPWHITESPACE(src); *domainp = dst = src; for (;;) { c = *src++; if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ':') { *dst++ = c; if (commentp) *commentp = 0; } else if (c == '.') { if (dst > *domainp && dst[-1] != '.') *dst++ = c; if (commentp) *commentp = 0; } else if (c == '(') { if (commentp) { *commentp = cdst = src; comment = 1; while (comment && (c = *src)) { src++; if (c == '(') comment++; else if (c == ')') comment--; else if (c == '\\' && (c = *src)) src++; if (comment) *cdst++ = c; } *cdst = '\0'; } else { src--; SKIPWHITESPACE(src); } } else if (!Uisspace(c)) { if (dst > *domainp && dst[-1] == '.') dst--; *dst = '\0'; *inp = src; return c; } } }
static void process_section(FILE *f, int *lnptr, masterconf_process *func, void *rock) { struct entry e; char buf[4096]; int lineno = *lnptr; while (fgets(buf, sizeof(buf), f)) { char *p, *q; lineno++; /* remove EOL character */ if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; /* remove starting whitespace */ for (p = buf; *p && Uisspace(*p); p++); /* remove comments */ q = strchr(p, '#'); if (q) *q = '\0'; /* skip empty lines or all comment lines */ if (!*p) continue; if (*p == '}') break; for (q = p; Uisalnum(*q); q++) ; if (*q) { if (q > p && !Uisspace(*q)) fatalf(EX_CONFIG, "configuration file %s: " "bad character '%c' in name on line %d", MASTER_CONFIG_FILENAME, *q, lineno); *q++ = '\0'; } if (q - p > 0) { /* there's a value on this line */ memset(&e, 0, sizeof(e)); e.lineno = lineno; split_args(&e, q); func(p, &e, rock); } /* end of section? */ if (strchr(q, '}')) break; } *lnptr = lineno; }
/* return malloc'd string containing the address */ static char *parseaddr(char *s) { char *p, *ret; int len; int lmtp_strict_rfc2821 = config_getswitch(IMAPOPT_LMTP_STRICT_RFC2821); p = s; if (*p++ != '<') return 0; /* at-domain-list */ while (*p == '@') { p++; if (*p == '[') { p++; while (Uisdigit(*p) || *p == '.') p++; if (*p++ != ']') return 0; } else { while (Uisalnum(*p) || *p == '.' || *p == '-') p++; } if (*p == ',' && p[1] == '@') p++; else if (*p == ':' && p[1] != '@') p++; else return 0; } /* local-part */ if (*p == '\"') { p++; while (*p && *p != '\"') { if (*p == '\\') { if (!*++p) return 0; } p++; } if (!*p++) return 0; } else { while (*p && *p != '@' && *p != '>') { if (*p == '\\') { if (!*++p) return 0; } else { if (*p & 128 && !lmtp_strict_rfc2821) { /* this prevents us from becoming a backscatter source if our MTA allows 8bit in local-part of adresses. */ *p = 'X'; } if (*p <= ' ' || (*p & 128) || strchr("<>()[]\\,;:\"", *p)) return 0; } p++; } } /* @domain */ if (*p == '@') { p++; if (*p == '[') { p++; while (Uisdigit(*p) || *p == '.') p++; if (*p++ != ']') return 0; } else { while (Uisalnum(*p) || *p == '.' || *p == '-') p++; } } if (*p++ != '>') return 0; if (*p && *p != ' ') return 0; len = p - s; ret = xmalloc(len + 1); memcpy(ret, s, len); ret[len] = '\0'; return ret; }
void masterconf_getsection(const char *section, masterconf_process *f, void *rock) { FILE *infile = NULL; int seclen = strlen(section); int level = 0; int lineno = 0; char buf[4096]; const char *cyrus_path; /* try loading the copy inside CYRUS_PREFIX first */ cyrus_path = getenv("CYRUS_PREFIX"); if (cyrus_path) { strlcpy(buf, cyrus_path, sizeof(buf)); strlcat(buf, MASTER_CONFIG_FILENAME, sizeof(buf)); infile = fopen(buf, "r"); } if (!infile) infile = fopen(MASTER_CONFIG_FILENAME, "r"); if (!infile) fatalf(EX_CONFIG, "can't open configuration file %s: %m", MASTER_CONFIG_FILENAME); while (fgets(buf, sizeof(buf), infile)) { char *p, *q; lineno++; if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; for (p = buf; *p && Uisspace(*p); p++); /* remove comments */ q = strchr(p, '#'); if (q) *q = '\0'; /* skip empty lines or all comment lines */ if (!*p) continue; if (level == 0 && *p == *section && !strncasecmp(p, section, seclen) && !Uisalnum(p[seclen])) { for (p += seclen; *p; p++) { if (*p == '{') level++; if (*p == '}') level--; } /* valid opening; process the section */ if (level == 1) process_section(infile, &lineno, f, rock); continue; } for (; *p; p++) { if (*p == '{') level++; if (*p == '}') level--; } } fclose(infile); }
/* Called before a cyrus application starts (but after command line parameters * are read) */ EXPORTED int cyrus_init(const char *alt_config, const char *ident, unsigned flags, int config_need_data) { char *p; const char *val; const char *prefix; int umaskval = 0; int syslog_opts = LOG_PID; const char *facility; if(cyrus_init_run != NOT_RUNNING) { fatal("cyrus_init called twice!", EC_CONFIG); } else { cyrus_init_run = RUNNING; } cyrus_init_nodb = (flags & CYRUSINIT_NODB); #ifdef LOG_PERROR if ((flags & CYRUSINIT_PERROR)) syslog_opts |= LOG_PERROR; #endif 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, syslog_opts, SYSLOG_FACILITY); /* Load configuration file. This will set config_dir when it finds it */ config_read(alt_config, config_need_data); prefix = config_getstring(IMAPOPT_SYSLOG_PREFIX); facility = config_getstring(IMAPOPT_SYSLOG_FACILITY); /* Reopen the log with the new prefix, if needed */ if (prefix || facility) { char *ident_buf; int facnum = facility ? get_facility(facility) : SYSLOG_FACILITY; if (prefix) ident_buf = strconcat(prefix, "/", ident, (char *)NULL); else ident_buf = xstrdup(ident); closelog(); openlog(ident_buf, syslog_opts, facnum); /* don't free the openlog() string! */ } /* allow debug logging */ if (!config_debug) setlogmask(~LOG_MASK(LOG_DEBUG)); /* 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 */ cyrus_acl_strtomask(config_getstring(IMAPOPT_IMPLICIT_OWNER_RIGHTS), &config_implicitrights); /* XXX and if strtomask fails? */ config_metapartition_files = config_getbitfield(IMAPOPT_METAPARTITION_FILES); val = config_getstring(IMAPOPT_SUPPRESS_CAPABILITIES); if (val) suppressed_capabilities = strarray_split(val, NULL, 0); if (config_getswitch(IMAPOPT_SEARCH_SKIPDIACRIT)) charset_flags |= CHARSET_SKIPDIACRIT; switch (config_getenum(IMAPOPT_SEARCH_WHITESPACE)) { case IMAP_ENUM_SEARCH_WHITESPACE_MERGE: charset_flags |= CHARSET_MERGESPACE; break; case IMAP_ENUM_SEARCH_WHITESPACE_SKIP: charset_flags |= CHARSET_SKIPSPACE; break; default: break; } if (config_getswitch(IMAPOPT_SEARCH_SKIPHTML)) charset_flags |= CHARSET_SKIPHTML; if (config_getswitch(IMAPOPT_RFC2047_UTF8)) charset_flags |= CHARSET_MIME_UTF8; /* Set snippet conversion flags. */ charset_snippet_flags = CHARSET_SNIPPET; if (config_getenum(IMAPOPT_SEARCH_ENGINE) != IMAP_ENUM_SEARCH_ENGINE_XAPIAN) { /* All search engines other than Xapian require escaped HTML */ charset_snippet_flags |= CHARSET_ESCAPEHTML; } if (!cyrus_init_nodb) { /* lookup the database backends */ config_mboxlist_db = config_getstring(IMAPOPT_MBOXLIST_DB); config_quota_db = config_getstring(IMAPOPT_QUOTA_DB); config_subscription_db = config_getstring(IMAPOPT_SUBSCRIPTION_DB); config_annotation_db = config_getstring(IMAPOPT_ANNOTATION_DB); config_seenstate_db = config_getstring(IMAPOPT_SEENSTATE_DB); config_mboxkey_db = config_getstring(IMAPOPT_MBOXKEY_DB); config_duplicate_db = config_getstring(IMAPOPT_DUPLICATE_DB); config_tls_sessions_db = config_getstring(IMAPOPT_TLS_SESSIONS_DB); config_ptscache_db = config_getstring(IMAPOPT_PTSCACHE_DB); config_statuscache_db = config_getstring(IMAPOPT_STATUSCACHE_DB); config_userdeny_db = config_getstring(IMAPOPT_USERDENY_DB); config_zoneinfo_db = config_getstring(IMAPOPT_ZONEINFO_DB); config_conversations_db = config_getstring(IMAPOPT_CONVERSATIONS_DB); config_backup_db = config_getstring(IMAPOPT_BACKUP_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_setstring(CYRUSOPT_AUTH_MECH, config_getstring(IMAPOPT_AUTH_MECH)); 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)); libcyrus_config_setswitch(CYRUSOPT_SKIPLIST_ALWAYS_CHECKPOINT, config_getswitch(IMAPOPT_SKIPLIST_ALWAYS_CHECKPOINT)); /* Not until all configuration parameters are set! */ libcyrus_init(); } return 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; }