Projects
Kolab:3.4
cyrus-imapd
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 102
View file
cyrus-imapd.spec
Changed
@@ -38,13 +38,13 @@ Name: cyrus-imapd Summary: A high-performance mail server with IMAP, POP3, NNTP and SIEVE support Version: 2.5 -Release: 0.1.dev20141010.gitaf61c13a%{?dist} +Release: 0.1.dev20141017.git9704e5d4%{?dist} License: BSD Group: System Environment/Daemons URL: http://www.cyrusimap.org # Upstream sources -# From af61c13a4259959ef7a09e1d8d6f4743c011b7e9 +# From 9704e5d41981a18f46a63af78cf02c63fe3824a6 Source0: ftp://ftp.andrew.cmu.edu/pub/cyrus/%{_name}-%{real_version}%{?dot_snapshot_version}.tar.gz Source1: cyrus-imapd.imap-2.3.x-conf Source2: cyrus-imapd.cvt_cyrusdb_all
View file
cyrus-imapd-2.5.tar.gz/Makefile.am
Changed
@@ -54,17 +54,37 @@ BUILT_SOURCES = xversion.h \ imap/imap_err.c \ lib/imapopts.c -DISTCLEANFILES = imap/imap_err.c imap/imap_err.h imap/mupdate_err.c imap/mupdate_err.h imap/nntp_err.c imap/nntp_err.h \ +DISTCLEANFILES = imap/imap_err.c \ + imap/imap_err.h \ + imap/mupdate_err.c \ + imap/mupdate_err.h \ + imap/nntp_err.c \ + imap/nntp_err.h \ com_err/et/compile_et \ - perl/annotator/Makefile perl/annotator/Makefile.PL perl/imap/Makefile perl/imap/Makefile.PL perl/sieve/managesieve/Makefile perl/sieve/managesieve/Makefile.PL perl/sieve/scripts/installsieve perl/sieve/scripts/sieveshell \ - sieve/sieve_err.c sieve/sieve_err.h + perl/annotator/Makefile \ + perl/annotator/Makefile.PL \ + perl/imap/Makefile \ + perl/imap/Makefile.PL \ + perl/sieve/managesieve/Makefile \ + perl/sieve/managesieve/Makefile.PL \ + perl/sieve/scripts/installsieve \ + perl/sieve/scripts/sieveshell \ + sieve/sieve_err.c \ + sieve/sieve_err.h MAINTAINERCLEANFILES = \ - doc/murder.png doc/netnews.png \ - doc/man/cyradm.1.html man/imapd.conf.5 man/sieveshell.1 doc/man/sieveshell.1.html \ - imap/lmtpstats.h imap/pushstats.h \ - lib/chartable.c lib/imapopts.h \ - sieve/addr.h sieve/sieve.h + doc/murder.png \ + doc/netnews.png \ + doc/man/cyradm.1.html \ + man/imapd.conf.5 \ + man/sieveshell.1 \ + doc/man/sieveshell.1.html \ + imap/lmtpstats.h \ + imap/pushstats.h \ + lib/chartable.c \ + lib/imapopts.h \ + sieve/addr.h \ + sieve/sieve.h SUBDIRS = . DIST_SUBDIRS = . @@ -391,7 +411,6 @@ com_err/et/config_script \ imap/lmtpstats.snmp \ imap/pushstats.snmp \ - lib/imapoptions \ lib/mkchartable.pl \ lib/test/run \ perl/sieve/scripts/installsieve.pl \ @@ -689,9 +708,14 @@ imap/pushstats.h \ imap/proxy.c \ imap/proxy.h \ - master/service.c \ + master/service.c + +if AUTOCREATE +imap_imapd_SOURCES += \ imap/autocreate.h \ imap/autocreate.c +endif + imap_imapd_LDADD = if SIEVE imap_imapd_LDADD += sieve/libcyrus_sieve.la @@ -748,6 +772,8 @@ imap/mutex.h \ imap/notify.c \ imap/notify.h \ + imap/partlist.c \ + imap/partlist.h \ imap/proc.c \ imap/proc.h \ imap/protocol.h \ @@ -776,6 +802,8 @@ imap/telemetry.h \ imap/tls.c \ imap/tls.h \ + imap/tls_th-lock.c \ + imap/tls_th-lock.h \ imap/upgrade_index.c \ imap/upgrade_index.h \ imap/user.c \ @@ -792,8 +820,6 @@ endif imap_lmtpd_SOURCES = \ - imap/autocreate.c \ - imap/autocreate.h \ imap/lmtpd.c \ imap/lmtpd.h \ imap/lmtpengine.c \ @@ -804,6 +830,13 @@ imap/proxy.c \ imap/spool.c \ master/service.c + +if AUTOCREATE +imap_lmtpd_SOURCES += \ + imap/autocreate.c \ + imap/autocreate.h +endif + imap_lmtpd_LDADD = if SIEVE imap_lmtpd_SOURCES += imap/lmtp_sieve.c imap/lmtp_sieve.h imap/smtpclient.c @@ -831,6 +864,7 @@ imap/mupdate.h \ imap/mupdate-slave.c \ imap/mutex_pthread.c \ + imap/tls_th-lock.c \ master/service-thread.c imap_mupdate_LDADD = $(LD_SERVER_ADD) -lpthread @@ -849,12 +883,17 @@ imap_nntpd_LDADD = $(LD_SERVER_ADD) imap_pop3d_SOURCES = \ - imap/autocreate.c \ - imap/autocreate.h \ imap/mutex_fake.c \ imap/pop3d.c \ imap/proxy.c \ master/service.c + +if AUTOCREATE +imap_pop3d_SOURCES += \ + imap/autocreate.c \ + imap/autocreate.h +endif + imap_pop3d_LDADD = if SIEVE imap_pop3d_LDADD += sieve/libcyrus_sieve.la
View file
cyrus-imapd-2.5.tar.gz/configure.ac
Changed
@@ -1076,6 +1076,12 @@ AC_DEFINE_UNQUOTED(MASTER_PIDFILE, $MASTERPIDFILE,Name of the pidfile for master) dnl +dnl see if we're compiling with autocreate support +dnl +AC_ARG_ENABLE(autocreate, + AS_HELP_STRING(--enable-autocreate, enable autocreate support),,enable_autocreate="no";) +AM_CONDITIONAL(AUTOCREATE, test "$enable_autocreate" != "no") +dnl dnl see if we're compiling with IMAP idled support dnl AC_ARG_ENABLE(idled, @@ -1623,6 +1629,7 @@ event notification: $enable_event_notification gssapi: $gssapi + autocreate: $enable_autocreate idled: $enable_idled kerberos V4: $krb4 murder: $enable_murder
View file
cyrus-imapd-2.5.tar.gz/doc/install-configure.html
Changed
@@ -508,15 +508,15 @@ <li>Add the following to <tt>/etc/imapd.conf</tt> to tell the server where to find the certificate and key files (used for ALL services): -<pre>tls_cert_file: /var/imap/server.pem -tls_key_file: /var/imap/server.pem +<pre>server_cert_file: /var/imap/server.cert +server_key_file: /var/imap/server.key </pre> Optionally, you can use separate certificates and key files for each service: -<pre>servicename_tls_cert_file: /var/imap/imap-server.pem -servicename_tls_key_file: /var/imap/imap-server.pem +<pre>servicename_server_cert_file: /var/imap/imap-server.cert +servicename_server_key_file: /var/imap/imap-server.key </pre> "servicename" here refers to the name of the service as specified
View file
cyrus-imapd-2.5.tar.gz/imap/annotate.c
Changed
@@ -49,6 +49,11 @@ #include <unistd.h> #endif #include <errno.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#elif defined(HAVE_STDINT_H) +# include <stdint.h> +#endif #include <sys/types.h> #include <sys/stat.h> #include <sys/uio.h> @@ -67,6 +72,7 @@ #include "times.h" #include "imap/imap_err.h" #include "mboxlist.h" +#include "partlist.h" #include "util.h" #include "xmalloc.h" #include "ptrarray.h" @@ -1424,11 +1430,37 @@ static void annotation_get_freespace(annotate_state_t *state, struct annotate_entry_list *entry) { - unsigned long tavail; + uint64_t tavail = 0; + struct buf value = BUF_INITIALIZER; + + (void) partlist_local_find_freespace_most(0, NULL, NULL, &tavail, NULL); + buf_printf(&value, "%" PRIuMAX, (uintmax_t)tavail); + output_entryatt(state, entry->name, "", &value); + buf_free(&value); +} + +static void annotation_get_freespace_total(annotate_state_t *state, + struct annotate_entry_list *entry) +{ + uint64_t tavail = 0; + uint64_t ttotal = 0; struct buf value = BUF_INITIALIZER; - (void) find_free_partition(&tavail); - buf_printf(&value, "%lu", tavail); + (void) partlist_local_find_freespace_most(0, NULL, NULL, &tavail, &ttotal); + buf_printf(&value, "%" PRIuMAX ";%" PRIuMAX, (uintmax_t)tavail, (uintmax_t)ttotal); + output_entryatt(state, entry->name, "", &value); + buf_free(&value); +} + +static void annotation_get_freespace_percent_most(annotate_state_t *state, + struct annotate_entry_list *entry) +{ + uint64_t avail = 0; + uint64_t total = 0; + struct buf value = BUF_INITIALIZER; + + (void) partlist_local_find_freespace_most(1, &avail, &total, NULL, NULL); + buf_printf(&value, "%" PRIuMAX ";%" PRIuMAX, (uintmax_t)avail, (uintmax_t)total); output_entryatt(state, entry->name, "", &value); buf_free(&value); } @@ -1961,6 +1993,24 @@ /*set*/NULL, NULL },{ + "/vendor/cmu/cyrus-imapd/freespace/total", + ATTRIB_TYPE_STRING, + BACKEND_ONLY, + ATTRIB_VALUE_SHARED, + 0, + annotation_get_freespace_total, + /*set*/NULL, + NULL + },{ + "/vendor/cmu/cyrus-imapd/freespace/percent/most", + ATTRIB_TYPE_STRING, + BACKEND_ONLY, + ATTRIB_VALUE_SHARED, + 0, + annotation_get_freespace_percent_most, + /*set*/NULL, + NULL + },{ "/vendor/cmu/cyrus-imapd/shutdown", ATTRIB_TYPE_STRING, PROXY_AND_BACKEND,
View file
cyrus-imapd-2.5.tar.gz/imap/autocreate.c
Changed
@@ -145,7 +145,7 @@ } /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */ - if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { + if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT_COMPILED))) { syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it"); do_compile = 1; } @@ -361,7 +361,7 @@ * to generate the global script so that it is not compiled each time then we create it. */ if(do_compile && - config_getswitch(IMAPOPT_GENERATE_COMPILED_SIEVE_SCRIPT)) { + config_getswitch(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT_COMPILE)) { if(!compiled_source_script) { syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf"); @@ -588,7 +588,7 @@ * subscribe user to every shared folder one has the apropriate * permissions. */ - if (config_getswitch(IMAPOPT_AUTOSUBSCRIBE_ALL_SHAREDFOLDERS)) { + if (config_getswitch(IMAPOPT_AUTOCREATE_SUBSCRIBE_SHAREDFOLDERS_ALL)) { /* don't care about errors here, the sub will log them */ mboxlist_findall(namespace, "*", 0, userid, auth_state, autochangesub, &changesub_rock); @@ -597,7 +597,7 @@ /* otherwise, check if there are particular folders to subscribe */ - sub = config_getstring(IMAPOPT_AUTOSUBSCRIBESHAREDFOLDERS); + sub = config_getstring(IMAPOPT_AUTOCREATE_SUBSCRIBE_SHAREDFOLDERS); if (!sub) return; changesub_rock.was_explicit = 1; @@ -618,8 +618,8 @@ const char *userid) { int r = IMAP_MAILBOX_NONEXISTENT; /* default error if we break early */ - int autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA); - int autocreatequotamessage = config_getint(IMAPOPT_AUTOCREATEQUOTAMSG); + int autocreatequota = config_getint(IMAPOPT_AUTOCREATE_QUOTA); + int autocreatequotamessage = config_getint(IMAPOPT_AUTOCREATE_QUOTA_MESSAGES); int n; char *inboxname = mboxname_user_mbox(userid, NULL); struct auth_state *auth_state = NULL; @@ -719,8 +719,8 @@ syslog(LOG_NOTICE, "autocreateinbox: User %s, INBOX was successfully created", userid); - create = strarray_split(config_getstring(IMAPOPT_AUTOCREATEINBOXFOLDERS), SEP, STRARRAY_TRIM); - subscribe = strarray_split(config_getstring(IMAPOPT_AUTOSUBSCRIBEINBOXFOLDERS), SEP, STRARRAY_TRIM); + create = strarray_split(config_getstring(IMAPOPT_AUTOCREATE_INBOX_FOLDERS), SEP, STRARRAY_TRIM); + subscribe = strarray_split(config_getstring(IMAPOPT_AUTOCREATE_SUBSCRIBE_FOLDERS), SEP, STRARRAY_TRIM); /* need to convert all names to internal namespace first */ for (n = 0; n < create->count; n++)
View file
cyrus-imapd-2.5.tar.gz/imap/backend.c
Changed
@@ -472,7 +472,10 @@ #endif /* HAVE_ZLIB */ } -EXPORTED int backend_starttls(struct backend *s, struct tls_cmd_t *tls_cmd) +EXPORTED int backend_starttls( struct backend *s, + struct tls_cmd_t *tls_cmd, + const char *c_cert_file, + const char *c_key_file) { #ifndef HAVE_SSL return -1; @@ -493,7 +496,7 @@ return -1; } - r = tls_init_clientengine(5, "", ""); + r = tls_init_clientengine(5, c_cert_file, c_key_file); if (r == -1) return -1; /* SASL and openssl have different ideas about whether ssf is signed */ @@ -591,7 +594,6 @@ socklen_t addrsize; char buf2048, optstr128, *p; const char *mech_conf, *pass; - if (prot->type != TYPE_STD) return SASL_FAIL; /* set the IP addresses */ @@ -642,6 +644,30 @@ if (!mech_conf) mech_conf = config_getstring(IMAPOPT_FORCE_SASL_CLIENT_MECH); +#ifdef HAVE_SSL + strlcpy(optstr, s->hostname, sizeof(optstr)); + p = strchr(optstr, '.'); + if (p) *p = '\0'; + + strlcat(optstr, "_client_cert", sizeof(optstr)); + const char *c_cert_file = config_getoverflowstring(optstr, NULL); + + if (!c_cert_file) { + c_cert_file = config_getstring(IMAPOPT_TLS_CLIENT_CERT); + } + + strlcpy(optstr, s->hostname, sizeof(optstr)); + p = strchr(optstr, '.'); + if (p) *p = '\0'; + + strlcat(optstr, "_client_key", sizeof(optstr)); + + const char *c_key_file = config_getoverflowstring(optstr, NULL); + if (!c_key_file) { + c_key_file = config_getstring(IMAPOPT_TLS_CLIENT_KEY); + } +#endif + mechlist = backend_get_cap_params(s, CAPA_AUTH); do { @@ -673,7 +699,7 @@ /* If we don't have a usable mech, do TLS and try again */ } while (r == SASL_NOMECH && CAPA(s, CAPA_STARTTLS) && - backend_starttls(s, &prot->u.std.tls_cmd) != -1 && + backend_starttls(s, &prot->u.std.tls_cmd, c_cert_file, c_key_file) != -1 && (mechlist = backend_get_cap_params(s, CAPA_AUTH))); if (r == SASL_OK) { @@ -771,8 +797,9 @@ strcmp(new_mechlist, old_mechlist)) { syslog(LOG_ERR, "possible MITM attack:" "list of available SASL mechanisms changed"); - free(new_mechlist); - free(old_mechlist); + + if (new_mechlist) free(new_mechlist); + if (old_mechlist) free(old_mechlist); return -1; } free(new_mechlist); @@ -967,7 +994,7 @@ prot_setisclient(ret->out, 1); /* Start TLS if required */ - if (do_tls) r = backend_starttls(ret, NULL); + if (do_tls) r = backend_starttls(ret, NULL, NULL, NULL); /* Login to the server */ if (prot->type == TYPE_SPEC)
View file
cyrus-imapd-2.5.tar.gz/imap/backend.h
Changed
@@ -96,7 +96,11 @@ struct protocol_t *prot, const char *userid, sasl_callback_t *cb, const char **auth_status, int logfd); -int backend_starttls(struct backend *s, struct tls_cmd_t *tls_cmd); +int backend_starttls( struct backend *s, + struct tls_cmd_t *tls_cmd, + const char *c_cert_file, + const char *c_key_file); + int backend_ping(struct backend *s, const char *userid); void backend_disconnect(struct backend *s); char *intersect_mechlists(char *config, char *server);
View file
cyrus-imapd-2.5.tar.gz/imap/ctl_cyrusdb.c
Changed
@@ -95,7 +95,7 @@ { FNAME_QUOTADB, &config_quota_db, NULL, 1 }, { FNAME_GLOBALANNOTATIONS, &config_annotation_db, NULL, 1 }, { FNAME_DELIVERDB, &config_duplicate_db, NULL, 0 }, - { FNAME_TLSSESSIONS, &config_tlscache_db, NULL, 0 }, + { FNAME_TLSSESSIONS, &config_tls_sessions_db,NULL, 0 }, { FNAME_PTSDB, &config_ptscache_db, NULL, 0 }, { FNAME_STATUSCACHEDB, &config_statuscache_db, NULL, 0 }, { NULL, NULL, NULL, 0 }
View file
cyrus-imapd-2.5.tar.gz/imap/global.c
Changed
@@ -96,7 +96,7 @@ EXPORTED const char *config_seenstate_db; HIDDEN const char *config_mboxkey_db; EXPORTED const char *config_duplicate_db; -EXPORTED const char *config_tlscache_db; +EXPORTED const char *config_tls_sessions_db; EXPORTED const char *config_ptscache_db; EXPORTED const char *config_statuscache_db; HIDDEN const char *config_userdeny_db; @@ -255,7 +255,7 @@ 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_tlscache_db = config_getstring(IMAPOPT_TLSCACHE_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); @@ -757,67 +757,6 @@ return 1; } -struct part_stats { - char nameMAX_PARTITION_LEN+1; /* name of part with most space */ - unsigned long avail; /* 1k free blocks on freeest part */ - unsigned long tavail; /* total 1k free blocks on server */ - unsigned long fsid512; /* array of file system IDs */ - unsigned nfsid; /* number of file system IDs */ -}; - -/* - * config_foreachoverflowstring() callback which finds spool partition - * with the most available space and totals the space available on - * all partitions. - */ -static void get_part_stats(const char *key, const char *val, void *rock) -{ - struct part_stats *stats = (struct part_stats *) rock; - struct statvfs s; - unsigned long avail; - unsigned i; - - /* not a partition-* config option */ - if (strncmp("partition-", key, 10)) return; - - /* can't stat the given path */ - if (statvfs(val, &s)) return; - - /* eliminate duplicate filesystems */ - for (i = 0; i < stats->nfsid; i++) { - if (s.f_fsid == stats->fsidi) return; - } - stats->fsidstats->nfsid++ = s.f_fsid; - - /* calculate avail space in 1k blocks */ - avail = (unsigned long) (s.f_bavail * (s.f_frsize / 1024.0)); - - /* add to total */ - stats->tavail += avail; - - if (avail > stats->avail) { - /* this part has the most avail space */ - stats->avail = avail; - strlcpy(stats->name, key+10, MAX_PARTITION_LEN); - } -} - -/* - * Returns the name of the spool partition with the most available space. - * Optionally returns the total amount of available space on the server - * (all partitions) in 1k blocks. - */ -HIDDEN char *find_free_partition(unsigned long *tavail) -{ - static struct part_stats stats; - - memset(&stats, 0, sizeof(struct part_stats)); - config_foreachoverflowstring(get_part_stats, &stats); - - if (tavail) *tavail = stats.tavail; - return stats.name; -} - /* Set up the Session ID Buffer */ EXPORTED void session_new_id(void) {
View file
cyrus-imapd-2.5.tar.gz/imap/global.h
Changed
@@ -155,13 +155,15 @@ int getint32(struct protstream *pin, int *num); int getsint32(struct protstream *pin, int *num); int getuint32(struct protstream *pin, unsigned int *num); +int getint64(struct protstream *pin, int64_t *num); +int getsint64(struct protstream *pin, int64_t *num); +int getuint64(struct protstream *pin, uint64_t *num); int getmodseq(struct protstream *pin, modseq_t *num); void eatline(struct protstream *pin, int c); /* Misc utils */ extern int shutdown_file(char *buf, int size); -extern char *find_free_partition(unsigned long *tavail); extern char *find_msgid(char *, char **); #define UNIX_SOCKET "unix socket" extern const char *get_clienthost(int s, @@ -179,7 +181,7 @@ extern const char *config_seenstate_db; extern const char *config_mboxkey_db; extern const char *config_duplicate_db; -extern const char *config_tlscache_db; +extern const char *config_tls_sessions_db; extern const char *config_ptscache_db; extern const char *config_statuscache_db; extern const char *config_userdeny_db;
View file
cyrus-imapd-2.5.tar.gz/imap/imap_proxy.c
Changed
@@ -59,6 +59,7 @@ #include "proxy.h" #include "mboxname.h" #include "mupdate-client.h" +#include "partlist.h" #include "prot.h" #include "util.h" #include "xmalloc.h" @@ -69,6 +70,10 @@ extern char *imapd_userid, *proxy_userid; extern struct namespace imapd_namespace; +static partlist_t *server_parts = NULL; + +static void proxy_part_filldata(partlist_t *part_list, int idx); + static void imap_postcapability(struct backend *s) { if (CAPA(s, CAPA_SASL_IR)) { @@ -1317,103 +1322,118 @@ char *find_free_server(void) { const char *servers = config_getstring(IMAPOPT_SERVERLIST); - unsigned long long int max_avail = 0; char *server = NULL; if (servers) { - char *tmpbuf, *cur_server, *next_server; - char mytag128; - struct backend *be; - - /* make a working copy of the list */ - cur_server = tmpbuf = xstrdup(servers); - - while (cur_server) { - /* eat any leading whitespace */ - while (Uisspace(*cur_server)) cur_server++; - - if (!*cur_server) break; - - /* find end of server */ - if ((next_server = strchr(cur_server, ' ')) || - (next_server = strchr(cur_server, '\t'))) - *next_server++ = '\0'; - - syslog(LOG_DEBUG, "checking free space on server '%s'", cur_server); - - /* connect to server */ - be = proxy_findserver(cur_server, &imap_protocol, - proxy_userid, &backend_cached, - &backend_current, &backend_inbox, imapd_in); - if (be) { - unsigned long long int avail = 0; - static struct buf avail_buf; - int c; - - /* fetch annotation from remote */ - proxy_gentag(mytag, sizeof(mytag)); - prot_printf(be->out, - "%s GETANNOTATION \"\" " - "\"/vendor/cmu/cyrus-imapd/freespace\" " - "\"value.shared\"\r\n", mytag); - prot_flush(be->out); - - for (/* each annotation response */;;) { - /* read a line */ - c = prot_getc(be->in); - if (c != '*') break; - c = prot_getc(be->in); - if (c != ' ') { /* protocol error */ c = EOF; break; } - - c = chomp(be->in, - "ANNOTATION \"\" " - "\"/vendor/cmu/cyrus-imapd/freespace\" " - "(\"value.shared\" "); - - if (c == EOF) { - /* we don't care about this response */ - eatline(be->in, c); - continue; - } - - /* read amount of free space */ - c = getastring(be->in, be->out, &avail_buf); + if (!server_parts) { + server_parts = xzmalloc(sizeof(partlist_t)); + + partlist_initialize( + server_parts, + proxy_part_filldata, + NULL, + servers, + NULL, + partlist_getmode(config_getstring(IMAPOPT_SERVERLIST_SELECT_MODE)), + config_getint(IMAPOPT_SERVERLIST_SELECT_SOFT_USAGE_LIMIT), + config_getint(IMAPOPT_SERVERLIST_SELECT_USAGE_REINIT) + ); - if (c != '"') { c = EOF; break; } - eatline(be->in, c); /* we don't care about the rest of the line */ - } - - if (c != EOF) { - prot_ungetc(c, be->in); + } - /* we should be looking at the tag now */ - eatline(be->in, c); - } + server = (char *)partlist_select_value(server_parts); + } - if (c == EOF) { - /* uh oh, we're not happy */ - fatal("Lost connection to backend", EC_UNAVAILABLE); - } + return server; +} - avail = strtoull(avail_buf.s, NULL, 10); - if (avail > max_avail) { - syslog(LOG_DEBUG, "freespace on %s (%llu) greater than current maximum on %s (%llu)", cur_server, avail, server, max_avail); - server = cur_server; - max_avail = avail; - } else { - syslog(LOG_DEBUG, "freespace on %s (%llu) still the current maximum (not %s (%llu))", server, max_avail, cur_server, avail); - } +static void proxy_part_filldata(partlist_t *part_list, int idx) +{ + char mytag128; + struct backend *be; + partitem_t *item = &part_list->itemsidx; + + item->id = 0; + item->available = 0; + item->total = 0; + item->quota = 0.; + + syslog(LOG_DEBUG, "checking free space on server '%s'", item->value); + + /* connect to server */ + be = proxy_findserver(item->value, &imap_protocol, + proxy_userid, &backend_cached, + &backend_current, &backend_inbox, imapd_in); + + if (be) { + uint64_t server_available = 0; + uint64_t server_total = 0; + int c; + + /* fetch annotation from remote */ + proxy_gentag(mytag, sizeof(mytag)); + if (part_list->mode == PART_SELECT_MODE_FREESPACE_MOST) { + prot_printf(be->out, + "%s GETANNOTATION \"\" " + "\"/vendor/cmu/cyrus-imapd/freespace/total\" " + "\"value.shared\"\r\n", mytag); + } + else { + prot_printf(be->out, + "%s GETANNOTATION \"\" " + "\"/vendor/cmu/cyrus-imapd/freespace/percent/most\" " + "\"value.shared\"\r\n", mytag); + } + prot_flush(be->out); + + for (/* each annotation response */;;) { + /* read a line */ + c = prot_getc(be->in); + if (c != '*') break; + c = prot_getc(be->in); + if (c != ' ') { /* protocol error */ c = EOF; break; } + + if (part_list->mode == PART_SELECT_MODE_FREESPACE_MOST) { + c = chomp(be->in, + "ANNOTATION \"\" " + "\"/vendor/cmu/cyrus-imapd/freespace/total\" " + "(\"value.shared\" "); + } else { + c = chomp(be->in, + "ANNOTATION \"\" " + "\"/vendor/cmu/cyrus-imapd/freespace/percent/most\" " + "(\"value.shared\" "); + } + if ((c == EOF) || (c != '\"')) { + /* we don't care about this response */ + eatline(be->in, c); + continue; } - /* move to next server */ - cur_server = next_server; + /* read available */ + c = getuint64(be->in, &server_available); + if (c != ';') { c = EOF; break; } + + /* read total */ + c = getuint64(be->in, &server_total); + if (c != '\"') { c = EOF; break; } + eatline(be->in, c); /* we don't care about the rest of the line */ } + if (c != EOF) { + prot_ungetc(c, be->in); - if (server) server = xstrdup(server); + /* we should be looking at the tag now */ + eatline(be->in, c); + } + if (c == EOF) { + /* uh oh, we're not happy */ + fatal("Lost connection to backend", EC_UNAVAILABLE); + } - free(tmpbuf); + /* unique id */ + item->id = idx; + item->available = server_available; + item->total = server_total; } - - return server; }
View file
cyrus-imapd-2.5.tar.gz/imap/imapd.c
Changed
@@ -70,7 +70,9 @@ #include "annotate.h" #include "append.h" #include "auth.h" +#ifdef USE_AUTOCREATE #include "autocreate.h" +#endif // USE_AUTOCREATE #include "assert.h" #include "backend.h" #include "bsearch.h" @@ -95,6 +97,7 @@ #include "mboxname.h" #include "mbdump.h" #include "mupdate-client.h" +#include "partlist.h" #include "proc.h" #include "quota.h" #include "seen.h" @@ -1082,6 +1085,8 @@ statuscache_done(); } + partlist_local_done(); + if (imapd_in) { /* Flush the incoming buffer */ prot_NONBLOCK(imapd_in); @@ -2245,6 +2250,7 @@ } } +#ifdef USE_AUTOCREATE /* * Autocreate Inbox and subfolders upon login */ @@ -2253,7 +2259,7 @@ if (imapd_userisadmin) return; if (imapd_userisproxyadmin) return; - if (config_getint(IMAPOPT_AUTOCREATEQUOTA)) { + if (config_getint(IMAPOPT_AUTOCREATE_QUOTA)) { char *inboxname = mboxname_user_mbox(imapd_userid, NULL); int r = mboxlist_lookup(inboxname, NULL, NULL); free(inboxname); @@ -2261,6 +2267,7 @@ autocreate_user(&imapd_namespace, imapd_userid); } } +#endif // USE_AUTOCREATE static void authentication_success(void) { @@ -2301,7 +2308,9 @@ mboxevent_free(&mboxevent); } +#ifdef USE_AUTOCREATE autocreate_inbox(); +#endif // USE_AUTOCREATE } static int checklimits(const char *tag) @@ -3027,7 +3036,7 @@ if (!imapd_compress_done && !imapd_tls_comp) { prot_printf(imapd_out, " COMPRESS=DEFLATE"); } -#endif +#endif // HAVE_ZLIB for (i = 0 ; i < QUOTA_NUMRESOURCES ; i++) prot_printf(imapd_out, " X-QUOTA=%s", quota_namesi); @@ -5332,7 +5341,6 @@ { int r = 0; char mailboxnameMAX_MAILBOX_BUFFER; - int autocreatequotastorage; int mbtype = 0; const char *partition = NULL; const char *server = NULL; @@ -5574,10 +5582,11 @@ NULL // struct mailbox mailboxptr ); +#ifdef USE_AUTOCREATE // Clausing autocreate for the INBOX if (r == IMAP_PERMISSION_DENIED) { if (strcasecmp(name, "INBOX")) { - if ((autocreatequotastorage = config_getint(IMAPOPT_AUTOCREATEQUOTA))) { + if ((int autocreatequotastorage = config_getint(IMAPOPT_AUTOCREATE_QUOTA))) { r = mboxlist_createmailbox( mailboxname, 0, @@ -5597,7 +5606,7 @@ goto done; } - int autocreatequotamessage = config_getint(IMAPOPT_AUTOCREATEQUOTAMSG); + int autocreatequotamessage = config_getint(IMAPOPT_AUTOCREATE_QUOTA_MESSAGES); if ((autocreatequotastorage > 0) || (autocreatequotamessage > 0)) { int newquotasQUOTA_NUMRESOURCES; @@ -5634,6 +5643,18 @@ } // (r == IMAP_PERMISSION_DENIED) +#else // USE_AUTOCREATE + if (r) { + prot_printf(imapd_out, "%s NO %s\r\n", tag, error_message(r)); + goto done; + + } else { // (r) + prot_printf(imapd_out, "%s OK %s\r\n", tag, error_message(IMAP_OK_COMPLETED)); + goto done; + + } // (r) +#endif // USE_AUTOCREATE + if (specialuse.len) { r = annotatemore_write(mailboxname, "/specialuse", imapd_userid, &specialuse); if (r) { @@ -6541,7 +6562,9 @@ goto freeargs; } +#ifdef USE_AUTOCREATE autocreate_inbox(); +#endif // USE_AUTOCREATE return; @@ -7474,7 +7497,7 @@ fatal("cmd_starttls() executed, but starttls isn't implemented!", EC_SOFTWARE); } -#endif /* HAVE_SSL */ +#endif // (OPENSSL_VERSION_NUMBER >= 0x0090800fL) static int parse_statusitems(unsigned *statusitemsp, const char **errstr) { @@ -12328,7 +12351,7 @@ "%s NO COMPRESSIONACTIVE %s active via TLS\r\n", tag, SSL_COMP_get_name(imapd_tls_comp)); } -#endif +#endif defined(HAVE_SSL) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL) else if (strcasecmp(alg, "DEFLATE")) { prot_printf(imapd_out, "%s NO Unknown COMPRESS algorithm: %s\r\n", tag, alg);
View file
cyrus-imapd-2.5.tar.gz/imap/imapparse.c
Changed
@@ -297,7 +297,80 @@ return c; } -/* This would be called getuint64() if +EXPORTED int getint64(struct protstream *pin, int64_t *num) +{ + int64_t result = 0; + char c; + int gotchar = 0; + + /* LLONG_MAX == 9223372036854775807LL */ + while ((c = prot_getc(pin)) != EOF && cyrus_isdigit(c)) { + if (result > 922337203685477580LL || (result == 922337203685477580LL && (c > '7'))) + fatal("num too big", EC_IOERR); + result = result * 10 + c - '0'; + gotchar = 1; + } + + if (!gotchar) + return EOF; + + *num = result; + + return c; +} + +/* Like getint64() but explicitly signed, i.e. negative numbers + * are accepted */ +EXPORTED int getsint64(struct protstream *pin, int64_t *num) +{ + int c; + int sgn = 1; + + c = prot_getc(pin); + if (c == EOF) + return EOF; + + if (c == '-') + sgn = -1; + else if (c == '+') + sgn = 1; + else + prot_ungetc(c, pin); + + c = getint64(pin, num); + if (c == EOF) + return EOF; + /* this is slightly buggy: the number LLONG_MIN == -9223372036854775808LL + * is a valid signed 64b int but is not accepted */ + if (sgn < 0) + *num = - (*num); + return c; +} + +/* can't flag with -1 if there is no number here, so return EOF */ +EXPORTED int getuint64(struct protstream *pin, uint64_t *num) +{ + uint64_t result = 0; + char c; + int gotchar = 0; + + /* ULLONG_MAX == 18446744073709551615ULL */ + while ((c = prot_getc(pin)) != EOF && cyrus_isdigit(c)) { + if (result > 1844674407370955161ULL || (result == 1844674407370955161ULL && (c > '5'))) + fatal("num too big", EC_IOERR); + result = result * 10 + c - '0'; + gotchar = 1; + } + + if (!gotchar) + return EOF; + + *num = result; + + return c; +} + +/* This would call getuint64() if * all were right with the world */ EXPORTED int getmodseq(struct protstream *pin, modseq_t *num) {
View file
cyrus-imapd-2.5.tar.gz/imap/lmtp_sieve.c
Changed
@@ -951,7 +951,7 @@ if (config_getswitch(IMAPOPT_ANYSIEVEFOLDER)) { createsievefolder = 1; } - else if ((subf = config_getstring(IMAPOPT_AUTOSIEVEFOLDERS)) != NULL) { + else if ((subf = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_FOLDERS)) != NULL) { strarray_t *create = strarray_split(subf, SEP, STRARRAY_TRIM); for (n = 0; n < create->count; n++) {
View file
cyrus-imapd-2.5.tar.gz/imap/lmtpd.c
Changed
@@ -67,7 +67,9 @@ #include "append.h" #include "assert.h" #include "auth.h" +#ifdef USE_AUTOCREATE #include "autocreate.h" +#endif #include "backend.h" #include "duplicate.h" #include "exitcodes.h" @@ -119,7 +121,9 @@ static FILE *spoolfile(message_data_t *msgdata); static void removespool(message_data_t *msgdata); +#ifdef USE_AUTOCREATE static int autocreate_inbox(const char *user, const char *domain); +#endif /* current namespace */ static struct namespace lmtpd_namespace; @@ -1044,7 +1048,7 @@ exit(code); } - +#ifdef USE_AUTOCREATE /* * Autocreate Inbox and subfolders upon login */ @@ -1073,11 +1077,11 @@ /* * Check for autocreatequota and createonpost */ - if (!config_getint(IMAPOPT_AUTOCREATEQUOTA)) { + if (!config_getint(IMAPOPT_AUTOCREATE_QUOTA)) { free(username); return IMAP_MAILBOX_NONEXISTENT; } - if (!config_getswitch(IMAPOPT_CREATEONPOST)) { + if (!config_getswitch(IMAPOPT_AUTOCREATE_POST)) { free(username); return IMAP_MAILBOX_NONEXISTENT; } @@ -1088,6 +1092,7 @@ return r; } +#endif // USE_AUTOCREATE static int verify_user(const char *user, const char *domain, char *mailbox, quota_t quotastorage_check, quota_t quotamessage_check, @@ -1133,11 +1138,13 @@ */ r = mlookup(namebuf, &mbentry); +#ifdef USE_AUTOCREATE /* If user mailbox does not exist, then invoke autocreate inbox function */ if (r == IMAP_MAILBOX_NONEXISTENT) { r = autocreate_inbox(user, domain); if (!r) r = mlookup(namebuf, &mbentry); } +#endif // USE_AUTOCREATE if (r == IMAP_MAILBOX_NONEXISTENT && !user && config_getswitch(IMAPOPT_LMTP_FUZZY_MAILBOX_MATCH) &&
View file
cyrus-imapd-2.5.tar.gz/imap/mboxevent.c
Changed
@@ -55,6 +55,7 @@ #include "annotate.h" #include "assert.h" #include "exitcodes.h" +#include "global.h" #include "imapurl.h" #include "libconfig.h" #include "map.h"
View file
cyrus-imapd-2.5.tar.gz/imap/mboxlist.c
Changed
@@ -70,6 +70,7 @@ #include "imap/imap_err.h" #include "xmalloc.h" #include "xstrlcpy.h" +#include "partlist.h" #include "xstrlcat.h" #include "user.h" @@ -588,12 +589,12 @@ if (!part && config_defpartition) part = config_defpartition; - /* look for partition with free space */ + /* look for most fitting partition */ if (!part) - part = find_free_partition(NULL); + part = partlist_local_select(); /* Configuration error */ - if (strlen(part) > MAX_PARTITION_LEN) + if (!part || (strlen(part) > MAX_PARTITION_LEN)) goto err; if (!config_partitiondir(part))
View file
cyrus-imapd-2.5.tar.gz/imap/mupdate.c
Changed
@@ -84,6 +84,7 @@ #include "nonblock.h" #include "prot.h" #include "tls.h" +#include "tls_th-lock.h" #include "util.h" #include "version.h" #include "xmalloc.h" @@ -553,6 +554,10 @@ database_init(); +#ifdef HAVE_SSL + CRYPTO_thread_setup(); +#endif + if (!masterp) { r = pthread_create(&t, NULL, &mupdate_client_start, NULL); if (r == 0) { @@ -598,6 +603,9 @@ /* Called by service API to shut down the service */ void service_abort(int error) { +#ifdef HAVE_SSL + CRYPTO_thread_cleanup(); +#endif shut_down(error); }
View file
cyrus-imapd-2.5.tar.gz/imap/nntpd.c
Changed
@@ -92,6 +92,7 @@ #include "mkgmtime.h" #include "mupdate-client.h" #include "imap/nntp_err.h" +#include "partlist.h" #include "proc.h" #include "prot.h" #include "proxy.h" @@ -659,6 +660,8 @@ idle_done(); + partlist_local_done(); + if (nntp_in) { prot_NONBLOCK(nntp_in); prot_fill(nntp_in);
View file
cyrus-imapd-2.5.tar.gz/imap/partlist.c
Added
@@ -0,0 +1,628 @@ +/* partlist.c - Partition/backend selection functions + * + * Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: $ + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <sys/statvfs.h> +#include <sys/types.h> + +#include "libconfig.h" +#include "partlist.h" +#include "xmalloc.h" + + +#define FREE(var) if (var) { free(var); (var) = NULL; } + +static void partlist_bump_action(partlist_t *part_list); +static int partlist_selectpart_index(partlist_t *part_list); +static void partlist_compute_quota(partlist_t *part_list); +static void partlist_fill(const char *key, const char *value, void *rock); +static void partition_filldata(partlist_t *part_list, int idx); + +typedef struct partlist_conf { + partlist_t *part_list; + const char *key_prefix; + size_t excluded_count; + const char **excluded_item; +} partlist_conf_t; + +static partlist_t *partlist_local = NULL; + + +EXPORTED partmode_t partlist_getmode(const char *mode) +{ + if (!strcmp(mode, "freespace-most")) { + return PART_SELECT_MODE_FREESPACE_MOST; + } + else if (!strcmp(mode, "freespace-percent-most")) { + return PART_SELECT_MODE_FREESPACE_PERCENT_MOST; + } + else if (!strcmp(mode, "freespace-percent-weighted")) { + return PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED; + } + else if (!strcmp(mode, "freespace-percent-weighted-delta")) { + return PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED_DELTA; + } + else { + return PART_SELECT_MODE_RANDOM; + } +} + + +EXPORTED void partlist_initialize(partlist_t *part_list, cb_part_filldata filldata, + const char *key_prefix, const char *key_value, + const char *excluded, partmode_t mode, + int soft_usage_limit, int reinit) +{ + partlist_conf_t part_list_conf; + char *excluded_parts = NULL; + + srand(time(NULL)); + memset(&part_list_conf, 0, sizeof(part_list_conf)); + memset(part_list, 0, sizeof(partlist_t)); + + part_list->mode = mode; + part_list->filldata = (filldata ? filldata : partition_filldata); + part_list->size = 0; + part_list->soft_usage_limit = soft_usage_limit; + part_list->reinit = reinit; + + part_list_conf.part_list = part_list; + part_list_conf.key_prefix = key_prefix; + + if (excluded && (strlen(excluded) > 0)) { + char *item = NULL; + char *lasts; + + excluded_parts = xstrdup(excluded); + item = strtok_r(excluded_parts, " ,\t", &lasts); + while (item) { + part_list_conf.excluded_item = (const char **)xrealloc(part_list_conf.excluded_item, (part_list_conf.excluded_count+1) * sizeof(const char *)); + part_list_conf.excluded_itempart_list_conf.excluded_count++ = item; + item = strtok_r(NULL, " ,\t", &lasts); + } + } + + if (key_value) { + char *items = xstrdup(key_value); + char *item = NULL; + char *lasts; + + item = strtok_r(items, " ,\t", &lasts); + while (item) { + partlist_fill(item, item, &part_list_conf); + item = strtok_r(NULL, " ,\t", &lasts); + } + + FREE(items); + } + else { + config_foreachoverflowstring(partlist_fill, &part_list_conf); + } + + /* excluded items no more necessary */ + FREE(excluded_parts); + FREE(part_list_conf.excluded_item); + + partlist_compute_quota(part_list); +} + + +static void partlist_free(partlist_t *part_list) +{ + int i; + + if (part_list == NULL) { + return; + } + + for (i = 0; i < part_list->size; i++) { + FREE(part_list->itemsi.item); + FREE(part_list->itemsi.value); + } + FREE(part_list->items); + part_list->size = -1; +} + + +static void partlist_bump_action(partlist_t *part_list) +{ + if ((part_list->reinit > 0) && (part_list->reinit_counter++ >= part_list->reinit)) { + partlist_compute_quota(part_list); + part_list->reinit_counter = 1; + } +} + + +static int partlist_getavailable(partlist_t *part_list) +{ + int count = 0; + int idx; + + for (idx = 0; idx < part_list->size; idx++) { + if (part_list->itemsidx.quota != 0.) { + count++; + } + } + + /* When nothing available, refresh quotas after a while */ + if (!count) { + partlist_bump_action(part_list); + } + + return count; +} + + +static const char *partlist_select_item(partlist_t *part_list) +{ + int idx = partlist_selectpart_index(part_list); + + return (idx == -1 ? NULL : part_list->itemsidx.item); +} + + +EXPORTED const char *partlist_select_value(partlist_t *part_list) +{ + int idx = partlist_selectpart_index(part_list); + + return (idx == -1 ? NULL : part_list->itemsidx.value); +} + + +static int partlist_selectpart_index(partlist_t *part_list) +{ + int i; + int do_random = 0; + int ret = -1; + int available; + + if (part_list->size <= 0) { + return -1; + } + + available = partlist_getavailable(part_list); + if (!available) { + return -1; + } + + partlist_bump_action(part_list); + + if ((part_list->mode == PART_SELECT_MODE_RANDOM) || part_list->force_random) { + do_random = 1; + } + else { + double sq = 0.; + double val = 0.; + uint64_t max_available = 0; + + switch (part_list->mode) { + case PART_SELECT_MODE_FREESPACE_MOST: + for (i = 0; i < part_list->size; i++) { + if (part_list->itemsi.quota == 0.) { + continue; + } + + if (part_list->itemsi.available > max_available) { + ret = i; + max_available = part_list->itemsi.available; + } + } + break; + + case PART_SELECT_MODE_FREESPACE_PERCENT_MOST: + for (i = 0 ;i < part_list->size; i++) { + if (part_list->itemsi.quota == 0.) { + continue; + } + + if (part_list->itemsi.quota > val) { + ret = i; + val = part_list->itemsi.quota; + } + } + break; + + case PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED: + case PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED_DELTA: + /* random in 0,100 */ + val = 100. * ((double)rand() / (RAND_MAX + 1.)); + + for (i = 0; i < part_list->size; i++) { + sq += part_list->itemsi.quota; + ret = i; + if (val < sq) { + break; + } + } + + /* sanity check: make sure we did not pick an unwanted entry + and get last wanted one (or -1 if all items are unwanted) */ + while ((part_list->itemsret.quota == 0.) && (--ret >= 0)) + ; + break; + + default: + /* sanity check */ + do_random = 1; + break; + } + } + + if (do_random) { + i = rand() % available; + ret = 0; + while (i--) { + while (part_list->items++ret.quota == 0.) + ; + } + } + + return ret; +} + + +static void partlist_compute_quota(partlist_t *part_list) +{ + int i; + int j; + unsigned long id; + double percent_available; + double quota_total = 0; + double quota_min = 100.; + double quota_min_limit = 100.; + double soft_quota_limit = 100. - part_list->soft_usage_limit; + int soft_quota_limit_use = 0; + partmode_t mode = part_list->mode; + + part_list->force_random = 0; + + if (mode == PART_SELECT_MODE_RANDOM) { + /* No need to check items usage */ + for (i = 0; i < part_list->size; i++) { + part_list->itemsi.quota = 50.0; + } + + return; + } + + for (i = 0; i < part_list->size; i++) { + part_list->filldata(part_list, i); + + if ((mode == PART_SELECT_MODE_FREESPACE_MOST) || (mode == PART_SELECT_MODE_FREESPACE_PERCENT_MOST)) { + id = part_list->itemsi.id; + for (j = i-1; j >= 0; j--) { + if (id == part_list->itemsj.id) { + /* duplicate id, keep only the first of its kind */ + part_list->itemsi.quota = 0.; + break; + } + } + if (j >= 0) { + /* duplicate id, skip */ + continue; + } + } + /* else: other modes does not need id de-duplication */ + + percent_available = -1.; + if (part_list->itemsi.total > 0) { + percent_available = (part_list->itemsi.available * (double)100. / part_list->itemsi.total); + } + + /* ensure we got a consistent value */ + if ((percent_available<0.) || (percent_available>100.)) { + /* fallback to random mode */ + part_list->force_random = 1; + break; + } + + part_list->itemsi.quota = percent_available; + /* Note: beware floating-point precision between variables stored in + * memory and CPU registers. From now on, do not use percent_available. + */ + + if (part_list->itemsi.quota < quota_min) { + quota_min = part_list->itemsi.quota; + } + + /* check free space against limit */ + if (part_list->itemsi.quota <= soft_quota_limit) { + /* entry below limit, will not be taken into account (unless all + entries are below limit) */ + continue; + } + /* at least one entry is ok, quota limit can be applied */ + soft_quota_limit_use = 1; + if (part_list->itemsi.quota < quota_min_limit) { + quota_min_limit = part_list->itemsi.quota; + } + } + + if (soft_quota_limit_use) { + quota_min = quota_min_limit; + } + + for (i = 0; i < part_list->size; i++) { + if (part_list->force_random) { + part_list->itemsi.quota = 50.0; + } + else if (soft_quota_limit_use && (part_list->itemsi.quota <= soft_quota_limit)) { + /* entry is below limit, make sure not to select it */ + part_list->itemsi.quota = 0.; + } + else if (mode == PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED_DELTA) { + /* Note: according to previous tests, current item quota shall be + * >= quota_min. Even with differences in floating-point precision + * between variables stored in memory and CPU registers, the former + * would be slightly under the latter, which would not matter since + * we are about to add .5. + */ + + /* the goal is to reach the level of the most used volume */ + part_list->itemsi.quota -= quota_min; + /* but prevent the most used one to starve */ + part_list->itemsi.quota += .5; + + /* Sanity check */ + if (part_list->itemsi.quota < 0) { + part_list->itemsi.quota = 0.; + } + } + } + + if (part_list->force_random) { + /* nothing else to do */ + return; + } + + if ((mode == PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED) || (mode == PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED_DELTA)) { + /* normalize */ + for (i = 0; i < part_list->size; i++) { + quota_total += part_list->itemsi.quota; + } + if (quota_total != 0) { + for (i = 0; i < part_list->size; i++) { + part_list->itemsi.quota = (part_list->itemsi.quota * 100.) / quota_total; + } + } + } +} + + +static void partlist_fill(const char *key, const char *value, void *rock) +{ + partlist_conf_t *part_list_conf = (partlist_conf_t *)rock; + partlist_t *part_list = part_list_conf->part_list; + int key_prefix_len = (part_list_conf->key_prefix ? strlen(part_list_conf->key_prefix) : 0); + int i; + + if (key_prefix_len) { + if ((strncmp(part_list_conf->key_prefix, key, key_prefix_len) != 0) || (strlen(key) <= key_prefix_len)) { + return; + } + } + + for (i = 0; i < part_list_conf->excluded_count; i++) { + if (!strcmp(key+key_prefix_len, (part_list_conf->excluded_item)i)) { + return; + } + } + + part_list->items = (partitem_t *)xrealloc(part_list->items, (part_list->size+1) * sizeof(partitem_t)); + memset(&part_list->itemspart_list->size, 0, sizeof(partitem_t)); + part_list->itemspart_list->size.item = xstrdup(key + key_prefix_len); + part_list->itemspart_list->size.value = xstrdup(value); + /* item usage data will be filled later */ + + part_list->size++; +} + + +/** + * \brief Fills partition data. + * + * @param inout part_list items list structure + * @param in idx item index + */ +static void partition_filldata(partlist_t *part_list, int idx) +{ + partitem_t *item = &part_list->itemsidx; + struct statvfs stat; + + item->id = 0; + item->available = 0; + item->total = 0; + item->quota = 0.; + + if (statvfs(item->value, &stat)) { + /* statvfs error */ + int error = 1; + + if (errno == ENOENT) { + /* try to create path */ + if ((cyrus_mkdir(item->value, 0755) == -1) || (mkdir(item->value, 0755) == -1)) { + syslog(LOG_ERR, "IOERROR: creating %s: %m", item->value); + return; + } + else { + error = statvfs(item->value, &stat) ? 1 : 0; + } + } + + if (error) { + syslog(LOG_ERR, "IOERROR: statvfs%s: %m", item->value); + return; + } + } + + if (stat.f_blocks <= 0) { + /* error retrieving statvfs info */ + syslog(LOG_ERR, "IOERROR: statvfs%s: non-positive number of blocks", item->value); + return; + } + + item->id = stat.f_fsid; + item->available = (uint64_t)(stat.f_bavail * (stat.f_frsize / 1024.)); + item->total = (uint64_t)(stat.f_blocks * (stat.f_frsize / 1024.)); +} + + +static void partlist_local_init(void) +{ + if (partlist_local) { + /* already done */ + return; + } + + partlist_local = xzmalloc(sizeof(partlist_t)); + partlist_initialize( + partlist_local, + NULL, + "partition-", + NULL, + config_getstring(IMAPOPT_PARTITION_SELECT_EXCLUDE), + partlist_getmode(config_getstring(IMAPOPT_PARTITION_SELECT_MODE)), + config_getint(IMAPOPT_PARTITION_SELECT_SOFT_USAGE_LIMIT), + config_getint(IMAPOPT_PARTITION_SELECT_USAGE_REINIT) + ); +} + + +HIDDEN const char *partlist_local_select(void) +{ + /* lazy loading */ + if (!partlist_local) { + partlist_local_init(); + } + + return (char *)partlist_select_item(partlist_local); +} + + +HIDDEN const char *partlist_local_find_freespace_most(int percent, uint64_t *available, + uint64_t *total, uint64_t *tavailable, + uint64_t *ttotal) +{ + const char *item = NULL; + unsigned long id; + uint64_t available_tmp; + uint64_t total_tmp; + double percent_available; + uint64_t available_max = 0; + double percent_available_max = 0.; + int i; + int j; + + /* lazy loading */ + if (!partlist_local) { + partlist_local_init(); + } + + if (available) *available = 0; + if (total) *total = 0; + if (tavailable) *tavailable = 0; + if (ttotal) *ttotal = 0; + + partlist_bump_action(partlist_local); + + for (i = 0; i < partlist_local->size; i++) { + if (partlist_local->itemsi.quota == 0.) { + continue; + } + + id = partlist_local->itemsi.id; + for (j = i-1; j >= 0; j--) { + if (id == partlist_local->itemsj.id) { + /* duplicate id */ + break; + } + } + if (j >= 0) { + /* duplicate id, skip */ + continue; + } + + available_tmp = partlist_local->itemsi.available; + total_tmp = partlist_local->itemsi.total; + + if (tavailable) *tavailable += available_tmp; + if (ttotal) *ttotal += total_tmp; + + if (percent) { + percent_available = 0.; + if (total_tmp > 0) { + percent_available = (available_tmp * (double)100. / total_tmp); + } + if ((percent_available > percent_available_max) && (percent_available <= 100.)) { + percent_available_max = percent_available; + item = partlist_local->itemsi.item; + if (available) *available = available_tmp; + if (total) *total = total_tmp; + } + } + else { + if (available_tmp > available_max) { + available_max = available_tmp; + item = partlist_local->itemsi.item; + if (available) *available = available_tmp; + if (total) *total = total_tmp; + } + } + } + + return item; +} + + +EXPORTED void partlist_local_done(void) +{ + if (partlist_local) { + partlist_free(partlist_local); + free(partlist_local); + partlist_local = NULL; + } +}
View file
cyrus-imapd-2.5.tar.gz/imap/partlist.h
Added
@@ -0,0 +1,158 @@ +/* partlist.h - Partition/backend selection functions + * + * Copyright (c) 1994-2010 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: $ + */ + +#include "config.h" + + +typedef struct partitem { + /** Item name */ + char *item; + /** Item value */ + char *value; + /** Item underlying id (filesystem id) */ + unsigned long id; + /** Item available space (KiB) */ + uint64_t available; + /** Item total space (KiB) */ + uint64_t total; + /** Item selection data */ + double quota; +} partitem_t; + +typedef enum partmode { + /** Random */ + PART_SELECT_MODE_RANDOM, + /** Most free space. */ + PART_SELECT_MODE_FREESPACE_MOST, + /** Most free space (percent). */ + PART_SELECT_MODE_FREESPACE_PERCENT_MOST, + /** Weighted free space (percent) */ + PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED, + /** Weighted free space (percent) delta */ + PART_SELECT_MODE_FREESPACE_PERCENT_WEIGHTED_DELTA +} partmode_t; + +struct partlist; + +/** + * \brief Item data callback. + * + * @param inout part_list items list structure + * @param in idx item index + */ +typedef void (*cb_part_filldata)(struct partlist *part_list, int idx); + +typedef struct partlist { + /** Data callback */ + cb_part_filldata filldata; + /** Number of items */ + int size; + /** Items */ + partitem_t *items; + /** Mode */ + partmode_t mode; + /** Whether to actually use random mode */ + int force_random; + /** Usage limit */ + int soft_usage_limit; + /** Reinit limit */ + int reinit; + /** Reinit counter */ + int reinit_counter; +} partlist_t; + +/** + * \brief Gets enumerated mode from string. + */ +extern partmode_t partlist_getmode(const char *mode); + +/** + * \brief Initializes items list. + * + * @param inout part_list items list structure + * @param in filldata items data callback, NULL for default (physical partitions) + * @param in key_prefix key prefix for items to search for in configuration + * @param in key_value key value, to be used if list of items is stored in one option + * @param in excluded excluded items list + * @param in mode items mode + * @param in soft_usage_limit usage limit + * @param in reinit reinit items data after given amount of operations + */ +extern void partlist_initialize(partlist_t *part_list, cb_part_filldata filldata, + const char *key_prefix, const char *key_value, + const char *excluded, partmode_t mode, + int soft_usage_limit, int reinit); + +/** + * \brief Selects item value from list. + * + * @param inout part_list items list structure + * @return selected item value, according to requested mode, or NULL if none found + */ +extern const char *partlist_select_value(partlist_t *part_list); + +/** + * \brief Selects local partitions. + * + * @return selected partition, according to requested mode, or NULL if none found + */ +const char *partlist_local_select(void); + +/** + * \brief Finds partition with most freespace (bytes or percents). + * + * @param out available number of KiB available on partition + * @param out total total number of KiB on partition + * @param out tavailable number of KiB available on server + * @param out ttotal total number of KiB on server + * @return partition, or NULL if none found + */ +const char *partlist_local_find_freespace_most(int percent, uint64_t *available, + uint64_t *total, uint64_t *tavailable, + uint64_t *ttotal); + +/** + * \brief Frees local partition data. + */ +extern void partlist_local_done(void);
View file
cyrus-imapd-2.5.tar.gz/imap/pop3d.c
Changed
@@ -64,7 +64,9 @@ #include "assert.h" #include "acl.h" +#ifdef USE_AUTOCREATE #include "autocreate.h" +#endif #include "util.h" #include "auth.h" #include "global.h" @@ -1796,6 +1798,7 @@ r = mboxlist_lookup(inboxname, &mbentry, NULL); +#ifdef USE_AUTOCREATE /* Try once again after autocreate_inbox */ if (r == IMAP_MAILBOX_NONEXISTENT) { /* NOTE - if we have a subfolder, autocreateinbox should still create @@ -1803,6 +1806,7 @@ r = autocreate_user(&popd_namespace, popd_userid); if (!r) r = mboxlist_lookup(inboxname, &mbentry, NULL); } +#endif if (!r && (config_popuseacl = config_getswitch(IMAPOPT_POPUSEACL)) && (!mbentry->acl ||
View file
cyrus-imapd-2.5.tar.gz/imap/reconstruct.c
Changed
@@ -85,6 +85,7 @@ #include "map.h" #include "message.h" #include "message_guid.h" +#include "partlist.h" #include "xmalloc.h" #include "xstrlcpy.h" #include "xstrlcat.h" @@ -368,6 +369,8 @@ quotadb_close(); quotadb_done(); + partlist_local_done(); + cyrus_done(); strarray_fini(&discovered);
View file
cyrus-imapd-2.5.tar.gz/imap/sync_server.c
Changed
@@ -83,6 +83,7 @@ #include "mailbox.h" #include "map.h" #include "mboxlist.h" +#include "partlist.h" #include "proc.h" #include "prot.h" #include "quota.h" @@ -458,6 +459,8 @@ annotatemore_close(); annotate_done(); + partlist_local_done(); + if (sync_in) { prot_NONBLOCK(sync_in); prot_fill(sync_in);
View file
cyrus-imapd-2.5.tar.gz/imap/tls.c
Changed
@@ -122,12 +122,13 @@ #include "nonblock.h" #include "xmalloc.h" #include "tls.h" +#include "tls_th-lock.h" /* Session caching/reuse stuff */ #include "global.h" #include "cyrusdb.h" -#define DB (config_tlscache_db) /* sessions are binary -> MUST use DB3 */ +#define DB (config_tls_sessions_db) /* sessions are binary -> MUST use DB3 */ static struct db *sessdb = NULL; static int sess_dbopen = 0; @@ -152,10 +153,10 @@ { const char *val; - val = config_getstring(IMAPOPT_TLS_CERT_FILE); + val = config_getstring(IMAPOPT_TLS_SERVER_CERT); if (!val || !strcasecmp(val, "disabled")) return 0; - val = config_getstring(IMAPOPT_TLS_KEY_FILE); + val = config_getstring(IMAPOPT_TLS_SERVER_KEY); if (!val || !strcasecmp(val, "disabled")) return 0; return 1; @@ -219,7 +220,7 @@ #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) /* Logic copied from OpenSSL apps/s_server.c: give the TLS context * DH params to work with DHE-* cipher suites. Hardcoded fallback - * in case no DH params in tls_key_file or tls_cert_file. + * in case no DH params in server_key or server_cert. */ static DH *get_dh1024(void) { @@ -623,6 +624,7 @@ */ /* must be called after cyrus_init */ +// I am the server EXPORTED int tls_init_serverengine(const char *ident, int verifydepth, int askcert, @@ -631,12 +633,22 @@ int off = 0; int verify_flags = SSL_VERIFY_NONE; const char *cipher_list; - const char *CApath; - const char *CAfile; - const char *s_cert_file; - const char *s_key_file; - int requirecert; - int timeout; + const char *client_ca_dir; + const char *client_ca_file; + const char *server_ca_file; + const char *server_cert_file; + const char *server_key_file; + enum enum_value tls_client_certs; + int server_cipher_order; + int timeout; + + /* Whether or not to use any client certificate CA context to + * verify client SSL certificates with. + * + * This is initially switched off by a value of "off" for the + * tls_client_certs setting, or should no client_ca_dir nor + * client_ca_file be specified. */ + int use_client_certs = 1; if (tls_serverengine) return (0); /* already running */ @@ -651,84 +663,184 @@ return -1; } -#if 0 - if (tlsonly) { - s_ctx = SSL_CTX_new(TLSv1_server_method()); - } else { - s_ctx = SSL_CTX_new(SSLv23_server_method()); - } -#endif /* even if we want TLS only, we use SSLv23 server method so we can deal with a client sending an SSLv2 greeting message */ - s_ctx = SSL_CTX_new(SSLv23_server_method()); if (s_ctx == NULL) { return (-1); }; off |= SSL_OP_ALL; /* Work around all known bugs */ - if (tlsonly) { + + const char *tls_versions = config_getstring(IMAPOPT_TLS_VERSIONS); + + if (strstr(tls_versions, "ssl2") == NULL || tlsonly) { off |= SSL_OP_NO_SSLv2; + } + + if (strstr(tls_versions, "ssl3") == NULL || tlsonly) { off |= SSL_OP_NO_SSLv3; } + + if (strstr(tls_versions, "tls1_2") == NULL) { +#if (OPENSSL_VERSION_NUMBER >= 0x1000105fL) + off |= SSL_OP_NO_TLSv1_2; +#else + syslog(LOG_ERR, "ERROR: TLSv1.2 configured, OpenSSL < 1.0.1e insufficient"); +#endif + } + + if (strstr(tls_versions, "tls1_1") == NULL) { +#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) + off |= SSL_OP_NO_TLSv1_1; +#else + syslog(LOG_ERR, "ERROR: TLSv1.1 configured, OpenSSL < 1.0.0 insufficient"); +#endif + } + + if (strstr(tls_versions, "tls1_0") == NULL) { + off |= SSL_OP_NO_TLSv1; + } + + server_cipher_order = config_getswitch(IMAPOPT_TLS_PREFER_SERVER_CIPHERS); + if (server_cipher_order) + off |= SSL_OP_CIPHER_SERVER_PREFERENCE; + + if (!config_getswitch(IMAPOPT_TLS_COMPRESSION)) { + off |= SSL_OP_NO_COMPRESSION; + syslog(LOG_DEBUG, "TLS client engine: Setting SSL_OP_NO_COMPRESSION"); + } + SSL_CTX_set_options(s_ctx, off); SSL_CTX_set_info_callback(s_ctx, apps_ssl_info_callback); - cipher_list = config_getstring(IMAPOPT_TLS_CIPHER_LIST); + cipher_list = config_getstring(IMAPOPT_TLS_CIPHERS); if (!SSL_CTX_set_cipher_list(s_ctx, cipher_list)) { syslog(LOG_ERR,"TLS server engine: cannot load cipher list '%s'", cipher_list); return (-1); } - CAfile = config_getstring(IMAPOPT_TLS_CA_FILE); - CApath = config_getstring(IMAPOPT_TLS_CA_PATH); + tls_client_certs = config_getenum(IMAPOPT_TLS_CLIENT_CERTS); - if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(s_ctx))) { - /* just a warning since this is only necessary for client auth */ - syslog(LOG_NOTICE,"TLS server engine: cannot load CA data"); + if (tls_client_certs != IMAP_ENUM_TLS_CLIENT_CERTS_OFF) { + client_ca_dir = config_getstring(IMAPOPT_TLS_CLIENT_CA_DIR); + client_ca_file = config_getstring(IMAPOPT_TLS_CLIENT_CA_FILE); + + if (client_ca_dir || client_ca_file) { + if ((!SSL_CTX_load_verify_locations(s_ctx, client_ca_file, client_ca_dir)) || + (!SSL_CTX_set_default_verify_paths(s_ctx))) { + /* just a warning since this is only necessary for client auth */ + syslog(LOG_NOTICE,"TLS server engine: Failed to load CA data."); + use_client_certs = 0; + } + } else { + syslog(LOG_NOTICE,"TLS server engine: Cannot load CA data."); + use_client_certs = 0; + } + } else { + use_client_certs = 0; } - s_cert_file = config_getstring(IMAPOPT_TLS_CERT_FILE); - s_key_file = config_getstring(IMAPOPT_TLS_KEY_FILE); + server_ca_file = config_getstring(IMAPOPT_TLS_SERVER_CA_FILE); + server_cert_file = config_getstring(IMAPOPT_TLS_SERVER_CERT); + server_key_file = config_getstring(IMAPOPT_TLS_SERVER_KEY); + + /* Only consider adding additional CA certificates -used to verify certificates + * issued to clients, which may have been issued by an intermediate CA and + * not the CA that issued our server certificate- when indeed we are using + * SSL/TLS on this server. + */ + if (server_ca_file && !strcasecmp(server_cert_file, "disabled")) { + SSL_CTX_set_mode(s_ctx,SSL_CTX_get_mode(s_ctx) | SSL_MODE_NO_AUTO_CHAIN); + BIO *filebio = BIO_new_file(server_ca_file, "r"); + + if (filebio) { + X509 *cacert; + syslog(LOG_DEBUG,"TLS server engine: loading additional client_ca_cert from file %s", server_ca_file); + + while ((cacert = PEM_read_bio_X509(filebio,NULL,NULL,NULL)) != NULL) { + char buf256; + X509_NAME_oneline(X509_get_subject_name(cacert), buf, sizeof(buf)); + if (!SSL_CTX_add_extra_chain_cert(s_ctx,cacert)) { + syslog(LOG_ERR,"TLS server engine: failed to add client_ca_cert to chain: %s",buf); + X509_free(cacert); + } else { + syslog(LOG_DEBUG,"TLS server engine: added CA cert to chain: %s",buf); + } + } + + BIO_free(filebio); + } else { + syslog(LOG_ERR,"TLS server engine: Cannot load client_ca_cert from file %s", server_ca_file); + return (-1); + } + } - if (!set_cert_stuff(s_ctx, s_cert_file, s_key_file)) { - syslog(LOG_ERR,"TLS server engine: cannot load cert/key data"); + if (!set_cert_stuff(s_ctx, server_cert_file, server_key_file)) { + syslog(LOG_ERR,"TLS server engine: cannot load server cert/key data"); return (-1); } + SSL_CTX_set_tmp_rsa_callback(s_ctx, tmp_rsa_cb); #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) /* Load DH params for DHE-* key exchanges */ - SSL_CTX_set_tmp_dh(s_ctx, load_dh_param(s_key_file, s_cert_file)); - /* FIXME: Load ECDH params for ECDHE suites when 0.9.9 is released */ + SSL_CTX_set_tmp_dh(s_ctx, load_dh_param(server_key_file, server_cert_file)); +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x1000103fL) + const char *ec = config_getstring(IMAPOPT_TLS_ECCURVE); + int openssl_nid = OBJ_sn2nid(ec); + if (openssl_nid != 0) { + EC_KEY *ecdh; + ecdh = EC_KEY_new_by_curve_name(openssl_nid); + if (ecdh != NULL) { + SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); + EC_KEY_free(ecdh); + } + } #endif verify_depth = verifydepth; - if (askcert!=0) - verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + tls_client_certs = config_getenum(IMAPOPT_TLS_CLIENT_CERTS); + + if (!use_client_certs) { + if ((tls_client_certs != IMAP_ENUM_TLS_CLIENT_CERTS_OFF) || askcert) + syslog(LOG_ERR, "TLS server engine: No client cert CA specified."); + + } else { + STACK_OF(X509_NAME) *CAnames = SSL_load_client_CA_file(client_ca_file); + + if (!CAnames || sk_num(CAnames) < 1) { + syslog(LOG_ERR, + "TLS server engine: No client CA certs specified. " + "Client side certs may not work"); + + } else { + if (askcert || tls_client_certs) + verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + + if (tls_client_certs) + verify_flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + + SSL_CTX_set_client_CA_list(s_ctx, CAnames); + + syslog( + LOG_DEBUG, + "Set client CA list: Client cert %srequested, %srequired", + verify_flags & SSL_VERIFY_PEER ? "" : "not ", + verify_flags & SSL_VERIFY_FAIL_IF_NO_PEER_CERT ? "":"not " + ); + } + } - requirecert = config_getswitch(IMAPOPT_TLS_REQUIRE_CERT); - if (requirecert) - verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT - | SSL_VERIFY_CLIENT_ONCE; SSL_CTX_set_verify(s_ctx, verify_flags, verify_callback); #if (OPENSSL_VERSION_NUMBER >= 0x0090806fL) SSL_CTX_set_tlsext_servername_callback(s_ctx, servername_callback); #endif - if (askcert || requirecert) { - if (CAfile == NULL) { - syslog(LOG_ERR, - "TLS server engine: No CA file specified. " - "Client side certs may not work"); - } else { - SSL_CTX_set_client_CA_list(s_ctx, SSL_load_client_CA_file(CAfile)); - } - } - /* Don't use an internal session cache */ SSL_CTX_sess_set_cache_size(s_ctx, 1); /* 0 is unlimited, so use 1 */ SSL_CTX_set_session_cache_mode(s_ctx, SSL_SESS_CACHE_SERVER | @@ -757,7 +869,7 @@ SSL_CTX_sess_set_remove_cb(s_ctx, remove_session_cb); SSL_CTX_sess_set_get_cb(s_ctx, get_session_cb); - fname = config_getstring(IMAPOPT_TLSCACHE_DB_PATH); + fname = config_getstring(IMAPOPT_TLS_SESSIONS_DB_PATH); /* create the name of the db file */ if (!fname) { @@ -1002,18 +1114,30 @@ } if (authid && *authid) { - syslog(LOG_NOTICE, "starttls: %s with cipher %s (%d/%d bits %s)" - " authenticated as %s", - tls_protocol, tls_cipher_name, - tls_cipher_usebits, tls_cipher_algbits, - SSL_session_reused(tls_conn) ? "reused" : "new", - *authid); + syslog( + LOG_NOTICE, + "starttls: %s with cipher %s (%d/%d bits %s) " + "authenticated as %s", + tls_protocol, + tls_cipher_name, + tls_cipher_usebits, + tls_cipher_algbits, + SSL_session_reused(tls_conn) ? "reused" : "new", + *authid + ); + } else { - syslog(LOG_NOTICE, "starttls: %s with cipher %s (%d/%d bits %s)" - " no authentication", - tls_protocol, tls_cipher_name, - tls_cipher_usebits, tls_cipher_algbits, - SSL_session_reused(tls_conn) ? "reused" : "new"); + syslog( + LOG_NOTICE, + "starttls: %s with cipher %s (%d/%d bits %s) " + "no authentication", + tls_protocol, + tls_cipher_name, + tls_cipher_usebits, + tls_cipher_algbits, + SSL_session_reused(tls_conn) ? "reused" : "new" + ); + } done: @@ -1137,7 +1261,7 @@ int ret; struct prunerock prock; - fname = config_getstring(IMAPOPT_TLSCACHE_DB_PATH); + fname = config_getstring(IMAPOPT_TLS_SESSIONS_DB_PATH); /* create the name of the db file */ if (!fname) { @@ -1184,16 +1308,17 @@ return (strlen(buf)); } +// I am the client HIDDEN int tls_init_clientengine(int verifydepth, - char *var_tls_cert_file, - char *var_tls_key_file) + const char *var_server_cert, + const char *var_server_key) { int off = 0; int verify_flags = SSL_VERIFY_NONE; - const char *CApath; - const char *CAfile; - char *c_cert_file; - char *c_key_file; + const char *server_ca_dir; + const char *server_ca_file; + char *client_cert; + char *client_key; if (tls_clientengine) return (0); /* already running */ @@ -1209,7 +1334,7 @@ } /* XXX May need to use only SSLv3 for iSchedule */ - c_ctx = SSL_CTX_new(TLSv1_client_method()); + c_ctx = SSL_CTX_new(SSLv23_client_method()); if (c_ctx == NULL) { return (-1); }; @@ -1217,31 +1342,40 @@ off |= SSL_OP_ALL; /* Work around all known bugs */ SSL_CTX_set_options(c_ctx, off); SSL_CTX_set_info_callback(c_ctx, apps_ssl_info_callback); - - CAfile = config_getstring(IMAPOPT_TLS_CA_FILE); - CApath = config_getstring(IMAPOPT_TLS_CA_PATH); - if ((!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(c_ctx))) { - /* just a warning since this is only necessary for client auth */ - syslog(LOG_NOTICE,"TLS client engine: cannot load CA data"); + if (!config_getswitch(IMAPOPT_TLS_COMPRESSION)) { + off |= SSL_OP_NO_COMPRESSION; + syslog(LOG_DEBUG, "TLS client engine: Setting SSL_OP_NO_COMPRESSION"); + } + + server_ca_dir = config_getstring(IMAPOPT_TLS_SERVER_CA_DIR); + server_ca_file = config_getstring(IMAPOPT_TLS_SERVER_CA_FILE); + + if (server_ca_dir || server_ca_file) { + if ((!SSL_CTX_load_verify_locations(c_ctx, server_ca_file, server_ca_dir)) || + (!SSL_CTX_set_default_verify_paths(c_ctx))) { + /* just a warning since this is only necessary for client auth */ + syslog(LOG_NOTICE,"TLS client engine: cannot load CA data"); + } } - if (strlen(var_tls_cert_file) == 0) - c_cert_file = NULL; + if (var_server_cert && strlen(var_server_cert) == 0) + client_cert = NULL; else - c_cert_file = var_tls_cert_file; - if (strlen(var_tls_key_file) == 0) - c_key_file = NULL; + client_cert = xstrdup(var_server_cert); + + if (var_server_key && strlen(var_server_key) == 0) + client_key = NULL; else - c_key_file = var_tls_key_file; + client_key = xstrdup(var_server_key); - if (c_cert_file || c_key_file) { - if (!set_cert_stuff(c_ctx, c_cert_file, c_key_file)) { - syslog(LOG_ERR,"TLS client engine: cannot load cert/key data"); + if (client_cert || client_key) { + if (!set_cert_stuff(c_ctx, client_cert, client_key)) { + syslog(LOG_ERR,"TLS client engine: cannot load client cert/key data"); return (-1); } } + SSL_CTX_set_tmp_rsa_callback(c_ctx, tmp_rsa_cb); verify_depth = verifydepth;
View file
cyrus-imapd-2.5.tar.gz/imap/tls.h
Changed
@@ -64,8 +64,8 @@ int tlsonly); int tls_init_clientengine(int verifydepth, - char *var_tls_cert_file, - char *var_tls_key_file); + const char *var_server_cert, + const char *var_server_key); /* start tls negotiation */ int tls_start_servertls(int readfd, int writefd, int timeout,
View file
cyrus-imapd-2.5.tar.gz/imap/tls_th-lock.c
Added
@@ -0,0 +1,70 @@ +/* tls_th-lock.c */ +/* Derived from openssl-0.9.8i/crypto/threads/th-lock.c + * by Duncan Gibb <duncan.gibb@siriusit.co.uk> + * 4 November 2008 + */ + +#include <config.h> +#include <pthread.h> +#include <syslog.h> + +#include <openssl/ssl.h> + +#include "tls_th-lock.h" + +static pthread_mutex_t *lock_cs; +static long *lock_count; + +void CRYPTO_thread_setup(void) +{ + int i; + + syslog(LOG_DEBUG, "Setting up pthreads TLS."); + + lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); + + for (i = 0; i < CRYPTO_num_locks(); i++) { + lock_counti=0; + pthread_mutex_init(&(lock_csi),NULL); + } + + CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); + CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); +} + +void CRYPTO_thread_cleanup(void) +{ + int i; + + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) { + pthread_mutex_destroy(&(lock_csi)); + } + + OPENSSL_free(lock_cs); + OPENSSL_free(lock_count); +} + +void pthreads_locking_callback( + int mode, + int type, + char *file, + int line +) { + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&(lock_cstype)); + lock_counttype++; + } else { + pthread_mutex_unlock(&(lock_cstype)); + } +} + +unsigned long pthreads_thread_id(void) +{ + unsigned long ret; + + ret = (unsigned long)pthread_self(); + return(ret); +} +
View file
cyrus-imapd-2.5.tar.gz/imap/tls_th-lock.h
Added
@@ -0,0 +1,22 @@ +/* tls_th-lock.h */ +/* Derived from openssl-0.9.8i/crypto/threads/th-lock.c + * by Duncan Gibb <duncan.gibb@siriusit.co.uk> + * 4 November 2008 + */ + +#ifndef INCLUDED_TLS_TH_LOCK_H +#define INCLUDED_TLS_TH_LOCK_H + +#ifdef HAVE_SSL + +void CRYPTO_thread_setup(void); +void CRYPTO_thread_cleanup(void); +/* +static void pthreads_locking_callback(int mode,int type,char *file,int line); +static unsigned long pthreads_thread_id(void ); +*/ +void pthreads_locking_callback(int mode,int type,char *file,int line); +unsigned long pthreads_thread_id(void ); + +#endif /* HAVE_SSL */ +#endif /* INCLUDED_TLS_TH_LOCK_H */
View file
cyrus-imapd-2.5.tar.gz/imtest/imtest.c
Changed
@@ -490,7 +490,7 @@ return IMTEST_FAIL; } - tls_ctx = SSL_CTX_new(TLSv1_client_method()); + tls_ctx = SSL_CTX_new(SSLv23_client_method()); if (tls_ctx == NULL) { return IMTEST_FAIL; };
View file
cyrus-imapd-2.5.tar.gz/lib/imapoptions
Changed
@@ -46,9 +46,9 @@ .SH NAME imapd.conf \- IMAP configuration file .SH DESCRIPTION -\fB/etc/imapd.conf\fR +\fB/etc/imapd.conf\fR is the configuration file for the Cyrus IMAP server. It defines -local parameters for IMAP. +local parameters for IMAP. .PP Each line of the \fB/etc/imapd.conf\fR file has the form .IP @@ -142,7 +142,7 @@ { "allowplaintext", 0, SWITCH } /* Allow the use of cleartext passwords on the wire. */ - + { "allowusermoves", 0, SWITCH } /* Allow moving user accounts (with associated meta-data) via RENAME or XFER. @@ -151,7 +151,7 @@ moved is not logged in, and cannot login during the move. Failure to do so may result in the user's meta-data (seen state, subscriptions, etc) being corrupted or out of date. */ - + { "altnamespace", 0, SWITCH } /* Use the alternate IMAP namespace, where personal folders reside at the same level in the hierarchy as INBOX. @@ -225,7 +225,7 @@ .\" .IP \fIproxy-type\fR 5 specifies whether this attribute is for the \fBbackend\fR or -\fBproxy\fR servers or both (\fBproxy_and_backend\fR) +\fBproxy\fR servers or both (\fBproxy_and_backend\fR) .\" .IP \fIattrib-names\fR 5 is the space-separated list of available attributes for the @@ -263,15 +263,69 @@ { "auth_mech", "unix", STRINGLIST("unix", "pts", "krb", "krb5")} /* The authorization mechanism to use. */ -{ "autocreatequota", 0, INT } +{ "autocreate_inbox_folders", NULL, STRING } +/* If a user does not have an INBOX created then the INBOX as well as some INBOX + subfolders are created under two conditions. + 1. The user logins via the IMAP or the POP3 protocol. (autocreatequota option must have a nonzero value) + 2. A message arrives for the user through the LMTPD protocol.(createonpost option must be yes) + autocreate_inbox_folders is a list of INBOX's subfolders separated by a "|", that + are automatically created by the server under the previous two situations. */ + +{ "autocreate_post", 0, SWITCH } +/* If enabled, when lmtpd receives an incoming mail for an INBOX that does not exist, + then the INBOX is automatically created by lmtpd. */ + +{ "autocreate_quota", 0, INT } /* If nonzero, normal users may create their own IMAP accounts by creating the mailbox INBOX. The user's quota is set to the value if it is positive, otherwise the user has unlimited quota. */ -{ "autocreatequotamsg", -1, INT } +{ "autocreate_quota_messages", -1, INT } /* When users create their own IMAP accounts by creating the mailbox INBOX, their message quota is set to this value. Default value (-1) is unlimited. */ +{ "autocreate_sieve_folders", NULL, STRING } +/* It is a "|" separated list of subfolders of INBOX that will be automatically created, + if requested by a sieve filter, through the "fileinto" action. (default = null) + i.e. autocreate_sieve_folders: Junk | Spam */ + +{ "autocreate_sieve_script", NULL, STRING } +/* The full path of a file that contains a sieve script. This script automatically becomes a + user's initial default sieve filter script. When this option is not defined, no default + sieve filter is created. The file must be readable by the cyrus daemon. */ + +{ "autocreate_sieve_script_compile", 0, SWITCH } +/* If set to yes and no compiled sieve script file exists, the sieve script which is + compiled on the fly will be saved in the file name that autocreate_sieve_compiledscript + option points to. In order a compiled script to be generated, autocreate_sieve_script and + autocreate_sieve_compiledscript must have valid values */ + +{ "autocreate_sieve_script_compiled", NULL, STRING } +/* The full path of a file that contains a compiled in bytecode sieve script. This script + automatically becomes a user's initial default sieve filter script. If this option is + not specified, or the filename doesn't exist then the script defined by + autocreate_sieve_script is compiled on the fly and installed as the user's default + sieve script */ + +{ "autocreate_subscribe_folders", NULL, STRING } +/* A list of folder names, separated by "|", that the users get automatically subscribed to, + when their INBOX is created. These folder names must have been included in the + autocreateinboxfolders option of the imapd.conf. */ + +{ "autocreate_subscribe_sharedfolders", NULL, STRING } +/* A list of shared folders (bulletin boards), separated by "|", that the users get + automatically subscribed to, after their INBOX is created. The shared folder must + have been created and the user must have the required permissions to get subscribed + to it. Otherwise, subscribing to the shared folder fails. */ + +{ "autocreate_subscribe_sharedfolders_all", 0, SWITCH } +/* If set to yes, the user is automatically subscribed to all shared folders, one has permission + to subscribe to. */ + +{ "autocreate_users", "anyone", STRING } +/* A space separated list of users and/or groups that are allowed their INBOX to be + automatically created. */ + { "berkeley_cachesize", 512, INT } /* Size (in kilobytes) of the shared memory buffer pool (cache) used by the berkeley environment. The minimum allowed value is 20. The @@ -303,55 +357,6 @@ /* Time in seconds. Any imap command that takes longer than this time is logged. */ -{ "createonpost", 0, SWITCH } -/* If yes, when lmtpd receives an incoming mail for an INBOX that does not exist, - then the INBOX is automatically created by lmtpd. */ - -{ "autocreateinboxfolders", NULL, STRING } -/* If a user does not have an INBOX created then the INBOX as well as some INBOX - subfolders are created under two conditions. - 1. The user logins via the IMAP or the POP3 protocol. (autocreatequota option must have a nonzero value) - 2. A message arrives for the user through the LMTPD protocol.(createonpost option must be yes) - autocreateinboxfolders is a list of INBOX's subfolders separated by a "|", that - are automatically created by the server under the previous two situations. */ - -{ "autosubscribeinboxfolders", NULL, STRING } -/* A list of folder names, separated by "|", that the users get automatically subscribed to, - when their INBOX is created. These folder names must have been included in the - autocreateinboxfolders option of the imapd.conf. */ - -{ "autosubscribesharedfolders", NULL, STRING } -/* A list of shared folders (bulletin boards), separated by "|", that the users get - automatically subscribed to, after their INBOX is created. The shared folder must - have been created and the user must have the required permissions to get subscribed - to it. Otherwise, subscribing to the shared folder fails. */ - -{ "autosubscribe_all_sharedfolders", 0, SWITCH } -/* If set to yes, the user is automatically subscribed to all shared folders, one has permission - to subscribe to. */ - -{ "autocreate_sieve_script", NULL, STRING } -/* The full path of a file that contains a sieve script. This script automatically becomes a - user's initial default sieve filter script. When this option is not defined, no default - sieve filter is created. The file must be readable by the cyrus daemon. */ - -{ "autocreate_sieve_compiledscript", NULL, STRING } -/* The full path of a file that contains a compiled in bytecode sieve script. This script - automatically becomes a user's initial default sieve filter script. If this option is - not specified, or the filename doesn't exist then the script defined by - autocreate_sieve_script is compiled on the fly and installed as the user's default - sieve script */ - -{ "generate_compiled_sieve_script", 0, SWITCH } -/* If set to yes and no compiled sieve script file exists, the sieve script which is - compiled on the fly will be saved in the file name that autocreate_sieve_compiledscript - option points to. In order a compiled script to be generated, autocreate_sieve_script and - autocreate_sieve_compiledscript must have valid values */ - -{ "autocreate_users", "anyone", STRING } -/* A space separated list of users and/or groups that are allowed their INBOX to be - automatically created. */ - { "configdirectory", NULL, STRING } /* The pathname of the IMAP configuration directory. This field is required. */ @@ -398,12 +403,12 @@ right, they will automatically be given the new 'x' right. */ { "disable_user_namespace", 0, SWITCH } -/* Preclude list command on user namespace. If set to 'yes', the +/* Preclude list command on user namespace. If set to 'yes', the LIST response will never include any other user's mailbox. Admin users will always see all mailboxes. The default is 'no' */ { "disable_shared_namespace", 0, SWITCH } -/* Preclude list command on user namespace. If set to 'yes', the +/* Preclude list command on shared namespace. If set to 'yes', the LIST response will never include any non-user mailboxes. Admin users will always see all mailboxes. The default is 'no' */ @@ -431,24 +436,24 @@ /* The mode in which message content may be included with MessageAppend and MessageNew. "standard" mode is the default behavior in which message is included up to a size with the notification. In "message" mode, the message - is included and may be truncated to a size. In "header" mode, it includes - headers truncated to a size. In "body" mode, it includes body truncated + is included and may be truncated to a size. In "header" mode, it includes + headers truncated to a size. In "body" mode, it includes body truncated to a size. In "headerbody" mode, it includes full headers and body truncated to a size */ { "event_content_size", 0, INT } -/* Truncate the message content that may be included with MessageAppend and +/* Truncate the message content that may be included with MessageAppend and MessageNew. Set 0 to include the entire message itself */ { "event_exclude_flags", NULL, STRING } /* Don't send event notification for given IMAP flag(s) */ { "event_exclude_specialuse", "\\Junk", STRING } -/* Don't send event notification for folder with given special-use attributes. +/* Don't send event notification for folder with given special-use attributes. Set ALL for any folder */ { "event_extra_params", "timestamp", BITFIELD("bodyStructure", "clientAddress", "diskUsed", "flagNames", "messageContent", "messageSize", "messages", "modseq", "service", "timestamp", "uidnext", "vnd.cmu.midset", "vnd.cmu.unseenMessages", "vnd.cmu.envelope", "vnd.cmu.sessionId") } -/* Space-separated list of extra parameters to add to any appropriated event. */ +/* Space-separated list of extra parameters to add to any appropriated event. */ { "event_groups", "message mailbox", BITFIELD("message", "quota", "flags", "access", "mailbox", "subscription") } /* Space-separated list of groups of related events to turn on notification */ @@ -546,7 +551,7 @@ 1. A value of 0 will disable IDLE. */ { "imapidresponse", 1, SWITCH } -/* If enabled, the server responds to an ID command with a parameter +/* If enabled, the server responds to an ID command with a parameter list containing: version, vendor, support-url, os, os-version, command, arguments, environment. Otherwise the server returns NIL. */ @@ -554,7 +559,7 @@ /* Only list a restricted set of mailboxes via IMAP by using userid+namespace syntax as the authentication/authorization id. Using userid+ (with an empty namespace) will list only subscribed - mailboxes. */ + mailboxes. */ { "implicit_owner_rights", "lkxa", STRING } /* The implicit Access Control List (ACL) for the owner of a mailbox. */ @@ -633,7 +638,7 @@ { "ldap_group_filter", "(cn=%u)", STRING } /* Specify a filter that searches for group identifiers. - See ldap_filter for more options. */ + See ldap_filter for more options. */ { "ldap_group_scope", "sub", STRINGLIST("sub", "one", "base") } /* Specify search scope for ldap_group_filter. */ @@ -654,12 +659,12 @@ /* LDAP base dn for ldap_member_filter. */ { "ldap_member_filter", "(member=%D)", STRING } -/* Specify a filter for "ldap_member_method: filter". - See ldap_filter for more options. */ +/* Specify a filter for "ldap_member_method: filter". + See ldap_filter for more options. */ { "ldap_member_method", "attribute", STRINGLIST("attribute", "filter") } -/* Specify a group method. The "attribute" method retrieves groups from - a multi-valued attribute specified in ldap_member_attribute. +/* Specify a group method. The "attribute" method retrieves groups from + a multi-valued attribute specified in ldap_member_attribute. The "filter" method uses a filter, specified by ldap_member_filter, to find groups; ldap_member_attribute is a single-value attribute group name. */ @@ -668,7 +673,7 @@ /* Specify search scope for ldap_member_filter. */ { "ldap_password", NULL, STRING } -/* Password for the connection to the LDAP server (SASL and simple bind). +/* Password for the connection to the LDAP server (SASL and simple bind). Do not use for anonymous simple binds */ { "ldap_realm", NULL, STRING } @@ -709,8 +714,8 @@ /* Specify a number of entries for a search request to return. */ { "ldap_start_tls", 0, SWITCH } -/* Use StartTLS extended operation. Do not use ldaps: ldap_uri when - this option is enabled. */ +/* Use transport layer security for ldap:// using STARTTLS. Do not use + ldaps:// in 'ldap_uri' with this option enabled. */ { "ldap_time_limit", 5, INT } /* Specify a number of seconds for a search request to complete. */ @@ -718,24 +723,24 @@ { "ldap_timeout", 5, INT } /* Specify a number of seconds a search can take before timing out. */ -{ "ldap_tls_cacert_dir", NULL, STRING } -/* Path to directory with CA (Certificate Authority) certificates. */ +{ "ldap_ca_dir", NULL, STRING } +/* Path to a directory with CA (Certificate Authority) certificates. */ -{ "ldap_tls_cacert_file", NULL, STRING } -/* File containing CA (Certificate Authority) certificate(s). */ +{ "ldap_ca_file", NULL, STRING } +/* Patch to a file containing CA (Certificate Authority) certificate(s). */ -{ "ldap_tls_cert", NULL, STRING } +{ "ldap_client_cert", NULL, STRING } /* File containing the client certificate. */ -{ "ldap_tls_check_peer", 0, SWITCH } +{ "ldap_verify_peer", 0, SWITCH } /* Require and verify server certificate. If this option is yes, - you must specify ldap_tls_cacert_file or ldap_tls_cacert_dir. */ + you must specify ldap_ca_file or ldap_ca_dir. */ -{ "ldap_tls_ciphers", NULL, STRING } +{ "ldap_ciphers", NULL, STRING } /* List of SSL/TLS ciphers to allow. The format of the string is described in ciphers(1). */ -{ "ldap_tls_key", NULL, STRING } +{ "ldap_client_key", NULL, STRING } /* File containing the private client key. */ { "ldap_uri", NULL, STRING } @@ -771,7 +776,7 @@ /* By default, lmtpd will be strict (per RFC 2821) with regards to which envelope addresses are allowed. If this option is set to false, 8bit characters in the local-part of envelope addresses are changed to 'X' - instead. This is useful to avoid generating backscatter with + instead. This is useful to avoid generating backscatter with certain MTAs like Postfix or Exim which accept such messages. */ { "lmtpsocket", "{configdirectory}/socket/lmtp", STRING } @@ -889,7 +894,7 @@ headers. The 8-bit characters are changed to `X'. If \fBreject8bit\fR is enabled, setting \fBmunge8bit\fR has no effect. (A proper solution to non-ASCII characters in headers is offered by - RFC 2047 and its predecessors.) */ + RFC 2047 and its predecessors.) */ # xxx badly worded { "mupdate_connections_max", 128, INT } @@ -961,7 +966,7 @@ /* Userid that is used for checking access controls when executing Usenet control messages. For instance, to allow articles to be automatically deleted by cancel messages, give the "news" user - the 'd' right on the desired mailboxes. To allow newsgroups to be + the 'd' right on the desired mailboxes. To allow newsgroups to be automatically created, deleted and renamed by the corresponding control messages, give the "news" user the 'c' right on the desired mailbox hierarchies. */ @@ -1010,7 +1015,7 @@ will be confdir/fetchnews.db */ { "nntptimeout", 3, INT } -/* Set the length of the NNTP server's inactivity autologout timer, +/* Set the length of the NNTP server's inactivity autologout timer, in minutes. The minimum value is 3, the default. */ { "notifysocket", "{configdirectory}/socket/notify", STRING } @@ -1041,11 +1046,47 @@ pathname MUST be specified. If the \fBdefaultpartition\fR option is used, then its pathname MUST be specified. For example, if the value of the \fBdefaultpartion\fR option is \fBdefault\fR, then the - \fBpartition-default\fR field is required. */ + \fBpartition-default\fR field is required. */ + +{ "partition_select_mode", "freespace-most", STRINGLIST("random", "freespace-most", "freespace-percent-most", "freespace-percent-weighted", "freespace-percent-weighted-delta") } +/* Partition selection mode. +.PP +.IP \fIrandom\fR 5 +(pseudo-)random selection +.IP \fIfreespace-most\fR 5 +partition with the most free space (KiB) +.IP \fIfreespace-percent-most\fR 5 +partition with the most free space (%) +.IP \fIfreespace-percent-weighted\fR 5 +each partition is weighted according to its free space (%); the more free space +the partition has, the more chances it has to be selected +.IP \fIfreespace-percent-weighted-delta\fR 5 +each partition is weighted according to its difference of free space (%) +compared to the most used partition; the more the partition is lagging behind +the most used +partition, the more chances it has to be selected +.PP +Note that actually even the most used partition has a few chances to be +selected, and those chances increase when other partitions get closer + */ + +{ "partition_select_exclude", NULL, STRING } +/* List of partitions to exclude from selection mode. */ + +{ "partition_select_usage_reinit", 0, INT } +/* For a given session, number of \fBoperations\fR (e.g. partition selection) + for which partitions usage data are cached. */ + +{ "partition_select_soft_usage_limit", 0, INT } +/* Limit of partition usage (%): if a partition is over that limit, it is + automatically excluded from selection mode. +.PP +If all partitions are over that limit, this feature is not used anymore. + */ { "plaintextloginpause", 0, INT } /* Number of seconds to pause after a successful plaintext login. For - systems that support strong authentication, this permits users to + systems that support strong authentication, this permits users to perceive a cost of using plaintext passwords. (This does not affect the use of PLAIN in SASL authentications.) */ @@ -1057,14 +1098,14 @@ left on the POP server before it is deleted (via the CAPA command, defined in the POP3 Extension Mechanism, which some clients may support). "NEVER", the default, may be specified with a negative - number. The Cyrus POP3 server never deletes mail, no matter what - the value of this parameter is. However, if a site implements a + number. The Cyrus POP3 server never deletes mail, no matter what + the value of this parameter is. However, if a site implements a less liberal policy, it needs to change this parameter accordingly. */ { "popminpoll", 0, INT } /* Set the minimum amount of time the server forces users to wait - between successive POP logins, in minutes. */ + between successive POP logins, in minutes. */ { "popsubfolders", 0, SWITCH } /* Allow access to subfolders of INBOX via POP3 by using @@ -1074,20 +1115,20 @@ /* Create a softer minimum poll restriction. Allows \fIpoppollpadding\fR connections before the minpoll restriction is triggered. Additionally, one padding entry is recovered every \fIpopminpoll\fR minutes. - This allows for the occasional polling rate faster than popminpoll, - (i.e., for clients that require a send/receive to send mail) but still + This allows for the occasional polling rate faster than popminpoll, + (i.e., for clients that require a send/receive to send mail) but still enforces the rate long-term. Default is 1 (disabled). .br .sp The easiest way to think of it is a queue of past connections, with one - slot being filled for every connection, and one slot being cleared + slot being filled for every connection, and one slot being cleared every \fIpopminpoll\fR minutes. When the queue is full, the user - will not be able to check mail again until a slot is cleared. If the + will not be able to check mail again until a slot is cleared. If the user waits a sufficient amount of time, they will get back many or all of the slots. */ { "poptimeout", 10, INT } -/* Set the length of the POP server's inactivity autologout timer, +/* Set the length of the POP server's inactivity autologout timer, in minutes. The minimum value is 10, the default. */ { "popuseacl", 0, SWITCH } @@ -1108,14 +1149,14 @@ { "postmaster", "postmaster", STRING } /* Username that is used as the 'From' address in rejection MDNs produced by sieve. */ - + { "postspec", NULL, STRING } { "postuser", "", STRING } /* Userid used to deliver messages to shared folders. For example, if set to "bb", email sent to "bb+shared.blah" would be delivered to the "shared.blah" folder. By default, an email address of - "+shared.blah" would be used. */ + "+shared.blah" would be used. */ { "proxy_authname", "proxy", STRING } /* The authentication name to use when authenticating to a backend server @@ -1154,7 +1195,7 @@ users, separated by spaces. Any user listed in this will be allowed to login for any other user: use with caution. In a standard murder this option should ONLY be set on backends. - DO NOT SET on frontends or things won't work properly. */ + DO NOT SET on frontends or things won't work properly. */ { "pts_module", "afskrb", STRINGLIST("afskrb", "ldap") } /* The PTS module to use. */ @@ -1241,7 +1282,7 @@ { "sasl_minimum_layer", 0, INT } /* The minimum SSF that the server will allow a client to negotiate. - A value of 1 requires integrity protection; any higher value + A value of 1 requires integrity protection; any higher value requires some amount of encryption. */ # Commented out - used by libsasl @@ -1251,7 +1292,7 @@ # Commented out - used by libsasl # { "sasl_pwcheck_method", NULL, STRING } -/* The mechanism used by the server to verify plaintext passwords. +/* The mechanism used by the server to verify plaintext passwords. Possible values include "auxprop", "saslauthd", and "pwcheck". */ { "search_skipdiacrit", 1, SWITCH } @@ -1281,6 +1322,34 @@ finding server with the most available free space for proxying CREATE. */ +{ "serverlist_select_mode", "freespace-most", STRINGLIST("random", "freespace-most", "freespace-percent-most", "freespace-percent-weighted", "freespace-percent-weighted-delta") } +/* Server selection mode. +.PP +.IP \fIrandom\fR 5 +(pseudo-)random selection +.IP \fIfreespace-most\fR 5 +backend with the most (total) free space (KiB) +.IP \fIfreespace-percent-most\fR 5 +backend whose partition has the most free space (%) +.IP \fIfreespace-percent-weighted\fR 5 +same as for partition selection, comparing the free space (%) of the least used +partition of each backend +.IP \fIfreespace-percent-weighted-delta\fR 5 +same as for partition selection, comparing the free space (%) of the least used +partition of each backend + */ + +{ "serverlist_select_usage_reinit", 0, INT } +/* For a given session, number of \fBoperations\fR (e.g. backend selection) + for which backend usage data are cached. */ + +{ "serverlist_select_soft_usage_limit", 0, INT } +/* Limit of backend usage (%): if a backend is over that limit, it is + automatically excluded from selection mode. +.PP +If all backends are over that limit, this feature is not used anymore. + */ + { "servername", NULL, STRING } /* This is the hostname visible in the greeting messages of the POP, IMAP and LMTP daemons. If it is unset, then the result returned @@ -1326,11 +1395,11 @@ { "sieve_maxscripts", 5, INT } /* Maximum number of sieve scripts any user may have, enforced at submission by timsieved(8). */ - + { "sieve_utf8fileinto", 0, SWITCH } /* If enabled, the sieve engine expects folder names for the \fIfileinto\fR action in scripts to use UTF8 encoding. Otherwise, - modified UTF7 encoding should be used. */ + modified UTF7 encoding should be used. */ { "sieve_sasl_send_unsolicited_capability", 0, SWITCH } /* If enabled, timsieved will emit a capability response after a successful @@ -1359,14 +1428,9 @@ directories: ~user/.sieve. */ { "anysievefolder", 0, SWITCH } -/* It must be "yes" in order to permit the autocreation of any INBOX subfolder +/* It must be "yes" in order to permit the autocreation of any INBOX subfolder requested by a sieve filter, through the "fileinto" action. (default = no) */ -{ "autosievefolders", NULL, STRING } -/* It is a "|" separated list of subfolders of INBOX that will be automatically created, - if requested by a sieve filter, through the "fileinto" action. (default = null) - i.e. autosievefolders: Junk | Spam */ - { "singleinstancestore", 1, SWITCH } /* If enabled, imapd, lmtpd and nntpd attempt to only write one copy of a message per partition and create hard links, resulting in a @@ -1425,14 +1489,14 @@ /* A list of users and groups that are allowed to resolve "urlauth=submit+" IMAP URLs, separated by spaces. Any user listed in this will be allowed to fetch the contents of any valid "urlauth=submit+" IMAP URL: - use with caution. */ + use with caution. */ { "subscription_db", "flat", STRINGLIST("flat", "berkeley", "berkeley-hash", "skiplist", "twoskip")} /* The cyrusdb backend to use for the subscriptions list. */ { "suppress_capabilities", NULL, STRING } /* Suppress the named capabilities from any capability response. Use the - exact case as it appears in the response, e.g. + exact case as it appears in the response, e.g. "suppress_capabilities: ESEARCH QRESYNC WITHIN XLIST LIST-EXTENDED" if you have a murder with 2.3.x backends and don't want clients being confused by new capabilities that some backends don't support. */ @@ -1513,14 +1577,14 @@ { "syslog_facility", NULL, STRING } /* Configure a syslog facility. The default is whatever is compiled - in. Allowed values are: DAEMON, MAIL, NEWS, USER, and LOCAL0 + in. Allowed values are: DAEMON, MAIL, NEWS, USER, and LOCAL0 through to LOCAL7 */ { "tcp_keepalive", 0, SWITCH } /* Enable keepalive on TCP connections */ { "tcp_keepalive_cnt", 0, INT } -/* Number of TCP keepalive probes to send before declaring the +/* Number of TCP keepalive probes to send before declaring the connection dead (0 == system default) */ { "tcp_keepalive_idle", 0, INT } @@ -1533,45 +1597,81 @@ { "temp_path", "/tmp", STRING } /* The pathname to store temporary files in */ -{ "timeout", 30, INT } -/* The length of the IMAP server's inactivity autologout timer, +{ "timeout", 30, INT } +/* The length of the IMAP server's inactivity autologout timer, in minutes. The minimum value is 30, the default. */ -{ "tls_ca_file", NULL, STRING } -/* File containing one or more Certificate Authority (CA) certificates. */ +{ "tls_ciphers", "DEFAULT", STRING } +/* The list of SSL/TLS ciphers to allow. The format of the string is + described in ciphers(1). */ -{ "tls_ca_path", NULL, STRING } -/* Path to directory with certificates of CAs. This directory must - have filenames with the hashed value of the certificates (see - openssl(XXX)). */ +{ "tls_client_ca_dir", NULL, STRING } +/* Path to a directory containing the CA certificates used to verify + client SSL certificates used for authentication. */ -{ "tlscache_db", "skiplist", STRINGLIST("berkeley", "berkeley-nosync", "berkeley-hash", "berkeley-hash-nosync", "skiplist", "sql", "twoskip")} -/* The cyrusdb backend to use for the TLS cache. */ +{ "tls_client_ca_file", NULL, STRING } +/* Path to a file containing the CA certificate(s) used to verify + client SSL certificates used for authentication. */ -{ "tlscache_db_path", NULL, STRING } -/* The absolute path to the tlscache db file. If not specified, - will be confdir/tls_sessions.db */ +{ "tls_client_cert", NULL, STRING } +/* File containing the certificate presented to a server for authentication + during STARTTLS. A value of "disabled" will disable this server's use + of certificate-based authentication. */ -{ "tls_cert_file", NULL, STRING } -/* File containing the certificate presented for server authentication - during STARTTLS. A value of "disabled" will disable SSL/TLS. */ +{ "tls_client_certs", "optional", ENUM("off", "optional", "require") } +/* Disable ("off"), allow ("optional", default) or require ("require") the + use of SSL certificates by clients to authenticate themselves. */ -{ "tls_cipher_list", "DEFAULT", STRING } -/* The list of SSL/TLS ciphers to allow. The format of the string is - described in ciphers(1). */ +{ "tls_client_key", NULL, STRING } +/* File containing the private key belonging to the tls_client_cert + certificate. A value of "disabled" will disable this server's use + of certificate-based authentication. */ -{ "tls_key_file", NULL, STRING } -/* File containing the private key belonging to the server - certificate. A value of "disabled" will disable SSL/TLS. */ +{ "tls_compression", 0, SWITCH } +/* Deactivate TLS compression by default. */ -{ "tls_require_cert", 0, SWITCH } -/* Require a client certificate for ALL services (imap, pop3, lmtp, sieve). */ +{ "tls_eccurve", "prime256v1", STRING } +/* The elliptic curve used for ECDHE. Default is NIST Suite B prime256. + See 'openssl ecparam -list_curves' for possible values. */ + +{ "tls_prefer_server_ciphers", 0, SWITCH } +/* Prefer the ciphers on the server side instead of client side. */ + +{ "tls_server_ca_dir", NULL, STRING } +/* Path to a directory with CA certificates used to verify certificates + offered when this server connects to other servers. This directory must + have filenames with the hashed value of the certificates (see + openssl(1)). */ + +{ "tls_server_ca_file", NULL, STRING } +/* Path to a file containing CA certificates used to verify certificates + offered when this server connects to other servers. */ + +{ "tls_server_cert", NULL, STRING } +/* File containing the certificate presented to clients. */ + +{ "tls_server_key", NULL, STRING } +/* File containing the private key belonging to the certificate in + tls_server_cert. */ + +{ "tls_sessions_db", "skiplist", STRINGLIST("berkeley", "berkeley-nosync", "berkeley-hash", "berkeley-hash-nosync", "skiplist", "sql", "twoskip")} +/* The cyrusdb backend to use for the TLS cache. */ + +{ "tls_sessions_db_path", NULL, STRING } +/* The absolute path to the TLS sessions db file. If not specified, + will be confdir/tls_sessions.db */ { "tls_session_timeout", 1440, INT } /* The length of time (in minutes) that a TLS session will be cached for later reuse. The maximum value is 1440 (24 hours), the default. A value of 0 will disable session caching. */ +{ "tls_versions", "ssl2 ssl3 tls1_0 tls1_1 tls1_2", STRING } +/* A list of SSL/TLS versions to not disable. Cyrus IMAP SSL/TLS starts + with all protocols, and substracts protocols not in this list. Newer + versions of SSL/TLS will need to be added here to allow them to get + disabled. */ + { "umask", "077", STRING } /* The umask value used by various Cyrus IMAP programs. */
View file
cyrus-imapd-2.5.tar.gz/ptclient/ldap.c
Changed
@@ -77,6 +77,7 @@ #include "auth_pts.h" #include "strhash.h" #include "xmalloc.h" +#include "xstrlcat.h" /* xxx this just uses the UNIX canonicalization semantics, which is * most likely wrong */ @@ -506,12 +507,12 @@ config_getstring(IMAPOPT_LDAP_PASSWORD) : config_getstring(IMAPOPT_LDAP_SASL_PASSWORD)); ptsm->start_tls = config_getswitch(IMAPOPT_LDAP_START_TLS); - ptsm->tls_check_peer = config_getswitch(IMAPOPT_LDAP_TLS_CHECK_PEER); - ptsm->tls_cacert_file = config_getstring(IMAPOPT_LDAP_TLS_CACERT_FILE); - ptsm->tls_cacert_dir = config_getstring(IMAPOPT_LDAP_TLS_CACERT_DIR); - ptsm->tls_ciphers = config_getstring(IMAPOPT_LDAP_TLS_CIPHERS); - ptsm->tls_cert = config_getstring(IMAPOPT_LDAP_TLS_CERT); - ptsm->tls_key = config_getstring(IMAPOPT_LDAP_TLS_KEY); + ptsm->tls_check_peer = config_getswitch(IMAPOPT_LDAP_VERIFY_PEER); + ptsm->tls_cacert_file = config_getstring(IMAPOPT_LDAP_CA_FILE); + ptsm->tls_cacert_dir = config_getstring(IMAPOPT_LDAP_CA_DIR); + ptsm->tls_ciphers = config_getstring(IMAPOPT_LDAP_CIPHERS); + ptsm->tls_cert = config_getstring(IMAPOPT_LDAP_CLIENT_CERT); + ptsm->tls_key = config_getstring(IMAPOPT_LDAP_CLIENT_KEY); p = config_getstring(IMAPOPT_LDAP_MEMBER_METHOD); if (!strcasecmp(p, "filter")) { @@ -628,7 +629,7 @@ return PTSM_OK; } -static int *ptsmodule_standard_root_dn(const char *domain, const char **result) +static int ptsmodule_standard_root_dn(char *domain, const char **result) { /* number of dots */ int dots; @@ -1110,8 +1111,7 @@ if (Uisupper(rdn0j)) rdn0j=tolower(rdn0j); } - strlcat((*newstate)->groupsi.id, rdn0, - sizeof((*newstate)->groupsi.id)); + strlcat((*newstate)->groupsi.id, rdn0, sizeof((*newstate)->groupsi.id)); (*newstate)->groupsi.hash = strhash((*newstate)->groupsi.id); } @@ -1278,8 +1278,7 @@ vals0j=tolower(vals0j); } - strlcat((*newstate)->groupsi.id, vals0, - sizeof((*newstate)->groupsi.id)); + strlcat((*newstate)->groupsi.id, vals0, sizeof((*newstate)->groupsi.id)); (*newstate)->groupsi.hash = strhash((*newstate)->groupsi.id); ldap_value_free(vals); @@ -1314,7 +1313,7 @@ char domain_filter1024; char *domain_attrs = {(char *)ptsm->domain_name_attribute,(char *)ptsm->domain_result_attribute,NULL}; int rc; - int i; int n; + int n; LDAPMessage *res = NULL; LDAPMessage *entry = NULL; char **vals = NULL;
View file
cyrus-imapd.dsc
Changed
@@ -2,7 +2,7 @@ Source: cyrus-imapd Binary: cyrus-imapd Architecture: any -Version: 2.5~dev2014100701-0~kolab1 +Version: 2.5~dev2014101701-0~kolab1 Maintainer: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Uploaders: Paul Klos <kolab@klos2day.nl> Homepage: http://www.cyrusimap.org/
View file
debian.changelog
Changed
@@ -1,3 +1,10 @@ +cyrus-imapd (2.5~dev2014101701-0~kolab1) unstable; urgency=low + + * Ship a GIT development snapshot from git.cyrusimap.org + 9704e5d41981a18f46a63af78cf02c63fe3824a6 + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Fri, 17 Oct 2014 11:30:13 +0100 + cyrus-imapd (2.5~dev2014100701-0~kolab1) unstable; urgency=low * Ship a GIT development snapshot from git.cyrusimap.org
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.