Home | History | Annotate | Download | only in dbus
      1 /*
      2  * dhcpcd - DHCP client daemon
      3  * Copyright (c) 2006-2015 Roy Marples <roy (at) 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
     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
     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
    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
    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
    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