/*1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2019-2020 Todd C. Miller <[email protected]>4*5* Permission to use, copy, modify, and distribute this software for any6* purpose with or without fee is hereby granted, provided that the above7* copyright notice and this permission notice appear in all copies.8*9* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES10* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF11* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR12* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES13* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN14* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF15* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.16*/1718#include <config.h>19#include <string.h>2021#include <ctype.h>22#include <stdlib.h>2324#include <sudo_gettext.h>25#include <sudo_compat.h>26#include "sudo_python_debug.h"27#include <sudo_queue.h>28#include <sudo_conf.h>29#include <sudo_fatal.h>303132static int python_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;33static unsigned int python_debug_refcnt;3435static const char *const python_subsystem_names[] = {36"py_calls", // logs c -> py calls37"c_calls", // logs py -> c calls38"load", // logs python plugin loading / unloading39"sudo_cb", // logs sudo callback calls40"internal", // logs internal functions of the language wrapper plugin41"plugin", // logs whatever log the python module would like to log through sudo.debug API42NULL43};4445#define NUM_SUBSYSTEMS sizeof(python_subsystem_names) / sizeof(*python_subsystem_names) - 14647/* Subsystem IDs assigned at registration time. */48unsigned int python_subsystem_ids[NUM_SUBSYSTEMS];4950/*51* Parse the "filename flags,..." debug_flags entry and insert a new52* sudo_debug_file struct into debug_files.53*/54bool55python_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files,56const char *entry)57{58/* Already initialized? */59if (python_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER)60return true;6162return sudo_debug_parse_flags(debug_files, entry) != -1;63}6465/*66* Register the specified debug files and program with the67* debug subsystem, freeing the debug list when done.68* Sets the active debug instance as a side effect.69*/70bool71python_debug_register(const char *program,72struct sudo_conf_debug_file_list *debug_files)73{74int instance = python_debug_instance;75struct sudo_debug_file *debug_file, *debug_next;7677/* Setup debugging if indicated. */78if (debug_files != NULL && !TAILQ_EMPTY(debug_files)) {79if (program != NULL) {80instance = sudo_debug_register(program, python_subsystem_names,81python_subsystem_ids, debug_files, -1);82}83TAILQ_FOREACH_SAFE(debug_file, debug_files, entries, debug_next) {84TAILQ_REMOVE(debug_files, debug_file, entries);85free(debug_file->debug_file);86free(debug_file->debug_flags);87free(debug_file);88}89}9091switch (instance) {92case SUDO_DEBUG_INSTANCE_ERROR:93return false;94case SUDO_DEBUG_INSTANCE_INITIALIZER:95/* Nothing to do */96break;97default:98/* New debug instance or additional reference on existing one. */99python_debug_instance = instance;100sudo_debug_set_active_instance(python_debug_instance);101python_debug_refcnt++;102break;103}104105return true;106}107108/*109* Deregister python_debug_instance if it is registered.110*/111void112python_debug_deregister(void)113{114debug_decl(python_debug_deregister, PYTHON_DEBUG_INTERNAL);115116if (python_debug_refcnt != 0) {117sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);118if (--python_debug_refcnt == 0) {119if (sudo_debug_deregister(python_debug_instance) < 1)120python_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;121}122}123}124125126