1 /*
2  * Copyright (c) 2011 Collabora Ltd.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *     * Redistributions of source code must retain the above
9  *       copyright notice, this list of conditions and the
10  *       following disclaimer.
11  *     * Redistributions in binary form must reproduce the
12  *       above copyright notice, this list of conditions and
13  *       the following disclaimer in the documentation and/or
14  *       other materials provided with the distribution.
15  *     * The names of contributors to this software may not be
16  *       used to endorse or promote products derived from this
17  *       software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30  * DAMAGE.
31  *
32  *
33  * CONTRIBUTORS
34  *  Stef Walter <stef@memberwebs.com>
35  */
36 
37 #include "config.h"
38 
39 #include "compat.h"
40 #include "debug.h"
41 
42 #include <assert.h>
43 #ifdef HAVE_LOCALE_H
44 #include <locale.h>
45 #endif
46 #include <stdio.h>
47 #include <stdarg.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 
52 #define P11_DEBUG_MESSAGE_MAX 512
53 
54 struct DebugKey {
55 	const char *name;
56 	int value;
57 };
58 
59 static struct DebugKey debug_keys[] = {
60 	{ "lib", P11_DEBUG_LIB },
61 	{ "conf", P11_DEBUG_CONF },
62 	{ "uri", P11_DEBUG_URI },
63 	{ "proxy", P11_DEBUG_PROXY },
64 	{ "trust", P11_DEBUG_TRUST },
65 	{ "tool", P11_DEBUG_TOOL },
66 	{ "rpc", P11_DEBUG_RPC },
67 	{ 0, }
68 };
69 
70 static bool debug_strict = false;
71 
72 /* global variable exported in debug.h */
73 int p11_debug_current_flags = ~0;
74 
75 #ifdef HAVE_STRERROR_L
76 extern locale_t p11_message_locale;
77 #endif
78 
79 static int
parse_environ_flags(void)80 parse_environ_flags (void)
81 {
82 	const char *env;
83 	int result = 0;
84 	const char *p;
85 	const char *q;
86 	int i;
87 
88 	env = secure_getenv ("P11_KIT_STRICT");
89 	if (env && env[0] != '\0')
90 		debug_strict = true;
91 
92 	env = getenv ("P11_KIT_DEBUG");
93 	if (!env)
94 		return 0;
95 
96 	if (strcmp (env, "all") == 0) {
97 		for (i = 0; debug_keys[i].name; i++)
98 			result |= debug_keys[i].value;
99 
100 	} else if (strcmp (env, "help") == 0) {
101 		fprintf (stderr, "Supported debug values:");
102 		for (i = 0; debug_keys[i].name; i++)
103 			fprintf (stderr, " %s", debug_keys[i].name);
104 		fprintf (stderr, "\n");
105 
106 	} else {
107 		p = env;
108 		while (*p) {
109 			q = strpbrk (p, ":;, \t");
110 			if (!q)
111 				q = p + strlen (p);
112 
113 			for (i = 0; debug_keys[i].name; i++) {
114 				if (q - p == strlen (debug_keys[i].name) &&
115 				    strncmp (debug_keys[i].name, p, q - p) == 0)
116 					result |= debug_keys[i].value;
117 			}
118 
119 			p = q;
120 			if (*p)
121 				p++;
122 		}
123 	}
124 
125 	return result;
126 }
127 
128 void
p11_debug_init(void)129 p11_debug_init (void)
130 {
131 	p11_debug_current_flags = parse_environ_flags ();
132 }
133 
134 void
p11_debug_message(int flag,const char * format,...)135 p11_debug_message (int flag,
136                     const char *format, ...)
137 {
138 	va_list args;
139 
140 	if (flag & p11_debug_current_flags) {
141 		fprintf (stderr, "(p11-kit:%d) ", getpid());
142 		va_start (args, format);
143 		vfprintf (stderr, format, args);
144 		va_end (args);
145 		fprintf (stderr, "\n");
146 	}
147 }
148 
149 void
p11_debug_message_err(int flag,int errnum,const char * format,...)150 p11_debug_message_err (int flag,
151 		       int errnum,
152 		       const char *format, ...)
153 {
154 	va_list args;
155 	char strerr[P11_DEBUG_MESSAGE_MAX];
156 
157 	if (flag & p11_debug_current_flags) {
158 		fprintf (stderr, "(p11-kit:%d) ", getpid());
159 		va_start (args, format);
160 		vfprintf (stderr, format, args);
161 		va_end (args);
162 
163 		snprintf (strerr, sizeof (strerr), "Unknown error %d", errnum);
164 #ifdef HAVE_STRERROR_L
165 		if (p11_message_locale != (locale_t) 0)
166 			strncpy (strerr, strerror_l (errnum, p11_message_locale), sizeof (strerr));
167 #else
168 		strerror_r (errnum, strerr, sizeof (strerr));
169 #endif
170 		strerr[P11_DEBUG_MESSAGE_MAX - 1] = 0;
171 		fprintf (stderr, ": %s\n", strerr);
172 	}
173 }
174 
175 void
p11_debug_precond(const char * format,...)176 p11_debug_precond (const char *format,
177                     ...)
178 {
179 	va_list va;
180 
181 	va_start (va, format);
182 	vfprintf (stderr, format, va);
183 	va_end (va);
184 
185 #ifdef __COVERITY__
186 	fprintf (stderr, "ignoring P11_KIT_STRICT under coverity: %d", (int)debug_strict);
187 #else
188 	if (debug_strict)
189 #endif
190 		abort ();
191 }
192