Fix sanitizer findings in agent configuration and IMAP

This commit is contained in:
Mario Fetka
2026-07-19 11:46:35 +02:00
parent 50a38f2325
commit ed6fc871e3
24 changed files with 369 additions and 90 deletions
+16
View File
@@ -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);
+3 -3
View File
@@ -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 },
};
+3 -3
View File
@@ -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
View File
@@ -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)
+3 -3
View File
@@ -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 }
};
+32
View File
@@ -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)
+3
View File
@@ -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,
+6 -6
View File
@@ -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,
+3 -3
View File
@@ -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 }
};
+2 -2
View File
@@ -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
View File
@@ -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 }
+3 -3
View File
@@ -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
View File
@@ -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 },
+1 -2
View File
@@ -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(
+10 -2
View File
@@ -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
View File
@@ -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()
+2 -2
View File
@@ -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;
}
+14 -3
View File
@@ -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: {
+45
View File
@@ -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;
}
+54
View File
@@ -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;
}
+55
View File
@@ -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;
}