Fix sanitizer findings in agent configuration and IMAP
This commit is contained in:
@@ -95,6 +95,22 @@ typedef struct _BongoConfigItem {
|
||||
void *destination;
|
||||
} BongoConfigItem;
|
||||
|
||||
/* JSON represents every integral value as int, while agent configuration
|
||||
* structures also contain byte, short, long and time_t destinations. Keep
|
||||
* the actual destination width in the schema so the generic loader never
|
||||
* writes through an incorrectly typed or unaligned int pointer. */
|
||||
typedef struct _BongoConfigIntegerDestination {
|
||||
void *pointer;
|
||||
size_t size;
|
||||
} BongoConfigIntegerDestination;
|
||||
|
||||
#define BONGO_CONFIG_INT(source, destination) \
|
||||
{ BONGO_JSON_INT, (source), \
|
||||
&(BongoConfigIntegerDestination){ (destination), sizeof(*(destination)) } }
|
||||
|
||||
BOOL SetBongoConfigInteger(BongoConfigIntegerDestination *destination,
|
||||
int value);
|
||||
|
||||
BOOL ReadBongoConfiguration(BongoConfigItem *config, char *filename);
|
||||
BOOL ProcessBongoConfiguration(BongoConfigItem *config, BongoJsonNode *node);
|
||||
BOOL SetBongoConfigItem(BongoConfigItem *schema, BongoJsonNode *node);
|
||||
|
||||
@@ -337,9 +337,9 @@ static BongoConfigItem SpamdHostList = { BONGO_JSON_STRING, NULL, &ASpam.spamd.h
|
||||
|
||||
static BongoConfigItem SpamdConfigSchema[] = {
|
||||
{ BONGO_JSON_BOOL, "o:enabled/b", &ASpam.spamd.enabled },
|
||||
{ BONGO_JSON_INT, "o:timeout/i", &ASpam.spamd.connectionTimeout },
|
||||
{ BONGO_JSON_INT, "o:maximum_message_size/i", &ASpam.spamd.maximumMessageSize },
|
||||
{ BONGO_JSON_INT, "o:maximum_response_size/i", &ASpam.spamd.maximumResponseSize },
|
||||
BONGO_CONFIG_INT("o:timeout/i", &ASpam.spamd.connectionTimeout),
|
||||
BONGO_CONFIG_INT("o:maximum_message_size/i", &ASpam.spamd.maximumMessageSize),
|
||||
BONGO_CONFIG_INT("o:maximum_response_size/i", &ASpam.spamd.maximumResponseSize),
|
||||
{ BONGO_JSON_ARRAY, "o:hosts/a", &SpamdHostList},
|
||||
{ BONGO_JSON_NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
@@ -351,9 +351,9 @@ static BongoConfigItem ClamHostList = {
|
||||
};
|
||||
|
||||
static BongoConfigItem AVirusConfigSchema[] = {
|
||||
{ BONGO_JSON_INT, "o:flags/i", &AVirus.flags },
|
||||
{ BONGO_JSON_INT, "o:queue/i", &AVirus.nmap.queue },
|
||||
{ BONGO_JSON_INT, "o:timeout/i", &AVirus.clamd.connectionTimeout },
|
||||
BONGO_CONFIG_INT("o:flags/i", &AVirus.flags),
|
||||
BONGO_CONFIG_INT("o:queue/i", &AVirus.nmap.queue),
|
||||
BONGO_CONFIG_INT("o:timeout/i", &AVirus.clamd.connectionTimeout),
|
||||
{ BONGO_JSON_ARRAY, "o:hosts/a", &ClamHostList},
|
||||
{ BONGO_JSON_NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
+27
-27
@@ -19,34 +19,34 @@
|
||||
* </Novell-copyright>
|
||||
****************************************************************************/
|
||||
|
||||
#define F_UID (1<<0)
|
||||
#define F_FLAGS (1<<1)
|
||||
#define F_ENVELOPE (1<<2)
|
||||
#define F_XSENDER (1<<3)
|
||||
#define F_INTERNALDATE (1<<4)
|
||||
#define F_BODYSTRUCTURE (1<<5)
|
||||
#define F_RFC822_TEXT (1<<6)
|
||||
#define F_RFC822_SIZE (1<<7)
|
||||
#define F_RFC822_HEADER (1<<8)
|
||||
#define F_RFC822_BOTH (1<<9)
|
||||
#define F_BODY (1<<10)
|
||||
#define F_BODY_HEADER (1<<11)
|
||||
#define F_BODY_HEADER_PARTIAL (1<<12)
|
||||
#define F_BODY_TEXT (1<<13)
|
||||
#define F_BODY_TEXT_PARTIAL (1<<14)
|
||||
#define F_BODY_BOTH (1<<15)
|
||||
#define F_BODY_BOTH_PARTIAL (1<<16)
|
||||
#define F_BODY_MIME (1<<17)
|
||||
#define F_BODY_MIME_PARTIAL (1<<18)
|
||||
#define F_BODY_HEADER_FIELDS (1<<19)
|
||||
#define F_BODY_HEADER_FIELDS_NOT (1<<20)
|
||||
#define F_BODY_PART (1<<21)
|
||||
#define F_BODY_SEEN (1<<22)
|
||||
#define F_BINARY (1<<23)
|
||||
#define F_BINARY_SIZE (1<<24)
|
||||
#define F_UID (1UL<<0)
|
||||
#define F_FLAGS (1UL<<1)
|
||||
#define F_ENVELOPE (1UL<<2)
|
||||
#define F_XSENDER (1UL<<3)
|
||||
#define F_INTERNALDATE (1UL<<4)
|
||||
#define F_BODYSTRUCTURE (1UL<<5)
|
||||
#define F_RFC822_TEXT (1UL<<6)
|
||||
#define F_RFC822_SIZE (1UL<<7)
|
||||
#define F_RFC822_HEADER (1UL<<8)
|
||||
#define F_RFC822_BOTH (1UL<<9)
|
||||
#define F_BODY (1UL<<10)
|
||||
#define F_BODY_HEADER (1UL<<11)
|
||||
#define F_BODY_HEADER_PARTIAL (1UL<<12)
|
||||
#define F_BODY_TEXT (1UL<<13)
|
||||
#define F_BODY_TEXT_PARTIAL (1UL<<14)
|
||||
#define F_BODY_BOTH (1UL<<15)
|
||||
#define F_BODY_BOTH_PARTIAL (1UL<<16)
|
||||
#define F_BODY_MIME (1UL<<17)
|
||||
#define F_BODY_MIME_PARTIAL (1UL<<18)
|
||||
#define F_BODY_HEADER_FIELDS (1UL<<19)
|
||||
#define F_BODY_HEADER_FIELDS_NOT (1UL<<20)
|
||||
#define F_BODY_PART (1UL<<21)
|
||||
#define F_BODY_SEEN (1UL<<22)
|
||||
#define F_BINARY (1UL<<23)
|
||||
#define F_BINARY_SIZE (1UL<<24)
|
||||
|
||||
#define F_PARSE_ERROR (1<<30)
|
||||
#define F_SYSTEM_ERROR (1<<31)
|
||||
#define F_PARSE_ERROR (1UL<<30)
|
||||
#define F_SYSTEM_ERROR (1UL<<31)
|
||||
|
||||
#define F_NEED_HEADER (F_BODY_HEADER | F_BODY_HEADER_PARTIAL | F_RFC822_HEADER | F_RFC822_BOTH | F_ENVELOPE | F_BODY_HEADER_FIELDS | F_BODY_HEADER_FIELDS_NOT | F_BODY_MIME | F_BODY_MIME_PARTIAL)
|
||||
#define F_NEED_MIME (F_BODY_PART | F_BODYSTRUCTURE | F_BODY | F_BINARY | F_BINARY_SIZE)
|
||||
|
||||
@@ -4479,12 +4479,12 @@ static BongoConfigItem IMAPProxyProtocolNetwork = {
|
||||
};
|
||||
|
||||
static BongoConfigItem IMAPConfig[] = {
|
||||
{ BONGO_JSON_INT, "o:port/i", &Imap.server.port },
|
||||
{ BONGO_JSON_INT, "o:port_ssl/i", &Imap.server.ssl.port },
|
||||
BONGO_CONFIG_INT("o:port/i", &Imap.server.port),
|
||||
BONGO_CONFIG_INT("o:port_ssl/i", &Imap.server.ssl.port),
|
||||
{ BONGO_JSON_BOOL, "o:allow_legacy_tls/b", &Imap.server.allowLegacyTLS },
|
||||
{ BONGO_JSON_BOOL, "o:proxy_protocol_enabled/b", &Imap.server.proxyProtocolEnabled },
|
||||
{ BONGO_JSON_ARRAY, "o:proxy_protocol_networks/a", &IMAPProxyProtocolNetwork },
|
||||
{ BONGO_JSON_INT, "o:threads_max/i", &Imap.session.threads.max },
|
||||
BONGO_CONFIG_INT("o:threads_max/i", &Imap.session.threads.max),
|
||||
{ BONGO_JSON_NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -119,6 +119,38 @@ IMAPSearchParseReturn(const char *parameters, unsigned int *options,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
IMAPSearchParseStoreHit(const char *response, uint32_t *uid)
|
||||
{
|
||||
const char *cursor;
|
||||
uint64_t parsed_uid = 0;
|
||||
size_t digits = 0;
|
||||
|
||||
if (!response || !uid) return 0;
|
||||
cursor = response;
|
||||
while (*cursor == ' ' || *cursor == '\t') cursor++;
|
||||
while (isxdigit((unsigned char)*cursor)) cursor++;
|
||||
if (!isspace((unsigned char)*cursor)) return 0;
|
||||
while (*cursor == ' ' || *cursor == '\t') cursor++;
|
||||
while (isxdigit((unsigned char)*cursor)) {
|
||||
unsigned int value;
|
||||
|
||||
if (*cursor >= '0' && *cursor <= '9')
|
||||
value = (unsigned int)(*cursor - '0');
|
||||
else
|
||||
value = (unsigned int)(toupper((unsigned char)*cursor) - 'A' + 10);
|
||||
if (parsed_uid > (UINT32_MAX - value) / 16) return 0;
|
||||
parsed_uid = parsed_uid * 16 + value;
|
||||
cursor++;
|
||||
digits++;
|
||||
}
|
||||
while (*cursor == ' ' || *cursor == '\t' ||
|
||||
*cursor == '\r' || *cursor == '\n') cursor++;
|
||||
if (!digits || *cursor) return 0;
|
||||
*uid = (uint32_t)parsed_uid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
AppendQuotedTag(char *buffer, size_t buffer_size, size_t *length,
|
||||
const char *tag)
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
int IMAPSearchParseReturn(const char *parameters, unsigned int *options,
|
||||
const char **criteria);
|
||||
|
||||
/* Parses the document GUID and IMAP UID returned by an NMAP SEARCH hit. */
|
||||
int IMAPSearchParseStoreHit(const char *response, uint32_t *uid);
|
||||
|
||||
/* Formats one complete untagged ESEARCH response, including CRLF. */
|
||||
size_t IMAPSearchFormatEsearch(char *buffer, size_t buffer_size,
|
||||
const char *tag, int by_uid,
|
||||
|
||||
@@ -533,13 +533,13 @@ __inline static long
|
||||
FullListProcessMatch(ImapSession *session __attribute__((unused)), SearchKey *key __attribute__((unused)), char *response)
|
||||
{
|
||||
long ccode;
|
||||
char *ptr;
|
||||
unsigned long sequenceNum;
|
||||
uint32_t uid;
|
||||
|
||||
ptr = strchr(response, ' ');
|
||||
if (ptr) {
|
||||
ptr++;
|
||||
ccode = UidToSequenceNum(&session->folder.selected.message[0], session->folder.selected.messageCount, (uint32_t)HexToUInt64(ptr, NULL), &sequenceNum);
|
||||
if (IMAPSearchParseStoreHit(response, &uid)) {
|
||||
ccode = UidToSequenceNum(&session->folder.selected.message[0],
|
||||
session->folder.selected.messageCount,
|
||||
uid, &sequenceNum);
|
||||
if (ccode == STATUS_CONTINUE) {
|
||||
key->matchList[sequenceNum] = -2 - key->matchList[sequenceNum];
|
||||
return(STATUS_CONTINUE);
|
||||
@@ -558,7 +558,7 @@ FullListSubstringSearch(ImapSession *session __attribute__((unused)), SearchKey
|
||||
for (;;) {
|
||||
ccode = NMAPReadResponse(session->store.conn, session->store.response, sizeof(session->store.response), TRUE);
|
||||
if (ccode == 2001) {
|
||||
FullListProcessMatch(session, key, session->store.response + 5);
|
||||
FullListProcessMatch(session, key, session->store.response);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,7 @@ main(void)
|
||||
uint32_t matches[] = { 2, 3, 4, 9, 11, 12 };
|
||||
uint32_t saved[] = { 3, 9, 99 };
|
||||
uint32_t mailbox[] = { 1, 3, 8, 9, 12 };
|
||||
uint32_t uid;
|
||||
char buffer[256];
|
||||
|
||||
assert(IMAPSearchParseReturn("ALL", &options, &criteria));
|
||||
@@ -49,6 +50,13 @@ main(void)
|
||||
&criteria));
|
||||
assert(!IMAPSearchParseReturn("RETURN (ALL)", &options, &criteria));
|
||||
|
||||
assert(IMAPSearchParseStoreHit("0000000000000010 00000001", &uid));
|
||||
assert(uid == 1);
|
||||
assert(IMAPSearchParseStoreHit("abcdef0123456789 ffffffff\r\n", &uid));
|
||||
assert(uid == UINT32_MAX);
|
||||
assert(!IMAPSearchParseStoreHit("0000000000000010", &uid));
|
||||
assert(!IMAPSearchParseStoreHit("0000000000000010 100000000", &uid));
|
||||
|
||||
assert(IMAPSearchFormatEsearch(buffer, sizeof(buffer), "A42", 0,
|
||||
IMAP_SEARCH_RETURN_MIN | IMAP_SEARCH_RETURN_MAX |
|
||||
IMAP_SEARCH_RETURN_ALL | IMAP_SEARCH_RETURN_COUNT,
|
||||
|
||||
@@ -816,9 +816,9 @@ ProxyServer(void *ignored)
|
||||
// MailProxy.contexts
|
||||
static BongoConfigItem ProxyConfig[] = {
|
||||
{ BONGO_JSON_STRING, "o:postmaster/s", &MailProxy.postmaster },
|
||||
{ BONGO_JSON_INT, "o:interval/i", &MailProxy.runInterval }, // in seconds
|
||||
{ BONGO_JSON_INT, "o:max_threads/i", &MailProxy.max.threadsParallel },
|
||||
{ BONGO_JSON_INT, "o:max_accounts/i", &MailProxy.max.accounts },
|
||||
BONGO_CONFIG_INT("o:interval/i", &MailProxy.runInterval), // in seconds
|
||||
BONGO_CONFIG_INT("o:max_threads/i", &MailProxy.max.threadsParallel),
|
||||
BONGO_CONFIG_INT("o:max_accounts/i", &MailProxy.max.accounts),
|
||||
{ BONGO_JSON_STRING, "o:queue/s", &MailProxy.nmap.address },
|
||||
{ BONGO_JSON_NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -2378,8 +2378,8 @@ static BongoConfigItem POP3ProxyProtocolNetwork = {
|
||||
};
|
||||
|
||||
static BongoConfigItem POP3Config[] = {
|
||||
{ BONGO_JSON_INT, "o:port/i", &POP3ServerPort },
|
||||
{ BONGO_JSON_INT, "o:port_ssl/i", &POP3ServerPortSSL },
|
||||
BONGO_CONFIG_INT("o:port/i", &POP3ServerPort),
|
||||
BONGO_CONFIG_INT("o:port_ssl/i", &POP3ServerPortSSL),
|
||||
{ BONGO_JSON_BOOL, "o:allow_legacy_tls/b", &POP3.server.ssl.allowLegacyTLS },
|
||||
{ BONGO_JSON_BOOL, "o:proxy_protocol_enabled/b", &POP3.server.proxyProtocolEnabled },
|
||||
{ BONGO_JSON_ARRAY, "o:proxy_protocol_networks/a", &POP3ProxyProtocolNetwork },
|
||||
|
||||
+15
-15
@@ -81,26 +81,26 @@ static BongoConfigItem QueueConfig[] = {
|
||||
{ BONGO_JSON_BOOL, "o:debug/b", &Conf.debug },
|
||||
{ BONGO_JSON_ARRAY, "o:domains/a", &domainsConfig },
|
||||
{ BONGO_JSON_BOOL, "o:limitremoteprocessing/b", &Conf.deferEnabled },
|
||||
{ BONGO_JSON_INT, "o:limitremotebegweekday/i", &Conf.i_deferStartWD },
|
||||
{ BONGO_JSON_INT, "o:limitremotebegweekend/i", &Conf.i_deferStartWE },
|
||||
{ BONGO_JSON_INT, "o:limitremoteendweekday/i", &Conf.i_deferEndWD },
|
||||
{ BONGO_JSON_INT, "o:limitremoteendweekend/i", &Conf.i_deferEndWE },
|
||||
{ BONGO_JSON_INT, "o:queuetuning_concurrent/i", &Conf.maxConcurrentWorkers },
|
||||
{ BONGO_JSON_INT, "o:queuetuning_sequential/i", &Conf.maxSequentialWorkers },
|
||||
{ BONGO_JSON_INT, "o:queuetuning_load_high/i", &Conf.loadMonitorHigh },
|
||||
{ BONGO_JSON_INT, "o:queuetuning_load_low/i", &Conf.loadMonitorLow },
|
||||
{ BONGO_JSON_INT, "o:queuetuning_trigger/i", &Conf.limitTrigger },
|
||||
{ BONGO_JSON_INT, "o:queuetimeout/i", &Conf.maxLinger },
|
||||
BONGO_CONFIG_INT("o:limitremotebegweekday/i", &Conf.i_deferStartWD),
|
||||
BONGO_CONFIG_INT("o:limitremotebegweekend/i", &Conf.i_deferStartWE),
|
||||
BONGO_CONFIG_INT("o:limitremoteendweekday/i", &Conf.i_deferEndWD),
|
||||
BONGO_CONFIG_INT("o:limitremoteendweekend/i", &Conf.i_deferEndWE),
|
||||
BONGO_CONFIG_INT("o:queuetuning_concurrent/i", &Conf.maxConcurrentWorkers),
|
||||
BONGO_CONFIG_INT("o:queuetuning_sequential/i", &Conf.maxSequentialWorkers),
|
||||
BONGO_CONFIG_INT("o:queuetuning_load_high/i", &Conf.loadMonitorHigh),
|
||||
BONGO_CONFIG_INT("o:queuetuning_load_low/i", &Conf.loadMonitorLow),
|
||||
BONGO_CONFIG_INT("o:queuetuning_trigger/i", &Conf.limitTrigger),
|
||||
BONGO_CONFIG_INT("o:queuetimeout/i", &Conf.maxLinger),
|
||||
{ BONGO_JSON_STRING, "o:quotamessage/s", &Conf.quotaMessage },
|
||||
{ BONGO_JSON_INT, "o:port/i", &Agent.agent.port },
|
||||
BONGO_CONFIG_INT("o:port/i", &Agent.agent.port),
|
||||
{ BONGO_JSON_BOOL, "o:forwardundeliverable_enabled/b", &Conf.forwardUndeliverableEnabled },
|
||||
{ BONGO_JSON_STRING, "o:forwardundeliverable_to/s", &Conf.forwardUndeliverableAddress },
|
||||
{ BONGO_JSON_INT, "o:queueinterval/i", &Conf.queueInterval },
|
||||
{ BONGO_JSON_INT, "o:minimumfreespace/i", &Conf.minimumFree },
|
||||
BONGO_CONFIG_INT("o:queueinterval/i", &Conf.queueInterval),
|
||||
BONGO_CONFIG_INT("o:minimumfreespace/i", &Conf.minimumFree),
|
||||
{ BONGO_JSON_ARRAY, "o:trustedhosts/a", &trustedHostsConfig },
|
||||
{ BONGO_JSON_BOOL, "o:rtsantispamconfig_enabled/b", &Conf.bounceBlockSpam },
|
||||
{ BONGO_JSON_INT, "o:rtsantispamconfig_delay/i", &Conf.bounceInterval },
|
||||
{ BONGO_JSON_INT, "o:rtsantispamconfig_threshold/i", &Conf.bounceMax },
|
||||
BONGO_CONFIG_INT("o:rtsantispamconfig_delay/i", &Conf.bounceInterval),
|
||||
BONGO_CONFIG_INT("o:rtsantispamconfig_threshold/i", &Conf.bounceMax),
|
||||
{ BONGO_JSON_BOOL, "o:bouncereturn/b", &Conf.b_bounceReturn },
|
||||
{ BONGO_JSON_BOOL, "o:bounceccpostmaster/b", &Conf.b_bounceCCPostmaster },
|
||||
{ BONGO_JSON_NULL, NULL, NULL }
|
||||
|
||||
@@ -53,12 +53,12 @@ static BongoConfigItem ProxyProtocolNetwork = {
|
||||
|
||||
static BongoConfigItem SieveConfig[] = {
|
||||
{ BONGO_JSON_STRING, "o:listen_address/s", &listen_address },
|
||||
{ BONGO_JSON_INT, "o:port/i", &server_port },
|
||||
BONGO_CONFIG_INT("o:port/i", &server_port),
|
||||
{ BONGO_JSON_BOOL, "o:allow_legacy_tls/b", &allow_legacy_tls },
|
||||
{ BONGO_JSON_BOOL, "o:proxy_protocol_enabled/b", &proxy_protocol_enabled },
|
||||
{ BONGO_JSON_ARRAY, "o:proxy_protocol_networks/a", &ProxyProtocolNetwork },
|
||||
{ BONGO_JSON_INT, "o:maximum_script_size/i", &maximum_script_size },
|
||||
{ BONGO_JSON_INT, "o:maximum_connections/i", &maximum_connections },
|
||||
BONGO_CONFIG_INT("o:maximum_script_size/i", &maximum_script_size),
|
||||
BONGO_CONFIG_INT("o:maximum_connections/i", &maximum_connections),
|
||||
{ BONGO_JSON_NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
+16
-16
@@ -125,22 +125,22 @@ static BongoConfigItem ProxyProtocolNetworkList = {
|
||||
};
|
||||
|
||||
static BongoConfigItem SMTPConfig[] = {
|
||||
{ BONGO_JSON_INT, "o:port/i", &SMTP.port },
|
||||
{ BONGO_JSON_INT, "o:port_ssl/i", &SMTP.port_ssl },
|
||||
BONGO_CONFIG_INT("o:port/i", &SMTP.port),
|
||||
BONGO_CONFIG_INT("o:port_ssl/i", &SMTP.port_ssl),
|
||||
{ BONGO_JSON_BOOL, "o:submission_enabled/b", &SMTP.submission_enabled },
|
||||
{ BONGO_JSON_INT, "o:submission_port/i", &SMTP.submission_port },
|
||||
{ BONGO_JSON_INT, "o:submission_port_ssl/i", &SMTP.submission_port_ssl },
|
||||
BONGO_CONFIG_INT("o:submission_port/i", &SMTP.submission_port),
|
||||
BONGO_CONFIG_INT("o:submission_port_ssl/i", &SMTP.submission_port_ssl),
|
||||
{ BONGO_JSON_BOOL, "o:submission_require_auth/b", &SMTP.submission_require_auth },
|
||||
{ BONGO_JSON_BOOL, "o:submission_allow_sender_override/b", &SMTP.submission_allow_sender_override },
|
||||
{ BONGO_JSON_BOOL, "o:internal_relay_enabled/b", &SMTP.internal_relay_enabled },
|
||||
{ BONGO_JSON_INT, "o:internal_relay_port/i", &SMTP.internal_relay_port },
|
||||
BONGO_CONFIG_INT("o:internal_relay_port/i", &SMTP.internal_relay_port),
|
||||
{ BONGO_JSON_STRING, "o:internal_relay_bind_address/s", &SMTP.internal_relay_bind_address },
|
||||
{ BONGO_JSON_ARRAY, "o:internal_relay_networks/a", &InternalRelayNetworkList },
|
||||
{ BONGO_JSON_BOOL, "o:internal_relay_allow_legacy_tls/b", &SMTP.internal_relay_allow_legacy_tls },
|
||||
{ BONGO_JSON_INT, "o:internal_relay_messages_per_minute/i", &SMTP.internal_relay_messages_per_minute },
|
||||
{ BONGO_JSON_INT, "o:internal_relay_recipients_per_minute/i", &SMTP.internal_relay_recipients_per_minute },
|
||||
{ BONGO_JSON_INT, "o:internal_relay_bytes_per_minute/i", &SMTP.internal_relay_bytes_per_minute },
|
||||
{ BONGO_JSON_INT, "o:internal_relay_connections_per_ip/i", &SMTP.internal_relay_connections_per_ip },
|
||||
BONGO_CONFIG_INT("o:internal_relay_messages_per_minute/i", &SMTP.internal_relay_messages_per_minute),
|
||||
BONGO_CONFIG_INT("o:internal_relay_recipients_per_minute/i", &SMTP.internal_relay_recipients_per_minute),
|
||||
BONGO_CONFIG_INT("o:internal_relay_bytes_per_minute/i", &SMTP.internal_relay_bytes_per_minute),
|
||||
BONGO_CONFIG_INT("o:internal_relay_connections_per_ip/i", &SMTP.internal_relay_connections_per_ip),
|
||||
{ BONGO_JSON_STRING, "o:internal_relay_domain/s", &SMTP.internal_relay_domain },
|
||||
{ BONGO_JSON_ARRAY, "o:internal_relay_device_mappings/a", &InternalRelayDeviceMappingList },
|
||||
{ BONGO_JSON_ARRAY, "o:internal_relay_dns_suffixes/a", &InternalRelayDNSSuffixList },
|
||||
@@ -155,16 +155,16 @@ static BongoConfigItem SMTPConfig[] = {
|
||||
{ BONGO_JSON_BOOL, "o:verify_address/b", &SMTP.verify_address },
|
||||
{ BONGO_JSON_BOOL, "o:accept_etrn/b", &SMTP.accept_etrn },
|
||||
{ BONGO_JSON_BOOL, "o:send_etrn/b", &SMTP.send_etrn },
|
||||
{ BONGO_JSON_INT, "o:maximum_recipients/i", &SMTP.max_recips },
|
||||
{ BONGO_JSON_INT, "o:message_size_limit/i", &SMTP.message_limit },
|
||||
BONGO_CONFIG_INT("o:maximum_recipients/i", &SMTP.max_recips),
|
||||
BONGO_CONFIG_INT("o:message_size_limit/i", &SMTP.message_limit),
|
||||
{ BONGO_JSON_BOOL, "o:use_relay_host/b", &SMTP.use_relay },
|
||||
{ BONGO_JSON_STRING, "o:relay_host/s", &SMTP.relay_host },
|
||||
{ BONGO_JSON_BOOL, "o:block_rts_spam/b", &SMTP.block_rts },
|
||||
{ BONGO_JSON_INT, "o:max_thread_load/i", &SMTP.max_thread_load },
|
||||
{ BONGO_JSON_INT, "o:max_flood_count/i", &SMTP.max_flood_count }, // UNUSED ?
|
||||
{ BONGO_JSON_INT, "o:max_null_sender/i", &SMTP.max_null_sender },
|
||||
{ BONGO_JSON_INT, "o:socket_timeout/i", &SMTP.socket_timeout },
|
||||
{ BONGO_JSON_INT, "o:max_mx_servers/i", &SMTP.max_mx_servers },
|
||||
BONGO_CONFIG_INT("o:max_thread_load/i", &SMTP.max_thread_load),
|
||||
BONGO_CONFIG_INT("o:max_flood_count/i", &SMTP.max_flood_count), // UNUSED ?
|
||||
BONGO_CONFIG_INT("o:max_null_sender/i", &SMTP.max_null_sender),
|
||||
BONGO_CONFIG_INT("o:socket_timeout/i", &SMTP.socket_timeout),
|
||||
BONGO_CONFIG_INT("o:max_mx_servers/i", &SMTP.max_mx_servers),
|
||||
{ BONGO_JSON_BOOL, "o:relay_local_mail/b", &SMTP.relay_local },
|
||||
{ BONGO_JSON_BOOL, "o:require_auth/b", &SMTP.require_auth },
|
||||
{ BONGO_JSON_BOOL, "o:spf_verify/b", &SMTP.spf_verify },
|
||||
|
||||
@@ -41,10 +41,9 @@ ReadSourceFile(void *source, char *buffer, unsigned long maxRead)
|
||||
__inline static CCode
|
||||
ReportHit(Connection *conn, StoreObject *document)
|
||||
{
|
||||
// FIXME: imap uids
|
||||
return ConnWriteF(conn,
|
||||
"2001 " GUID_FMT " %08x\r\n",
|
||||
document->guid, (uint32_t) document->guid);
|
||||
document->guid, document->imap_uid);
|
||||
}
|
||||
|
||||
static CCode
|
||||
|
||||
@@ -25,6 +25,7 @@ from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import mock
|
||||
from pathlib import Path
|
||||
|
||||
SOURCE = Path(__file__).resolve().parents[4]
|
||||
@@ -102,6 +103,28 @@ class ConfigurationModelTest(unittest.TestCase):
|
||||
self.assertFalse(errors(validate_all(
|
||||
configs, defaults, check_files=False)))
|
||||
|
||||
def test_web_databases_follow_configured_state_directory(self):
|
||||
defaults = templates()
|
||||
with mock.patch.dict("os.environ", {
|
||||
"BONGO_STATE_DIR": "/srv/bongo-test-state"}):
|
||||
configs = apply_scenario(defaults, Scenario(
|
||||
hostname="mail.example.test",
|
||||
bind_address="127.0.0.1",
|
||||
domains=["example.test"],
|
||||
admin_password="0123456789ab",
|
||||
web_mode="direct",
|
||||
web_public_url="http://127.0.0.1:8080",
|
||||
))
|
||||
self.assertEqual(
|
||||
configs["web"]["session_database"],
|
||||
"/srv/bongo-test-state/web/sessions.db")
|
||||
self.assertEqual(
|
||||
configs["web"]["task_database"],
|
||||
"/srv/bongo-test-state/web/tasks.db")
|
||||
self.assertEqual(
|
||||
configs["web"]["identity_database"],
|
||||
"/srv/bongo-test-state/web/identities.db")
|
||||
|
||||
def test_proxy_requires_trusted_network(self):
|
||||
defaults = templates()
|
||||
configs = apply_scenario(defaults, Scenario(
|
||||
|
||||
@@ -1108,8 +1108,10 @@ GenerateInstancesForChunk (BongoCalInstance *inst,
|
||||
DPRINT("now have %d occurrences\n", occs->len);
|
||||
DPRINT("and %d exception occurrences\n", exOccs->len);
|
||||
|
||||
qsort (rdatePeriods->data, rdatePeriods->len,
|
||||
sizeof (CalObjRecurrenceDate), CalObjCompareFunc);
|
||||
if (rdatePeriods->len > 1) {
|
||||
qsort (rdatePeriods->data, rdatePeriods->len,
|
||||
sizeof (CalObjRecurrenceDate), CalObjCompareFunc);
|
||||
}
|
||||
|
||||
/* Create the final array, by removing the exceptions from the
|
||||
occurrences, and removing any duplicates. */
|
||||
@@ -1782,6 +1784,12 @@ CalObjInitializeRecurData (RecurData *recurData,
|
||||
static void
|
||||
CalObjSortOccurrences (GArray *occs)
|
||||
{
|
||||
/* GLib leaves data NULL for an empty array. The C library declares the
|
||||
* qsort base argument non-null even when nmemb is zero, so avoid passing
|
||||
* the empty-array representation through to qsort. */
|
||||
if (!occs || occs->len < 2)
|
||||
return;
|
||||
|
||||
qsort (occs->data, occs->len, sizeof (CalObjTime),
|
||||
CalObjCompareFunc);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,15 @@ def _safe_absolute_path(value: Any) -> bool:
|
||||
return value != "/" and ".." not in Path(value).parts
|
||||
|
||||
|
||||
def _state_directory() -> Path:
|
||||
"""Return the state root compiled into Bongo, with a source-tree fallback."""
|
||||
try:
|
||||
from bongo import Xpl
|
||||
return Path(Xpl.DEFAULT_STATE_DIR)
|
||||
except ImportError:
|
||||
return Path(os.environ.get("BONGO_STATE_DIR", "/var/lib/bongo"))
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Issue:
|
||||
document: str
|
||||
@@ -284,6 +293,10 @@ def apply_scenario(templates: Mapping[str, Any], scenario: Scenario) -> dict[str
|
||||
web["tls_key"] = ""
|
||||
web["public_base_url"] = scenario.web_public_url
|
||||
web["client_ip_header"] = "X-Forwarded-For"
|
||||
web_state = _state_directory() / "web"
|
||||
web["session_database"] = str(web_state / "sessions.db")
|
||||
web["task_database"] = str(web_state / "tasks.db")
|
||||
web["identity_database"] = str(web_state / "identities.db")
|
||||
|
||||
configs["authentication"].update({
|
||||
"AuthLdapEnabled": scenario.ldap_enabled,
|
||||
|
||||
@@ -12,6 +12,7 @@ add_library(bongoutil SHARED
|
||||
quicksort.c
|
||||
utf7mod.c
|
||||
logging.c
|
||||
config-integer.c
|
||||
bongoagent.c
|
||||
bongoutil.c)
|
||||
|
||||
@@ -22,3 +23,14 @@ target_link_libraries(bongoutil
|
||||
)
|
||||
|
||||
install(TARGETS bongoutil DESTINATION ${LIB_INSTALL_DIR})
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_executable(util-config-integer-test
|
||||
tests/config-integer-test.c config-integer.c)
|
||||
target_compile_definitions(util-config-integer-test PRIVATE _NO_BONGO_GLOBALS)
|
||||
add_test(NAME util-config-integer COMMAND util-config-integer-test)
|
||||
|
||||
add_executable(util-array-test tests/array-test.c array.c)
|
||||
target_link_libraries(util-array-test PRIVATE GLib2::GLib2)
|
||||
add_test(NAME util-array COMMAND util-array-test)
|
||||
endif()
|
||||
|
||||
@@ -7,7 +7,7 @@ GArrayFindUnsorted(GArray *array, void *needle, ArrayCompareFunc compare)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!array || !compare) {
|
||||
if (!array || !needle || !compare || array->len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ GArrayFindSorted(GArray *array, void *needle, ssize_t type_size, ArrayCompareFun
|
||||
{
|
||||
void *data;
|
||||
|
||||
if (!array || !compare) {
|
||||
if (!array || !needle || !compare || type_size <= 0 || array->len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,11 @@ FreeBongoConfiguration(BongoConfigItem *config) {
|
||||
|
||||
BOOL
|
||||
SetBongoConfigItem(BongoConfigItem *schema, BongoJsonNode *node) {
|
||||
if (!node || node->type != schema->type) {
|
||||
if (!schema || !node) {
|
||||
XplConsolePrintf("config: missing schema or data node\r\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (node->type != schema->type) {
|
||||
XplConsolePrintf("config: didn't find data at %s (type: %d, want: %d) \r\n", schema->source, node->type, schema->type);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -156,8 +160,15 @@ SetBongoConfigItem(BongoConfigItem *schema, BongoJsonNode *node) {
|
||||
}
|
||||
break;
|
||||
case BONGO_JSON_INT: {
|
||||
int *dest = (int *)schema->destination;
|
||||
*dest = BongoJsonNodeAsInt(node);
|
||||
BongoConfigIntegerDestination *destination = schema->destination;
|
||||
int value = BongoJsonNodeAsInt(node);
|
||||
|
||||
if (!SetBongoConfigInteger(destination, value)) {
|
||||
XplConsolePrintf("config: unsupported integer destination size %zu at %s\r\n",
|
||||
destination ? destination->size : 0U,
|
||||
schema->source);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BONGO_JSON_STRING: {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
* <Novell-copyright>
|
||||
* Copyright (c) 2001 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* </Novell-copyright>
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bongoagent.h>
|
||||
|
||||
BOOL
|
||||
SetBongoConfigInteger(BongoConfigIntegerDestination *destination, int value)
|
||||
{
|
||||
if (!destination || !destination->pointer)
|
||||
return FALSE;
|
||||
if (destination->size == sizeof(uint8_t)) {
|
||||
uint8_t converted = (uint8_t)value;
|
||||
memcpy(destination->pointer, &converted, sizeof(converted));
|
||||
} else if (destination->size == sizeof(uint16_t)) {
|
||||
uint16_t converted = (uint16_t)value;
|
||||
memcpy(destination->pointer, &converted, sizeof(converted));
|
||||
} else if (destination->size == sizeof(uint32_t)) {
|
||||
uint32_t converted = (uint32_t)value;
|
||||
memcpy(destination->pointer, &converted, sizeof(converted));
|
||||
} else if (destination->size == sizeof(uint64_t)) {
|
||||
uint64_t converted = (uint64_t)(int64_t)value;
|
||||
memcpy(destination->pointer, &converted, sizeof(converted));
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
* <Novell-copyright>
|
||||
* Copyright (c) 2001 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* </Novell-copyright>
|
||||
****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <bongoutil.h>
|
||||
|
||||
static int
|
||||
CompareInt(const void *left, const void *right)
|
||||
{
|
||||
int a = *(const int *)left;
|
||||
int b = *(const int *)right;
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
GArray *values = g_array_new(FALSE, FALSE, sizeof(int));
|
||||
int needle = 7;
|
||||
int value;
|
||||
|
||||
assert(values != NULL);
|
||||
assert(GArrayFindSorted(values, &needle, sizeof(int), CompareInt) == -1);
|
||||
assert(GArrayFindSorted(values, NULL, sizeof(int), CompareInt) == -1);
|
||||
assert(GArrayFindSorted(values, &needle, 0, CompareInt) == -1);
|
||||
|
||||
value = 3;
|
||||
g_array_append_val(values, value);
|
||||
value = 7;
|
||||
g_array_append_val(values, value);
|
||||
value = 9;
|
||||
g_array_append_val(values, value);
|
||||
assert(GArrayFindSorted(values, &needle, sizeof(int), CompareInt) == 1);
|
||||
g_array_free(values, TRUE);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
* <Novell-copyright>
|
||||
* Copyright (c) 2001 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* </Novell-copyright>
|
||||
****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bongoagent.h>
|
||||
|
||||
static void
|
||||
CheckIntegerWidth(size_t offset, size_t width, int input, uint64_t expected)
|
||||
{
|
||||
unsigned char storage[32];
|
||||
BongoConfigIntegerDestination destination;
|
||||
uint64_t actual = 0;
|
||||
|
||||
assert(offset + width <= sizeof(storage));
|
||||
memset(storage, 0xa5, sizeof(storage));
|
||||
destination.pointer = storage + offset;
|
||||
destination.size = width;
|
||||
assert(SetBongoConfigInteger(&destination, input));
|
||||
memcpy(&actual, storage + offset, width);
|
||||
if (width < sizeof(actual))
|
||||
actual &= (UINT64_C(1) << (width * 8U)) - 1U;
|
||||
assert(actual == expected);
|
||||
assert(storage[offset - 1U] == 0xa5);
|
||||
assert(storage[offset + width] == 0xa5);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
/* Every destination starts at an intentionally unaligned offset. */
|
||||
CheckIntegerWidth(1U, sizeof(uint8_t), 0x7f, UINT64_C(0x7f));
|
||||
CheckIntegerWidth(1U, sizeof(uint16_t), 65535, UINT64_C(0xffff));
|
||||
CheckIntegerWidth(1U, sizeof(uint32_t), -7, UINT64_C(0xfffffff9));
|
||||
CheckIntegerWidth(1U, sizeof(uint64_t), -7,
|
||||
UINT64_C(0xfffffffffffffff9));
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user