Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2011 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <stdio.h>
22 : #include <stdlib.h>
23 : #include <limits.h>
24 : #include <talloc.h>
25 : #include <popt.h>
26 : #include <sys/types.h>
27 : #include <dirent.h>
28 : #include <ctype.h>
29 : #include <signal.h>
30 : #include <utime.h>
31 : #include <ldb.h>
32 :
33 : #include "config.h"
34 : #include "util/util.h"
35 : #include "tools/tools_util.h"
36 : #include "confdb/confdb.h"
37 :
38 : #define CHECK(expr, done, msg) do { \
39 : if (expr) { \
40 : ERROR(msg "\n"); \
41 : goto done; \
42 : } \
43 : } while(0)
44 :
45 : struct debuglevel_tool_ctx {
46 : struct confdb_ctx *confdb;
47 : char **sections;
48 : };
49 :
50 : static errno_t set_debug_level(struct debuglevel_tool_ctx *tool_ctx,
51 : int debug_to_set, const char *config_file);
52 : static errno_t connect_to_confdb(TALLOC_CTX *ctx, struct confdb_ctx **cdb_ctx);
53 : static errno_t get_confdb_sections(TALLOC_CTX *ctx, struct confdb_ctx *confdb,
54 : char ***output_sections);
55 : static int parse_debug_level(const char *strlevel);
56 :
57 0 : int main(int argc, const char **argv)
58 : {
59 : int ret;
60 0 : int pc_debug = SSSDBG_DEFAULT;
61 0 : int debug_to_set = SSSDBG_INVALID;
62 0 : const char *debug_as_string = NULL;
63 0 : const char *config_file = NULL;
64 0 : const char *pc_config_file = NULL;
65 0 : struct debuglevel_tool_ctx *ctx = NULL;
66 0 : struct poptOption long_options[] = {
67 : POPT_AUTOHELP
68 : {"debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug,
69 0 : 0, _("The debug level to run with"), NULL },
70 : {"config", 'c', POPT_ARG_STRING, &pc_config_file,
71 0 : 0, _("Specify a non-default config file"), NULL},
72 : POPT_TABLEEND
73 : };
74 0 : poptContext pc = NULL;
75 :
76 0 : debug_prg_name = argv[0];
77 :
78 : /* parse parameters */
79 0 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
80 0 : poptSetOtherOptionHelp(pc, "DEBUG_LEVEL_TO_SET");
81 0 : while((ret = poptGetNextOpt(pc)) != -1) {
82 : switch(ret) {
83 : default:
84 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
85 : poptBadOption(pc, 0), poptStrerror(ret));
86 0 : poptPrintUsage(pc, stderr, 0);
87 0 : ret = EXIT_FAILURE;
88 0 : goto fini;
89 : }
90 : }
91 0 : DEBUG_CLI_INIT(pc_debug);
92 :
93 : /* get debug level */
94 0 : debug_as_string = poptGetArg(pc);
95 0 : if (debug_as_string == NULL) {
96 0 : BAD_POPT_PARAMS(pc, _("Specify debug level you want to set\n"),
97 : ret, fini);
98 : }
99 :
100 : /* No more arguments expected. If something follows it is an error. */
101 0 : if (poptGetArg(pc)) {
102 0 : BAD_POPT_PARAMS(pc, _("Only one argument expected\n"),
103 : ret, fini);
104 : }
105 :
106 : /* get config file */
107 0 : if (pc_config_file) {
108 0 : config_file = talloc_strdup(ctx, pc_config_file);
109 : } else {
110 0 : config_file = talloc_strdup(ctx, CONFDB_DEFAULT_CONFIG_FILE);
111 : }
112 :
113 0 : if (config_file == NULL) {
114 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
115 0 : ret = ENOMEM;
116 0 : goto fini;
117 : }
118 :
119 0 : CHECK_ROOT(ret, debug_prg_name);
120 :
121 : /* free pc_config_file? */
122 : /* free debug_as_string? */
123 :
124 0 : debug_to_set = parse_debug_level(debug_as_string);
125 0 : CHECK(debug_to_set == SSSDBG_INVALID, fini, "Invalid debug level.");
126 :
127 : /* allocate context */
128 0 : ctx = talloc_zero(NULL, struct debuglevel_tool_ctx);
129 0 : if (ctx == NULL) {
130 0 : DEBUG(SSSDBG_CRIT_FAILURE,
131 : "Could not allocate memory for tools context\n");
132 0 : ret = ENOMEM;
133 0 : goto fini;
134 : }
135 :
136 0 : ret = connect_to_confdb(ctx, &ctx->confdb);
137 0 : CHECK(ret != EOK, fini, "Could not connect to configuration database.");
138 :
139 0 : ret = get_confdb_sections(ctx, ctx->confdb, &ctx->sections);
140 0 : CHECK(ret != EOK, fini, "Could not get all configuration sections.");
141 :
142 0 : ret = set_debug_level(ctx, debug_to_set, config_file);
143 0 : CHECK(ret != EOK, fini, "Could not set debug level.");
144 :
145 0 : ret = signal_sssd(SIGHUP);
146 0 : CHECK(ret != EOK, fini,
147 : "Could not force sssd processes to reload configuration. "
148 : "Is sssd running?");
149 :
150 : fini:
151 0 : poptFreeContext(pc);
152 0 : talloc_free(ctx);
153 0 : return ret;
154 : }
155 :
156 0 : errno_t set_debug_level(struct debuglevel_tool_ctx *tool_ctx,
157 : int debug_to_set, const char *config_file)
158 : {
159 : int ret;
160 : int err;
161 : const char *values[2];
162 0 : char **section = NULL;
163 0 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
164 :
165 0 : if (tmp_ctx == NULL) {
166 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
167 0 : return ENOMEM;
168 : }
169 :
170 : /* convert debug_to_set to string */
171 0 : values[0] = talloc_asprintf(tmp_ctx, "0x%.4x", debug_to_set);
172 0 : if (values[0] == NULL) {
173 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not allocate memory for "
174 : "debug_to_set to string conversion\n");
175 0 : ret = ENOMEM;
176 0 : goto done;
177 : }
178 0 : values[1] = NULL;
179 :
180 : /* write to confdb */
181 0 : for (section = tool_ctx->sections; *section != NULL; section++) {
182 0 : ret = confdb_add_param(tool_ctx->confdb, 1, *section,
183 : CONFDB_SERVICE_DEBUG_LEVEL, values);
184 0 : if (ret != EOK) {
185 0 : goto done;
186 : }
187 : }
188 :
189 : /*
190 : * Change atime and mtime of sssd.conf,
191 : * so the configuration can be restored on next start.
192 : */
193 0 : errno = 0;
194 0 : if (utime(config_file, NULL) == -1 ) {
195 0 : err = errno;
196 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change mtime of \"%s\": %s\n",
197 : config_file, strerror(err));
198 : }
199 :
200 0 : ret = EOK;
201 :
202 : done:
203 0 : talloc_free(tmp_ctx);
204 0 : return ret;
205 : }
206 :
207 0 : errno_t connect_to_confdb(TALLOC_CTX *ctx, struct confdb_ctx **cdb_ctx)
208 : {
209 : int ret;
210 0 : char* confdb_path = NULL;
211 :
212 0 : confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
213 0 : if (confdb_path == NULL) {
214 0 : DEBUG(SSSDBG_CRIT_FAILURE,
215 : "Could not allocate memory for confdb path\n");
216 0 : return ENOMEM;
217 : }
218 :
219 0 : ret = confdb_init(ctx, cdb_ctx, confdb_path);
220 0 : if (ret != EOK) {
221 0 : DEBUG(SSSDBG_CRIT_FAILURE,
222 : "Could not initialize connection to the confdb\n");
223 : }
224 :
225 0 : talloc_free(confdb_path);
226 0 : return ret;
227 : }
228 :
229 0 : errno_t get_confdb_sections(TALLOC_CTX *ctx, struct confdb_ctx *confdb,
230 : char ***output_sections)
231 : {
232 : int ret;
233 0 : int domain_count = 0;
234 0 : int i = 0;
235 0 : struct sss_domain_info *domain = NULL;
236 0 : struct sss_domain_info *domain_list = NULL;
237 : char **sections;
238 0 : const char *known_services[] = {
239 : CONFDB_MONITOR_CONF_ENTRY,
240 : CONFDB_NSS_CONF_ENTRY,
241 : CONFDB_PAM_CONF_ENTRY,
242 : CONFDB_PAC_CONF_ENTRY,
243 : CONFDB_SSH_CONF_ENTRY,
244 : CONFDB_SUDO_CONF_ENTRY,
245 : CONFDB_AUTOFS_CONF_ENTRY,
246 : CONFDB_IFP_CONF_ENTRY,
247 : };
248 : static const int known_services_count = sizeof(known_services)
249 : / sizeof(*known_services);
250 0 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
251 :
252 0 : if (tmp_ctx == NULL) {
253 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
254 0 : return ENOMEM;
255 : }
256 :
257 : /* get domains */
258 0 : ret = confdb_get_domains(confdb, &domain_list);
259 0 : if (ret != EOK)
260 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain list\n");
261 :
262 0 : for (domain = domain_list;
263 : domain;
264 0 : domain = get_next_domain(domain, false)) {
265 0 : domain_count++;
266 : }
267 :
268 : /* allocate output space */
269 0 : sections = talloc_array(ctx, char*,
270 : domain_count + known_services_count + 1);
271 0 : if (sections == NULL) {
272 0 : DEBUG(SSSDBG_CRIT_FAILURE,
273 : "Could not allocate memory for sections\n");
274 0 : ret = ENOMEM;
275 0 : goto fail;
276 : }
277 :
278 0 : for (i = 0; i < known_services_count; i++) {
279 0 : sections[i] = talloc_strdup(tmp_ctx, known_services[i]);
280 0 : if (sections[i] == NULL) {
281 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
282 0 : ret = ENOMEM;
283 0 : goto fail;
284 : }
285 : }
286 :
287 0 : for (domain = domain_list;
288 : domain;
289 0 : domain = get_next_domain(domain, false), i++) {
290 0 : sections[i] = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL,
291 : domain->name);
292 0 : if (sections[i] == NULL) {
293 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
294 0 : ret = ENOMEM;
295 0 : goto fail;
296 : }
297 : }
298 :
299 : /* add NULL to the end */
300 0 : sections[i] = NULL;
301 :
302 0 : *output_sections = talloc_steal(ctx, sections);
303 :
304 0 : return EOK;
305 : fail:
306 0 : talloc_free(tmp_ctx);
307 0 : return ret;
308 : }
309 :
310 0 : int parse_debug_level(const char *strlevel)
311 : {
312 : long value;
313 : char *endptr;
314 :
315 0 : errno = 0;
316 0 : value = strtol(strlevel, &endptr, 0);
317 0 : if ((errno != 0) || (endptr == strlevel) || (*endptr != '\0')) {
318 0 : return SSSDBG_INVALID;
319 : }
320 :
321 0 : return debug_convert_old_level(value);
322 : }
|