• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * dhcpcd - DHCP client daemon
3  * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4  * All rights reserved
5 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <arpa/inet.h>
29 
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <syslog.h>
35 
36 #include <dbus/dbus.h>
37 
38 #include "../config.h"
39 #include "dbus-dict.h"
40 
41 static dbus_bool_t
append_sanitized_string(DBusMessageIter * iter,const char * value)42 append_sanitized_string(DBusMessageIter *iter, const char *value)
43 {
44 	dbus_bool_t ret;
45 	int len = strlen(value);
46 	char *sanitized_value = NULL;
47 	int i;
48 
49 	for (i = 0; i < len; i++) {
50 		if (isascii(value[i]) || isprint(value[i])) {
51 			if (sanitized_value)
52 				sanitized_value[i] = value[i];
53 		} else {
54 			if (sanitized_value == NULL) {
55 				sanitized_value = malloc(len + 1);
56 				if (sanitized_value == NULL) {
57 					syslog(LOG_ERR, "DBus string parameter "
58 					       "sanitization failed due to "
59 					       "malloc failure");
60 					return FALSE;
61 				}
62 				memcpy(sanitized_value, value, i);
63 			}
64 			sanitized_value[i] = '?';
65 		}
66 	}
67 	if (sanitized_value) {
68 		syslog(LOG_ERR, "DBus string parameter sanitization"
69                        " was invoked");
70 		sanitized_value[i] = '\0';
71 		ret = dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
72 	            &sanitized_value);
73 
74 		free(sanitized_value);
75 	} else {
76 		ret = dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
77 	            &value);
78 	}
79 
80 	return ret;
81 }
82 
83 static int
append_config_value(DBusMessageIter * entry,int type,const char * data)84 append_config_value(DBusMessageIter *entry, int type,
85     const char *data)
86 {
87 	int retval;
88 	DBusMessageIter var;
89 	unsigned char byte;
90 	dbus_uint16_t u16;
91 	dbus_uint32_t u32;
92 	dbus_int16_t i16;
93 	dbus_int32_t i32;
94 	struct in_addr in;
95 
96 	retval = -1;
97 	switch (type) {
98 	case DBUS_TYPE_BOOLEAN:
99 		if (*data == '0' || *data == '\0')
100 			u32 = 0;
101 		else
102 			u32 = 1;
103 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
104 		    DBUS_TYPE_BOOLEAN_AS_STRING, &var);
105 		if (dbus_message_iter_append_basic(&var,
106 			DBUS_TYPE_BOOLEAN, &u32))
107 			retval = 0;
108 		break;
109 	case DBUS_TYPE_BYTE:
110 		byte = strtoul(data, NULL, 0);
111 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
112 		    DBUS_TYPE_BYTE_AS_STRING, &var);
113 		if (dbus_message_iter_append_basic(&var, DBUS_TYPE_BYTE,
114 			&byte))
115 			retval = 0;
116 		break;
117 	case DBUS_TYPE_STRING:
118 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
119 		    DBUS_TYPE_STRING_AS_STRING, &var);
120 		if (append_sanitized_string(&var, data))
121 			retval = 0;
122 		break;
123 	case DBUS_TYPE_INT16:
124 		i16 = strtol(data, NULL, 0);
125 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
126 		    DBUS_TYPE_INT16_AS_STRING, &var);
127 		if (dbus_message_iter_append_basic(&var,
128 			DBUS_TYPE_INT16, &i16))
129 			retval = 0;
130 		break;
131 	case DBUS_TYPE_UINT16:
132 		u16 = strtoul(data, NULL, 0);
133 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
134 		    DBUS_TYPE_UINT16_AS_STRING, &var);
135 		if (dbus_message_iter_append_basic(&var,
136 			DBUS_TYPE_UINT16, &u16))
137 			retval = 0;
138 		break;
139 	case DBUS_TYPE_INT32:
140 		i32 = strtol(data, NULL, 0);
141 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
142 		    DBUS_TYPE_INT32_AS_STRING, &var);
143 		if (dbus_message_iter_append_basic(&var,
144 			DBUS_TYPE_INT32, &i32))
145 			retval = 0;
146 		break;
147 	case DBUS_TYPE_UINT32:
148 		if (strchr(data, '.') != NULL && inet_aton(data, &in) == 1)
149 			u32 = in.s_addr;
150 		else
151 			u32 = strtoul(data, NULL, 0);
152 		dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
153 		    DBUS_TYPE_UINT32_AS_STRING, &var);
154 		if (dbus_message_iter_append_basic(&var,
155 			DBUS_TYPE_UINT32, &u32))
156 			retval = 0;
157 		break;
158 	default:
159 		retval = 1;
160 		break;
161 	}
162 	if (retval == 0)
163 		dbus_message_iter_close_container(entry, &var);
164 	else if (retval == 1)
165 		retval = 0;
166 
167 	return retval;
168 }
169 
170 static int
append_config_byte_array(DBusMessageIter * entry,const char * data)171 append_config_byte_array(DBusMessageIter *entry, const char *data)
172 {
173 	DBusMessageIter var, array;
174 	dbus_bool_t ok = TRUE;
175 	uint8_t u8, u8_2;
176 	size_t len;
177 	const char *it, *end;
178 	const char *tsa, *ts;
179 
180 	tsa = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
181 	ts = DBUS_TYPE_BYTE_AS_STRING;
182 
183 	dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, tsa, &var);
184 	dbus_message_iter_open_container(&var, DBUS_TYPE_ARRAY, ts, &array);
185 
186 	len = strlen(data);
187 	it = data;
188 	end = data + len;
189 
190 	/* "a12" is treated as "0a12" */
191 	if (len & 1) {
192 		ok = (sscanf(it++, "%1hhx", &u8) == 1) &&
193 			dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE,
194 						       &u8);
195 	}
196 
197 	while (ok && it < end) {
198 		/* sscanf("1z", "%2hhx", &u8) will store 0x01 in u8 and
199 		 * will return 1 */
200 		ok = (sscanf(it++, "%1hhx", &u8) == 1) &&
201 			(sscanf(it++, "%1hhx", &u8_2) == 1);
202 		if (!ok)
203 			break;
204 
205 		u8 = (u8 << 4) | u8_2;
206 		ok = dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE, &u8);
207 	}
208 
209 	dbus_message_iter_close_container(&var, &array);
210 	dbus_message_iter_close_container(entry, &var);
211 	return ok ? 0 : -1;
212 }
213 
214 static int
append_config_array(DBusMessageIter * entry,int type,const char * data)215 append_config_array(DBusMessageIter *entry, int type, const char *data)
216 {
217 	int retval;
218 	char *ns, *p, *tok;
219 	const char *tsa, *ts;
220 	DBusMessageIter var, array;
221 	dbus_bool_t ok;
222 	dbus_uint32_t u32;
223 	struct in_addr in;
224 
225 	if (type == DBUS_TYPE_BYTE)
226 		return append_config_byte_array(entry, data);
227 
228 	switch (type) {
229 	case DBUS_TYPE_STRING:
230 		tsa = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING;
231 		ts = DBUS_TYPE_STRING_AS_STRING;
232 		break;
233 	case DBUS_TYPE_UINT32:
234 		tsa = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_UINT32_AS_STRING;
235 		ts = DBUS_TYPE_UINT32_AS_STRING;
236 		break;
237 	default:
238 		return -1;
239 	}
240 
241 	ns = p = strdup(data);
242 	if (ns == NULL)
243 		return -1;
244 	retval = 0;
245 
246 	dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, tsa, &var);
247 	dbus_message_iter_open_container(&var, DBUS_TYPE_ARRAY, ts, &array);
248 	while ((tok = strsep(&p, " ")) != NULL) {
249 		if (*tok == '\0')
250 			continue;
251 		switch(type) {
252 		case DBUS_TYPE_STRING:
253 			ok = append_sanitized_string(&array, tok);
254 			break;
255 		case DBUS_TYPE_UINT32:
256 			if (strchr(tok, '.') != NULL &&
257 			    inet_aton(tok, &in) == 1)
258 				u32 = in.s_addr;
259 			else
260 				u32 = strtoul(tok, NULL, 0);
261 			ok = dbus_message_iter_append_basic(&array,
262 			    DBUS_TYPE_UINT32, &u32);
263 			break;
264 		default:
265 			ok = FALSE;
266 			break;
267 		}
268 		if (!ok)
269 			break;
270 	}
271 	dbus_message_iter_close_container(&var, &array);
272 	dbus_message_iter_close_container(entry, &var);
273 	free(ns);
274 	return retval;
275 }
276 
277 int
dict_append_config_item(DBusMessageIter * iter,const struct o_dbus * op,const char * data)278 dict_append_config_item(DBusMessageIter *iter, const struct o_dbus *op,
279     const char *data)
280 {
281 	int retval;
282 	DBusMessageIter entry;
283 
284 	retval = 0;
285 	if (*data == '\0')
286 		return retval;
287 	dbus_message_iter_open_container(iter,
288 	    DBUS_TYPE_DICT_ENTRY,
289 	    NULL,
290 	    &entry);
291 	append_sanitized_string(&entry, op->name);
292 	if (op->type == DBUS_TYPE_ARRAY)
293 		retval = append_config_array(&entry, op->sub_type, data);
294 	else
295 		retval = append_config_value(&entry, op->type, data);
296 	dbus_message_iter_close_container(iter, &entry);
297 	return retval;
298 }
299