]> granicus.if.org Git - sudo/blob - plugins/sudoers/sudoers_debug.c
d09ec12257fbd1911598bf1db121a01fe5396b1b
[sudo] / plugins / sudoers / sudoers_debug.c
1 /*
2  * Copyright (c) 2014-2015 Todd C. Miller <Todd.Miller@sudo.ws>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /*
18  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
19  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
20  */
21
22 #include <config.h>
23
24 #include <sys/types.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_STDBOOL_H
28 # include <stdbool.h>
29 #else
30 # include "compat/stdbool.h"
31 #endif
32 #ifdef HAVE_STRING_H
33 # include <string.h>
34 #endif /* HAVE_STRING_H */
35 #ifdef HAVE_STRINGS_H
36 # include <strings.h>
37 #endif /* HAVE_STRINGS_H */
38 #include <unistd.h>
39 #include <ctype.h>
40
41 #include "sudoers.h"
42
43 static int sudoers_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
44
45 static const char *const sudoers_subsystem_names[] = {
46     "alias",
47     "audit",
48     "auth",
49     "defaults",
50     "env",
51     "event",
52     "ldap",
53     "logging",
54     "main",
55     "match",
56     "netif",
57     "nss",
58     "parser",
59     "perms",
60     "plugin",
61     "rbtree",
62     "sssd",
63     "util",
64     NULL
65 };
66
67 #define NUM_SUBSYSTEMS  (nitems(sudoers_subsystem_names) - 1)
68
69 /* Subsystem IDs assigned at registration time. */
70 unsigned int sudoers_subsystem_ids[NUM_SUBSYSTEMS];
71
72 /*
73  * Parse the "filename flags,..." debug_flags entry and insert a new
74  * sudo_debug_file struct into debug_files.
75  */
76 bool
77 sudoers_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files,
78     const char *entry)
79 {
80     struct sudo_debug_file *debug_file;
81     const char *filename, *flags;
82     size_t namelen;
83
84     /* Already initialized? */
85     if (sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER)
86         return true;
87
88     /* Only process new-style debug flags: filename flags,... */
89     filename = entry;
90     if (*filename != '/' || (flags = strpbrk(filename, " \t")) == NULL)
91         return true;
92     namelen = (size_t)(flags - filename);
93     while (isblank((unsigned char)*flags))
94         flags++;
95     if (*flags != '\0') {
96         if ((debug_file = calloc(1, sizeof(*debug_file))) == NULL)
97             goto oom;
98         if ((debug_file->debug_file = strndup(filename, namelen)) == NULL)
99             goto oom;
100         if ((debug_file->debug_flags = strdup(flags)) == NULL)
101             goto oom;
102         TAILQ_INSERT_TAIL(debug_files, debug_file, entries);
103     }
104     return true;
105 oom:
106     if (debug_file != NULL) {
107         free(debug_file->debug_file);
108         free(debug_file->debug_flags);
109         free(debug_file);
110     }
111     sudo_warnx_nodebug(U_("%s: %s"), "sudoers_debug_parse_flags",
112         U_("unable to allocate memory"));
113     return false;
114 }
115
116 /*
117  * Register the specified debug files and program with the
118  * debug subsystem, freeing the debug list when done.
119  * Sets the active debug instance as a side effect.
120  */
121 bool
122 sudoers_debug_register(const char *program,
123     struct sudo_conf_debug_file_list *debug_files)
124 {
125     struct sudo_debug_file *debug_file, *debug_next;
126
127     /* Already initialized? */
128     if (sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER) {
129         sudo_debug_set_active_instance(sudoers_debug_instance);
130     }
131
132     /* Setup debugging if indicated. */
133     if (debug_files != NULL && !TAILQ_EMPTY(debug_files)) {
134         if (program != NULL) {
135             sudoers_debug_instance = sudo_debug_register(program,
136                 sudoers_subsystem_names, sudoers_subsystem_ids, debug_files);
137             if (sudoers_debug_instance == SUDO_DEBUG_INSTANCE_ERROR)
138                 return false;
139         }
140         TAILQ_FOREACH_SAFE(debug_file, debug_files, entries, debug_next) {
141             TAILQ_REMOVE(debug_files, debug_file, entries);
142             free(debug_file->debug_file);
143             free(debug_file->debug_flags);
144             free(debug_file);
145         }
146     }
147     return true;
148 }
149
150 /*
151  * Deregister sudoers_debug_instance if it is registered.
152  */
153 void
154 sudoers_debug_deregister(void)
155 {
156     debug_decl(sudoers_debug_deregister, SUDOERS_DEBUG_PLUGIN)
157     if (sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER) {
158         sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
159         sudo_debug_deregister(sudoers_debug_instance);
160         sudoers_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
161     }
162 }