179{
180 std::istringstream input(content);
181 Policy policy;
182 std::string section;
184 std::size_t lineNumber = 0;
185 std::uint32_t nextRuleId = 1;
186
187 while (std::getline(input, line)) {
188 ++lineNumber;
190 if (
line.empty() ||
line.front() ==
'#' ||
line.front() ==
';')
191 continue;
192
193 if (
line.front() ==
'[' &&
line.back() ==
']') {
195 continue;
196 }
197
198 const auto separator =
line.find(
'=');
199 if (separator == std::string::npos)
200 throw std::runtime_error("riga policy non valida: " +
201 std::to_string(lineNumber));
202
203 const std::string key =
lower(
trim(
line.substr(0, separator)));
204 const std::string value =
unquote(
line.substr(separator + 1));
205
206 if (section == "engine") {
207 if (key == "version") {
208 policy.version =
parseUint32(value, lineNumber,
"version");
209 } else if (key == "mode") {
210 policy.mode =
parseMode(value, lineNumber);
211 } else if (key == "unknown_action") {
212 policy.unknownAction =
parseAction(value, lineNumber,
"unknown_action");
213 } else if (key == "metadata_action") {
214 policy.metadataAction =
parseAction(value, lineNumber,
"metadata_action");
215 } else if (key == "global_metadata_action") {
216 policy.globalMetadataAction =
217 parseAction(value, lineNumber,
"global_metadata_action");
218 } else if (key == "credential_anomaly_action") {
219 policy.credentialAnomalyAction =
220 parseAction(value, lineNumber,
"credential_anomaly_action");
221 } else if (key == "allow_missing_paths") {
222 policy.allowMissingPaths =
parseBool(value, lineNumber);
223 } else if (key == "require_root_owned_trusted_executables") {
224 policy.requireRootOwnedTrustedExecutables =
parseBool(value, lineNumber);
225 } else if (key == "protect_trusted_executables") {
226 policy.protectTrustedExecutables =
parseBool(value, lineNumber);
227 } else if (key == "monitor_global_privilege_metadata") {
228 policy.monitorGlobalPrivilegeMetadata =
parseBool(value, lineNumber);
229 } else if (key == "detect_global_metadata_bursts") {
230 policy.detectGlobalMetadataBursts =
parseBool(value, lineNumber);
231 } else if (key == "global_metadata_sample_limit") {
232 policy.globalMetadataSampleLimit =
parseUint32(value, lineNumber,
"global_metadata_sample_limit");
233 } else if (key == "metadata_burst_threshold") {
234 policy.metadataBurstThreshold =
parseUint32(value, lineNumber,
"metadata_burst_threshold");
235 } else if (key == "metadata_burst_window_ms") {
236 policy.metadataBurstWindowMs =
parseUint32(value, lineNumber,
"metadata_burst_window_ms");
237 } else if (key == "metadata_burst_cooldown_ms") {
238 policy.metadataBurstCooldownMs =
parseUint32(value, lineNumber,
"metadata_burst_cooldown_ms");
239 } else if (key == "ignore_run_global_metadata") {
240 policy.ignoreRunGlobalMetadata =
parseBool(value, lineNumber);
241 } else if (key == "log_trusted") {
242 policy.logTrusted =
parseBool(value, lineNumber);
243 } else if (key == "auto_block_system_services") {
244 policy.autoBlockSystemServices =
parseBool(value, lineNumber);
245 } else if (key == "block_user_home") {
246 policy.blockUserHome =
parseBool(value, lineNumber);
247 } else if (key == "integrity_poll_seconds") {
248 policy.integrityPollSeconds =
249 parseUint32(value, lineNumber,
"integrity_poll_seconds");
250 } else if (key == "event_log") {
251 policy.eventLog = value;
252 } else {
253 throw std::runtime_error("chiave engine sconosciuta alla riga " +
254 std::to_string(lineNumber) + ": " + key);
255 }
256 } else if (section == "trusted-applications" ||
257 section == "trusted-executables" ||
258 section == "denied-executables" ||
259 section == "protected-paths" ||
260 section == "ignored-paths") {
261 const bool recursiveKey =
262 key == "recursive_path" || key == "required_recursive_path";
263 const bool regularKey = key == "path" || key == "required_path";
264 if (!regularKey && !recursiveKey)
265 throw std::runtime_error("chiave policy sconosciuta alla riga " +
266 std::to_string(lineNumber) + ": " + key);
267 if (recursiveKey &&
268 section != "protected-paths" &&
269 section != "ignored-paths") {
270 throw std::runtime_error(
271 "le regole ricorsive sono ammesse soltanto in [protected-paths] "
272 "o [ignored-paths] alla riga " +
273 std::to_string(lineNumber));
274 }
275
276 const bool required =
277 key == "required_path" || key == "required_recursive_path";
278 PolicyPath entry{nextRuleId++, value, required, recursiveKey};
279 if (section == "trusted-applications")
280 policy.trustedApplications.push_back(std::move(entry));
281 else if (section == "trusted-executables")
282 policy.trustedExecutables.push_back(std::move(entry));
283 else if (section == "denied-executables")
284 policy.deniedExecutables.push_back(std::move(entry));
285 else if (section == "protected-paths")
286 policy.protectedPaths.push_back(std::move(entry));
287 else
288 policy.ignoredPaths.push_back(std::move(entry));
289 } else {
290 throw std::runtime_error("sezione policy mancante o sconosciuta alla riga " +
291 std::to_string(lineNumber));
292 }
293 }
294
295 try {
297 } catch (const std::exception& error) {
298 throw std::runtime_error(source.string() + ": " + error.what());
299 }
300 return policy;
301}
std::string trim(std::string value)
std::string lower(std::string value)
std::string unquote(std::string value)
void validate(const Policy &policy)
bool parseBool(const std::string &value, const std::size_t line)
Action parseAction(const std::string &value, const std::size_t line, const char *keyName)
Mode parseMode(const std::string &value, const std::size_t line)
std::uint32_t parseUint32(const std::string &value, const std::size_t line, const char *keyName)