Harden Store administration and credential handling

This commit is contained in:
Mario Fetka
2026-07-18 12:37:23 +02:00
parent 0d86ee9d98
commit 9a4cbf4bad
9 changed files with 197 additions and 30 deletions
+32 -7
View File
@@ -41,6 +41,7 @@
#define DEFAULT_EXTENSION_HOURS 48L
#define MAX_EXTENSION_HOURS (24L * 31L)
#define MAX_CONFIG_DOCUMENT_SIZE (1024U * 1024U)
#define ADMIN_STORE_TIMEOUT_SECONDS 15U
#ifndef BONGO_CONFIG_UI_PATH
#define BONGO_CONFIG_UI_PATH "/usr/libexec/bongo/bongo-config-ui"
@@ -48,6 +49,22 @@
static int ValidCommandName(const char *name);
static int
IsAdministrativeUser(void)
{
const char *service_user;
uid_t service_uid;
gid_t service_gid;
if (geteuid() == 0)
return 1;
service_user = MsgGetUnprivilegedUser();
if (!service_user ||
XplLookupUser(service_user, &service_uid, &service_gid) != 0)
return 0;
return geteuid() == service_uid;
}
static int
ValidConfigurationName(const char *name)
{
@@ -165,7 +182,7 @@ AccessConfiguration(const char *name, int replace)
}
XplInit();
if (!ConnStartup(15 * 60)) {
if (!ConnStartup(ADMIN_STORE_TIMEOUT_SECONDS)) {
fprintf(stderr, "bongo-admin: cannot initialize networking\n");
goto done;
}
@@ -361,12 +378,15 @@ ShowAgents(const char *requested)
int result = 1;
XplInit();
if (!ConnStartup(15 * 60))
if (!ConnStartup(ADMIN_STORE_TIMEOUT_SECONDS))
goto done;
conn_started = 1;
MsgInit();
msg_started = 1;
NMAPInitialize();
if (!NMAPInitialize()) {
fprintf(stderr, "bongo-admin: cannot load the Store credential\n");
goto done;
}
if (!NMAPReadConfigFile("manager", &config) || !config) {
fprintf(stderr, "bongo-admin: cannot read live manager configuration\n");
goto done;
@@ -468,12 +488,15 @@ RenameUser(const char *old_username, const char *new_username)
return 1;
}
XplInit();
if (!ConnStartup(15 * 60)) {
if (!ConnStartup(ADMIN_STORE_TIMEOUT_SECONDS)) {
fprintf(stderr, "bongo-admin: cannot initialize networking\n");
return 1;
}
MsgInit();
NMAPInitialize();
if (!NMAPInitialize()) {
fprintf(stderr, "bongo-admin: cannot load the Store credential\n");
goto done;
}
connection = NMAPConnect("127.0.0.1", NULL);
if (!connection ||
!NMAPAuthenticateToStore(connection, response, sizeof(response))) {
@@ -621,8 +644,10 @@ main(int argc, char **argv)
Usage(stderr);
return 2;
}
if (geteuid() != 0) {
fprintf(stderr, "bongo-admin: this command must be run as root\n");
if (!IsAdministrativeUser()) {
fprintf(stderr,
"bongo-admin: this command must be run as root or the Bongo "
"service user\n");
return 1;
}
if (argc == 3 && !strcmp(argv[1], "__config-read"))
+10
View File
@@ -23,6 +23,7 @@ from __future__ import annotations
import copy
import json
import subprocess
import sys
import tempfile
import unittest
@@ -122,6 +123,15 @@ class ConfigurationStorageTest(unittest.TestCase):
self.store.save(configurations)
self.assertEqual(self.store.live["smtp"], original_smtp)
def test_store_helper_timeout_names_operation_and_document(self):
store = ConfigurationStore(self.paths)
with mock.patch("subprocess.run", side_effect=subprocess.TimeoutExpired(
[str(self.paths.admin), "__config-read", "sieve"], 30)):
with self.assertRaisesRegex(
ConfigurationError,
r"timed out during __config-read for sieve"):
store.read_store_document("sieve")
def test_scanner_ping_probes_require_expected_reply(self):
clam = FakeSocket(b"PONG\0")
spam = FakeSocket(b"SPAMD/1.5 0 PONG\r\n")