xref: /freebsd/contrib/libucl/src/ucl_util.c (revision bfb8efd0ed67bba02c0a82f6aef82c810ec7cf4c)
1 /* Copyright (c) 2013, Vsevolod Stakhov
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *       * Redistributions of source code must retain the above copyright
7  *         notice, this list of conditions and the following disclaimer.
8  *       * Redistributions in binary form must reproduce the above copyright
9  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 #include "ucl.h"
25 #include "ucl_internal.h"
26 #include "ucl_chartable.h"
27 
28 #include <libgen.h> /* For dirname */
29 
30 #ifdef HAVE_OPENSSL
31 #include <openssl/err.h>
32 #include <openssl/sha.h>
33 #include <openssl/rsa.h>
34 #include <openssl/ssl.h>
35 #include <openssl/evp.h>
36 #endif
37 
38 #ifdef _WIN32
39 #include <windows.h>
40 
41 #define PROT_READ       1
42 #define PROT_WRITE      2
43 #define PROT_READWRITE  3
44 #define MAP_SHARED      1
45 #define MAP_PRIVATE     2
46 #define MAP_FAILED      ((void *) -1)
47 
48 static void *mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
49 {
50 	void *map = NULL;
51 	HANDLE handle = INVALID_HANDLE_VALUE;
52 
53 	switch (prot) {
54 	default:
55 	case PROT_READ:
56 		{
57 			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
58 			if (!handle) break;
59 			map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
60 			CloseHandle(handle);
61 			break;
62 		}
63 	case PROT_WRITE:
64 		{
65 			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
66 			if (!handle) break;
67 			map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
68 			CloseHandle(handle);
69 			break;
70 		}
71 	case PROT_READWRITE:
72 		{
73 			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
74 			if (!handle) break;
75 			map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
76 			CloseHandle(handle);
77 			break;
78 		}
79 	}
80 	if (map == (void *) NULL) {
81 		return (void *) MAP_FAILED;
82 	}
83 	return (void *) ((char *) map + offset);
84 }
85 
86 static int munmap(void *map,size_t length)
87 {
88 	if (!UnmapViewOfFile(map)) {
89 		return(-1);
90 	}
91 	return(0);
92 }
93 
94 static char* realpath(const char *path, char *resolved_path) {
95     char *p;
96     char tmp[MAX_PATH + 1];
97     strncpy(tmp, path, sizeof(tmp)-1);
98     p = tmp;
99     while(*p) {
100         if (*p == '/') *p = '\\';
101         p++;
102     }
103     return _fullpath(resolved_path, tmp, MAX_PATH);
104 }
105 #endif
106 
107 /**
108  * @file rcl_util.c
109  * Utilities for rcl parsing
110  */
111 
112 
113 static void
114 ucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
115 {
116 	ucl_object_t *sub, *tmp;
117 
118 	while (obj != NULL) {
119 		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
120 			UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
121 		}
122 		if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
123 			UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
124 		}
125 
126 		if (obj->type == UCL_ARRAY) {
127 			sub = obj->value.av;
128 			while (sub != NULL) {
129 				tmp = sub->next;
130 				ucl_object_free_internal (sub, false);
131 				sub = tmp;
132 			}
133 		}
134 		else if (obj->type == UCL_OBJECT) {
135 			if (obj->value.ov != NULL) {
136 				ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref);
137 			}
138 		}
139 		tmp = obj->next;
140 		UCL_FREE (sizeof (ucl_object_t), obj);
141 		obj = tmp;
142 
143 		if (!allow_rec) {
144 			break;
145 		}
146 	}
147 }
148 
149 void
150 ucl_object_free (ucl_object_t *obj)
151 {
152 	ucl_object_free_internal (obj, true);
153 }
154 
155 size_t
156 ucl_unescape_json_string (char *str, size_t len)
157 {
158 	char *t = str, *h = str;
159 	int i, uval;
160 
161 	/* t is target (tortoise), h is source (hare) */
162 
163 	while (len) {
164 		if (*h == '\\') {
165 			h ++;
166 			switch (*h) {
167 			case 'n':
168 				*t++ = '\n';
169 				break;
170 			case 'r':
171 				*t++ = '\r';
172 				break;
173 			case 'b':
174 				*t++ = '\b';
175 				break;
176 			case 't':
177 				*t++ = '\t';
178 				break;
179 			case 'f':
180 				*t++ = '\f';
181 				break;
182 			case '\\':
183 				*t++ = '\\';
184 				break;
185 			case '"':
186 				*t++ = '"';
187 				break;
188 			case 'u':
189 				/* Unicode escape */
190 				uval = 0;
191 				for (i = 0; i < 4; i++) {
192 					uval <<= 4;
193 					if (isdigit (h[i])) {
194 						uval += h[i] - '0';
195 					}
196 					else if (h[i] >= 'a' && h[i] <= 'f') {
197 						uval += h[i] - 'a' + 10;
198 					}
199 					else if (h[i] >= 'A' && h[i] <= 'F') {
200 						uval += h[i] - 'A' + 10;
201 					}
202 				}
203 				h += 3;
204 				len -= 3;
205 				/* Encode */
206 				if(uval < 0x80) {
207 					t[0] = (char)uval;
208 					t ++;
209 				}
210 				else if(uval < 0x800) {
211 					t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
212 					t[1] = 0x80 + ((uval & 0x03F));
213 					t += 2;
214 				}
215 				else if(uval < 0x10000) {
216 					t[0] = 0xE0 + ((uval & 0xF000) >> 12);
217 					t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
218 					t[2] = 0x80 + ((uval & 0x003F));
219 					t += 3;
220 				}
221 				else if(uval <= 0x10FFFF) {
222 					t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
223 					t[1] = 0x80 + ((uval & 0x03F000) >> 12);
224 					t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
225 					t[3] = 0x80 + ((uval & 0x00003F));
226 					t += 4;
227 				}
228 				else {
229 					*t++ = '?';
230 				}
231 				break;
232 			default:
233 				*t++ = *h;
234 				break;
235 			}
236 			h ++;
237 			len --;
238 		}
239 		else {
240 			*t++ = *h++;
241 		}
242 		len --;
243 	}
244 	*t = '\0';
245 
246 	return (t - str);
247 }
248 
249 UCL_EXTERN char *
250 ucl_copy_key_trash (ucl_object_t *obj)
251 {
252 	if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
253 		obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
254 		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
255 			memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
256 			obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
257 		}
258 		obj->key = obj->trash_stack[UCL_TRASH_KEY];
259 		obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
260 	}
261 
262 	return obj->trash_stack[UCL_TRASH_KEY];
263 }
264 
265 UCL_EXTERN char *
266 ucl_copy_value_trash (ucl_object_t *obj)
267 {
268 	if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
269 		if (obj->type == UCL_STRING) {
270 			/* Special case for strings */
271 			obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
272 			if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
273 				memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
274 				obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
275 				obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
276 			}
277 		}
278 		else {
279 			/* Just emit value in json notation */
280 			obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
281 			obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
282 		}
283 		obj->flags |= UCL_OBJECT_ALLOCATED_VALUE;
284 	}
285 	return obj->trash_stack[UCL_TRASH_VALUE];
286 }
287 
288 UCL_EXTERN ucl_object_t*
289 ucl_parser_get_object (struct ucl_parser *parser)
290 {
291 	if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
292 		return ucl_object_ref (parser->top_obj);
293 	}
294 
295 	return NULL;
296 }
297 
298 UCL_EXTERN void
299 ucl_parser_free (struct ucl_parser *parser)
300 {
301 	struct ucl_stack *stack, *stmp;
302 	struct ucl_macro *macro, *mtmp;
303 	struct ucl_chunk *chunk, *ctmp;
304 	struct ucl_pubkey *key, *ktmp;
305 	struct ucl_variable *var, *vtmp;
306 
307 	if (parser->top_obj != NULL) {
308 		ucl_object_unref (parser->top_obj);
309 	}
310 
311 	LL_FOREACH_SAFE (parser->stack, stack, stmp) {
312 		free (stack);
313 	}
314 	HASH_ITER (hh, parser->macroes, macro, mtmp) {
315 		free (macro->name);
316 		HASH_DEL (parser->macroes, macro);
317 		UCL_FREE (sizeof (struct ucl_macro), macro);
318 	}
319 	LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
320 		UCL_FREE (sizeof (struct ucl_chunk), chunk);
321 	}
322 	LL_FOREACH_SAFE (parser->keys, key, ktmp) {
323 		UCL_FREE (sizeof (struct ucl_pubkey), key);
324 	}
325 	LL_FOREACH_SAFE (parser->variables, var, vtmp) {
326 		free (var->value);
327 		free (var->var);
328 		UCL_FREE (sizeof (struct ucl_variable), var);
329 	}
330 
331 	if (parser->err != NULL) {
332 		utstring_free(parser->err);
333 	}
334 
335 	UCL_FREE (sizeof (struct ucl_parser), parser);
336 }
337 
338 UCL_EXTERN const char *
339 ucl_parser_get_error(struct ucl_parser *parser)
340 {
341 	if (parser->err == NULL)
342 		return NULL;
343 
344 	return utstring_body(parser->err);
345 }
346 
347 UCL_EXTERN bool
348 ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
349 {
350 #ifndef HAVE_OPENSSL
351 	ucl_create_err (&parser->err, "cannot check signatures without openssl");
352 	return false;
353 #else
354 # if (OPENSSL_VERSION_NUMBER < 0x10000000L)
355 	ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
356 	return EXIT_FAILURE;
357 # else
358 	struct ucl_pubkey *nkey;
359 	BIO *mem;
360 
361 	mem = BIO_new_mem_buf ((void *)key, len);
362 	nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
363 	nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
364 	BIO_free (mem);
365 	if (nkey->key == NULL) {
366 		UCL_FREE (sizeof (struct ucl_pubkey), nkey);
367 		ucl_create_err (&parser->err, "%s",
368 				ERR_error_string (ERR_get_error (), NULL));
369 		return false;
370 	}
371 	LL_PREPEND (parser->keys, nkey);
372 # endif
373 #endif
374 	return true;
375 }
376 
377 #ifdef CURL_FOUND
378 struct ucl_curl_cbdata {
379 	unsigned char *buf;
380 	size_t buflen;
381 };
382 
383 static size_t
384 ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud)
385 {
386 	struct ucl_curl_cbdata *cbdata = ud;
387 	size_t realsize = size * nmemb;
388 
389 	cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1);
390 	if (cbdata->buf == NULL) {
391 		return 0;
392 	}
393 
394 	memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize);
395 	cbdata->buflen += realsize;
396 	cbdata->buf[cbdata->buflen] = 0;
397 
398 	return realsize;
399 }
400 #endif
401 
402 /**
403  * Fetch a url and save results to the memory buffer
404  * @param url url to fetch
405  * @param len length of url
406  * @param buf target buffer
407  * @param buflen target length
408  * @return
409  */
410 static bool
411 ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen,
412 		UT_string **err, bool must_exist)
413 {
414 
415 #ifdef HAVE_FETCH_H
416 	struct url *fetch_url;
417 	struct url_stat us;
418 	FILE *in;
419 
420 	fetch_url = fetchParseURL (url);
421 	if (fetch_url == NULL) {
422 		ucl_create_err (err, "invalid URL %s: %s",
423 				url, strerror (errno));
424 		return false;
425 	}
426 	if ((in = fetchXGet (fetch_url, &us, "")) == NULL) {
427 		if (!must_exist) {
428 			ucl_create_err (err, "cannot fetch URL %s: %s",
429 				url, strerror (errno));
430 		}
431 		fetchFreeURL (fetch_url);
432 		return false;
433 	}
434 
435 	*buflen = us.size;
436 	*buf = malloc (*buflen);
437 	if (*buf == NULL) {
438 		ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
439 				url, strerror (errno));
440 		fclose (in);
441 		fetchFreeURL (fetch_url);
442 		return false;
443 	}
444 
445 	if (fread (*buf, *buflen, 1, in) != 1) {
446 		ucl_create_err (err, "cannot read URL %s: %s",
447 				url, strerror (errno));
448 		fclose (in);
449 		fetchFreeURL (fetch_url);
450 		return false;
451 	}
452 
453 	fetchFreeURL (fetch_url);
454 	return true;
455 #elif defined(CURL_FOUND)
456 	CURL *curl;
457 	int r;
458 	struct ucl_curl_cbdata cbdata;
459 
460 	curl = curl_easy_init ();
461 	if (curl == NULL) {
462 		ucl_create_err (err, "CURL interface is broken");
463 		return false;
464 	}
465 	if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) {
466 		ucl_create_err (err, "invalid URL %s: %s",
467 				url, curl_easy_strerror (r));
468 		curl_easy_cleanup (curl);
469 		return false;
470 	}
471 	curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback);
472 	cbdata.buf = *buf;
473 	cbdata.buflen = *buflen;
474 	curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata);
475 
476 	if ((r = curl_easy_perform (curl)) != CURLE_OK) {
477 		if (!must_exist) {
478 			ucl_create_err (err, "error fetching URL %s: %s",
479 				url, curl_easy_strerror (r));
480 		}
481 		curl_easy_cleanup (curl);
482 		if (cbdata.buf) {
483 			free (cbdata.buf);
484 		}
485 		return false;
486 	}
487 	*buf = cbdata.buf;
488 	*buflen = cbdata.buflen;
489 
490 	return true;
491 #else
492 	ucl_create_err (err, "URL support is disabled");
493 	return false;
494 #endif
495 }
496 
497 /**
498  * Fetch a file and save results to the memory buffer
499  * @param filename filename to fetch
500  * @param len length of filename
501  * @param buf target buffer
502  * @param buflen target length
503  * @return
504  */
505 static bool
506 ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen,
507 		UT_string **err, bool must_exist)
508 {
509 	int fd;
510 	struct stat st;
511 
512 	if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
513 		if (must_exist) {
514 			ucl_create_err (err, "cannot stat file %s: %s",
515 					filename, strerror (errno));
516 		}
517 		return false;
518 	}
519 	if (st.st_size == 0) {
520 		/* Do not map empty files */
521 		*buf = "";
522 		*buflen = 0;
523 	}
524 	else {
525 		if ((fd = open (filename, O_RDONLY)) == -1) {
526 			ucl_create_err (err, "cannot open file %s: %s",
527 					filename, strerror (errno));
528 			return false;
529 		}
530 		if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
531 			close (fd);
532 			ucl_create_err (err, "cannot mmap file %s: %s",
533 					filename, strerror (errno));
534 			return false;
535 		}
536 		*buflen = st.st_size;
537 		close (fd);
538 	}
539 
540 	return true;
541 }
542 
543 
544 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
545 static inline bool
546 ucl_sig_check (const unsigned char *data, size_t datalen,
547 		const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
548 {
549 	struct ucl_pubkey *key;
550 	char dig[EVP_MAX_MD_SIZE];
551 	unsigned int diglen;
552 	EVP_PKEY_CTX *key_ctx;
553 	EVP_MD_CTX *sign_ctx = NULL;
554 
555 	sign_ctx = EVP_MD_CTX_create ();
556 
557 	LL_FOREACH (parser->keys, key) {
558 		key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
559 		if (key_ctx != NULL) {
560 			if (EVP_PKEY_verify_init (key_ctx) <= 0) {
561 				EVP_PKEY_CTX_free (key_ctx);
562 				continue;
563 			}
564 			if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
565 				EVP_PKEY_CTX_free (key_ctx);
566 				continue;
567 			}
568 			if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
569 				EVP_PKEY_CTX_free (key_ctx);
570 				continue;
571 			}
572 			EVP_DigestInit (sign_ctx, EVP_sha256 ());
573 			EVP_DigestUpdate (sign_ctx, data, datalen);
574 			EVP_DigestFinal (sign_ctx, dig, &diglen);
575 
576 			if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
577 				EVP_MD_CTX_destroy (sign_ctx);
578 				EVP_PKEY_CTX_free (key_ctx);
579 				return true;
580 			}
581 
582 			EVP_PKEY_CTX_free (key_ctx);
583 		}
584 	}
585 
586 	EVP_MD_CTX_destroy (sign_ctx);
587 
588 	return false;
589 }
590 #endif
591 
592 /**
593  * Include an url to configuration
594  * @param data
595  * @param len
596  * @param parser
597  * @param err
598  * @return
599  */
600 static bool
601 ucl_include_url (const unsigned char *data, size_t len,
602 		struct ucl_parser *parser, bool check_signature, bool must_exist)
603 {
604 
605 	bool res;
606 	unsigned char *buf = NULL;
607 	size_t buflen = 0;
608 	struct ucl_chunk *chunk;
609 	char urlbuf[PATH_MAX];
610 	int prev_state;
611 
612 	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
613 
614 	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, must_exist)) {
615 		return (!must_exist || false);
616 	}
617 
618 	if (check_signature) {
619 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
620 		unsigned char *sigbuf = NULL;
621 		size_t siglen = 0;
622 		/* We need to check signature first */
623 		snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
624 		if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
625 			return false;
626 		}
627 		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
628 			ucl_create_err (&parser->err, "cannot verify url %s: %s",
629 							urlbuf,
630 							ERR_error_string (ERR_get_error (), NULL));
631 			if (siglen > 0) {
632 				munmap (sigbuf, siglen);
633 			}
634 			return false;
635 		}
636 		if (siglen > 0) {
637 			munmap (sigbuf, siglen);
638 		}
639 #endif
640 	}
641 
642 	prev_state = parser->state;
643 	parser->state = UCL_STATE_INIT;
644 
645 	res = ucl_parser_add_chunk (parser, buf, buflen);
646 	if (res == true) {
647 		/* Remove chunk from the stack */
648 		chunk = parser->chunks;
649 		if (chunk != NULL) {
650 			parser->chunks = chunk->next;
651 			UCL_FREE (sizeof (struct ucl_chunk), chunk);
652 		}
653 	}
654 
655 	parser->state = prev_state;
656 	free (buf);
657 
658 	return res;
659 }
660 
661 /**
662  * Include a file to configuration
663  * @param data
664  * @param len
665  * @param parser
666  * @param err
667  * @return
668  */
669 static bool
670 ucl_include_file (const unsigned char *data, size_t len,
671 		struct ucl_parser *parser, bool check_signature, bool must_exist)
672 {
673 	bool res;
674 	struct ucl_chunk *chunk;
675 	unsigned char *buf = NULL;
676 	size_t buflen;
677 	char filebuf[PATH_MAX], realbuf[PATH_MAX];
678 	int prev_state;
679 
680 	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
681 	if (realpath (filebuf, realbuf) == NULL) {
682 		if (!must_exist) {
683 			return true;
684 		}
685 		ucl_create_err (&parser->err, "cannot open file %s: %s",
686 									filebuf,
687 									strerror (errno));
688 		return false;
689 	}
690 
691 	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) {
692 		return (!must_exist || false);
693 	}
694 
695 	if (check_signature) {
696 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
697 		unsigned char *sigbuf = NULL;
698 		size_t siglen = 0;
699 		/* We need to check signature first */
700 		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
701 		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
702 			return false;
703 		}
704 		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
705 			ucl_create_err (&parser->err, "cannot verify file %s: %s",
706 							filebuf,
707 							ERR_error_string (ERR_get_error (), NULL));
708 			if (siglen > 0) {
709 				munmap (sigbuf, siglen);
710 			}
711 			return false;
712 		}
713 		if (siglen > 0) {
714 			munmap (sigbuf, siglen);
715 		}
716 #endif
717 	}
718 
719 	ucl_parser_set_filevars (parser, realbuf, false);
720 
721 	prev_state = parser->state;
722 	parser->state = UCL_STATE_INIT;
723 
724 	res = ucl_parser_add_chunk (parser, buf, buflen);
725 	if (res == true) {
726 		/* Remove chunk from the stack */
727 		chunk = parser->chunks;
728 		if (chunk != NULL) {
729 			parser->chunks = chunk->next;
730 			UCL_FREE (sizeof (struct ucl_chunk), chunk);
731 		}
732 	}
733 
734 	parser->state = prev_state;
735 
736 	if (buflen > 0) {
737 		munmap (buf, buflen);
738 	}
739 
740 	return res;
741 }
742 
743 /**
744  * Handle include macro
745  * @param data include data
746  * @param len length of data
747  * @param ud user data
748  * @param err error ptr
749  * @return
750  */
751 UCL_EXTERN bool
752 ucl_include_handler (const unsigned char *data, size_t len, void* ud)
753 {
754 	struct ucl_parser *parser = ud;
755 
756 	if (*data == '/' || *data == '.') {
757 		/* Try to load a file */
758 		return ucl_include_file (data, len, parser, false, true);
759 	}
760 
761 	return ucl_include_url (data, len, parser, false, true);
762 }
763 
764 /**
765  * Handle includes macro
766  * @param data include data
767  * @param len length of data
768  * @param ud user data
769  * @param err error ptr
770  * @return
771  */
772 UCL_EXTERN bool
773 ucl_includes_handler (const unsigned char *data, size_t len, void* ud)
774 {
775 	struct ucl_parser *parser = ud;
776 
777 	if (*data == '/' || *data == '.') {
778 		/* Try to load a file */
779 		return ucl_include_file (data, len, parser, true, true);
780 	}
781 
782 	return ucl_include_url (data, len, parser, true, true);
783 }
784 
785 
786 UCL_EXTERN bool
787 ucl_try_include_handler (const unsigned char *data, size_t len, void* ud)
788 {
789 	struct ucl_parser *parser = ud;
790 
791 	if (*data == '/' || *data == '.') {
792 		/* Try to load a file */
793 		return ucl_include_file (data, len, parser, false, false);
794 	}
795 
796 	return ucl_include_url (data, len, parser, false, false);
797 }
798 
799 UCL_EXTERN bool
800 ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
801 {
802 	char realbuf[PATH_MAX], *curdir;
803 
804 	if (filename != NULL) {
805 		if (need_expand) {
806 			if (realpath (filename, realbuf) == NULL) {
807 				return false;
808 			}
809 		}
810 		else {
811 			ucl_strlcpy (realbuf, filename, sizeof (realbuf));
812 		}
813 
814 		/* Define variables */
815 		ucl_parser_register_variable (parser, "FILENAME", realbuf);
816 		curdir = dirname (realbuf);
817 		ucl_parser_register_variable (parser, "CURDIR", curdir);
818 	}
819 	else {
820 		/* Set everything from the current dir */
821 		curdir = getcwd (realbuf, sizeof (realbuf));
822 		ucl_parser_register_variable (parser, "FILENAME", "undef");
823 		ucl_parser_register_variable (parser, "CURDIR", curdir);
824 	}
825 
826 	return true;
827 }
828 
829 UCL_EXTERN bool
830 ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
831 {
832 	unsigned char *buf;
833 	size_t len;
834 	bool ret;
835 	char realbuf[PATH_MAX];
836 
837 	if (realpath (filename, realbuf) == NULL) {
838 		ucl_create_err (&parser->err, "cannot open file %s: %s",
839 				filename,
840 				strerror (errno));
841 		return false;
842 	}
843 
844 	if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
845 		return false;
846 	}
847 
848 	ucl_parser_set_filevars (parser, realbuf, false);
849 	ret = ucl_parser_add_chunk (parser, buf, len);
850 
851 	if (len > 0) {
852 		munmap (buf, len);
853 	}
854 
855 	return ret;
856 }
857 
858 size_t
859 ucl_strlcpy (char *dst, const char *src, size_t siz)
860 {
861 	char *d = dst;
862 	const char *s = src;
863 	size_t n = siz;
864 
865 	/* Copy as many bytes as will fit */
866 	if (n != 0) {
867 		while (--n != 0) {
868 			if ((*d++ = *s++) == '\0') {
869 				break;
870 			}
871 		}
872 	}
873 
874 	if (n == 0 && siz != 0) {
875 		*d = '\0';
876 	}
877 
878 	return (s - src - 1);    /* count does not include NUL */
879 }
880 
881 size_t
882 ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
883 {
884 	memcpy (dst, src, siz - 1);
885 	dst[siz - 1] = '\0';
886 
887 	return siz - 1;
888 }
889 
890 size_t
891 ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
892 {
893 	char *d = dst;
894 	const char *s = src;
895 	size_t n = siz;
896 
897 	/* Copy as many bytes as will fit */
898 	if (n != 0) {
899 		while (--n != 0) {
900 			if ((*d++ = tolower (*s++)) == '\0') {
901 				break;
902 			}
903 		}
904 	}
905 
906 	if (n == 0 && siz != 0) {
907 		*d = '\0';
908 	}
909 
910 	return (s - src);    /* count does not include NUL */
911 }
912 
913 ucl_object_t *
914 ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
915 {
916 	ucl_object_t *obj;
917 	const char *start, *end, *p, *pos;
918 	char *dst, *d;
919 	size_t escaped_len;
920 
921 	if (str == NULL) {
922 		return NULL;
923 	}
924 
925 	obj = ucl_object_new ();
926 	if (obj) {
927 		if (len == 0) {
928 			len = strlen (str);
929 		}
930 		if (flags & UCL_STRING_TRIM) {
931 			/* Skip leading spaces */
932 			for (start = str; (size_t)(start - str) < len; start ++) {
933 				if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
934 					break;
935 				}
936 			}
937 			/* Skip trailing spaces */
938 			for (end = str + len - 1; end > start; end --) {
939 				if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
940 					break;
941 				}
942 			}
943 			end ++;
944 		}
945 		else {
946 			start = str;
947 			end = str + len;
948 		}
949 
950 		obj->type = UCL_STRING;
951 		if (flags & UCL_STRING_ESCAPE) {
952 			for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
953 				if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
954 					escaped_len ++;
955 				}
956 			}
957 			dst = malloc (escaped_len + 1);
958 			if (dst != NULL) {
959 				for (p = start, d = dst; p < end; p ++, d ++) {
960 					if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
961 						switch (*p) {
962 						case '\n':
963 							*d++ = '\\';
964 							*d = 'n';
965 							break;
966 						case '\r':
967 							*d++ = '\\';
968 							*d = 'r';
969 							break;
970 						case '\b':
971 							*d++ = '\\';
972 							*d = 'b';
973 							break;
974 						case '\t':
975 							*d++ = '\\';
976 							*d = 't';
977 							break;
978 						case '\f':
979 							*d++ = '\\';
980 							*d = 'f';
981 							break;
982 						case '\\':
983 							*d++ = '\\';
984 							*d = '\\';
985 							break;
986 						case '"':
987 							*d++ = '\\';
988 							*d = '"';
989 							break;
990 						}
991 					}
992 					else {
993 						*d = *p;
994 					}
995 				}
996 				*d = '\0';
997 				obj->value.sv = dst;
998 				obj->trash_stack[UCL_TRASH_VALUE] = dst;
999 				obj->len = escaped_len;
1000 			}
1001 		}
1002 		else {
1003 			dst = malloc (end - start + 1);
1004 			if (dst != NULL) {
1005 				ucl_strlcpy_unsafe (dst, start, end - start + 1);
1006 				obj->value.sv = dst;
1007 				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1008 				obj->len = end - start;
1009 			}
1010 		}
1011 		if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1012 			/* Parse what we have */
1013 			if (flags & UCL_STRING_PARSE_BOOLEAN) {
1014 				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1015 					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1016 							flags & UCL_STRING_PARSE_DOUBLE,
1017 							flags & UCL_STRING_PARSE_BYTES);
1018 				}
1019 			}
1020 			else {
1021 				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1022 						flags & UCL_STRING_PARSE_DOUBLE,
1023 						flags & UCL_STRING_PARSE_BYTES);
1024 			}
1025 		}
1026 	}
1027 
1028 	return obj;
1029 }
1030 
1031 static ucl_object_t *
1032 ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
1033 		const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
1034 {
1035 	ucl_object_t *found, *cur;
1036 	ucl_object_iter_t it = NULL;
1037 	const char *p;
1038 
1039 	if (elt == NULL || key == NULL) {
1040 		return NULL;
1041 	}
1042 
1043 	if (top == NULL) {
1044 		top = ucl_object_new ();
1045 		top->type = UCL_OBJECT;
1046 	}
1047 
1048 	if (top->type != UCL_OBJECT) {
1049 		/* It is possible to convert NULL type to an object */
1050 		if (top->type == UCL_NULL) {
1051 			top->type = UCL_OBJECT;
1052 		}
1053 		else {
1054 			/* Refuse converting of other object types */
1055 			return top;
1056 		}
1057 	}
1058 
1059 	if (top->value.ov == NULL) {
1060 		top->value.ov = ucl_hash_create ();
1061 	}
1062 
1063 	if (keylen == 0) {
1064 		keylen = strlen (key);
1065 	}
1066 
1067 	for (p = key; p < key + keylen; p ++) {
1068 		if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
1069 			elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
1070 			break;
1071 		}
1072 	}
1073 
1074 	elt->key = key;
1075 	elt->keylen = keylen;
1076 
1077 	if (copy_key) {
1078 		ucl_copy_key_trash (elt);
1079 	}
1080 
1081 	found = ucl_hash_search_obj (top->value.ov, elt);
1082 
1083 	if (!found) {
1084 		top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1085 		DL_APPEND (found, elt);
1086 	}
1087 	else {
1088 		if (replace) {
1089 			ucl_hash_delete (top->value.ov, found);
1090 			ucl_object_unref (found);
1091 			top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1092 			found = NULL;
1093 			DL_APPEND (found, elt);
1094 		}
1095 		else if (merge) {
1096 			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
1097 				/* Insert old elt to new one */
1098 				elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false);
1099 				ucl_hash_delete (top->value.ov, found);
1100 				top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1101 			}
1102 			else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
1103 				/* Insert new to old */
1104 				found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false);
1105 			}
1106 			else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
1107 				/* Mix two hashes */
1108 				while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
1109 					ucl_object_ref (cur);
1110 					found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false);
1111 				}
1112 				ucl_object_unref (elt);
1113 			}
1114 			else {
1115 				/* Just make a list of scalars */
1116 				DL_APPEND (found, elt);
1117 			}
1118 		}
1119 		else {
1120 			DL_APPEND (found, elt);
1121 		}
1122 	}
1123 
1124 	return top;
1125 }
1126 
1127 bool
1128 ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
1129 {
1130 	ucl_object_t *found;
1131 
1132 	found = ucl_object_find_keyl(top, key, keylen);
1133 
1134 	if (found == NULL)
1135 		return false;
1136 
1137 	ucl_hash_delete(top->value.ov, found);
1138 	ucl_object_unref (found);
1139 	top->len --;
1140 
1141 	return true;
1142 }
1143 
1144 bool
1145 ucl_object_delete_key(ucl_object_t *top, const char *key)
1146 {
1147 	return ucl_object_delete_keyl(top, key, 0);
1148 }
1149 
1150 ucl_object_t *
1151 ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1152 		const char *key, size_t keylen, bool copy_key)
1153 {
1154 	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1155 }
1156 
1157 ucl_object_t *
1158 ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
1159 		const char *key, size_t keylen, bool copy_key)
1160 {
1161 	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
1162 }
1163 
1164 ucl_object_t *
1165 ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
1166 		const char *key, size_t keylen, bool copy_key)
1167 {
1168 	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
1169 }
1170 
1171 ucl_object_t *
1172 ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
1173 {
1174 	ucl_object_t *ret, srch;
1175 
1176 	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1177 		return NULL;
1178 	}
1179 
1180 	srch.key = key;
1181 	srch.keylen = klen;
1182 	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1183 
1184 	return ret;
1185 }
1186 
1187 ucl_object_t *
1188 ucl_object_find_key (ucl_object_t *obj, const char *key)
1189 {
1190 	size_t klen;
1191 	ucl_object_t *ret, srch;
1192 
1193 	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1194 		return NULL;
1195 	}
1196 
1197 	klen = strlen (key);
1198 	srch.key = key;
1199 	srch.keylen = klen;
1200 	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1201 
1202 	return ret;
1203 }
1204 
1205 ucl_object_t*
1206 ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1207 {
1208 	ucl_object_t *elt;
1209 
1210 	if (expand_values) {
1211 		switch (obj->type) {
1212 		case UCL_OBJECT:
1213 			return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1214 			break;
1215 		case UCL_ARRAY:
1216 			elt = *iter;
1217 			if (elt == NULL) {
1218 				elt = obj->value.av;
1219 				if (elt == NULL) {
1220 					return NULL;
1221 				}
1222 			}
1223 			else if (elt == obj->value.av) {
1224 				return NULL;
1225 			}
1226 			*iter = elt->next ? elt->next : obj->value.av;
1227 			return elt;
1228 		default:
1229 			/* Go to linear iteration */
1230 			break;
1231 		}
1232 	}
1233 	/* Treat everything as a linear list */
1234 	elt = *iter;
1235 	if (elt == NULL) {
1236 		elt = obj;
1237 		if (elt == NULL) {
1238 			return NULL;
1239 		}
1240 	}
1241 	else if (elt == obj) {
1242 		return NULL;
1243 	}
1244 	*iter = elt->next ? elt->next : obj;
1245 	return elt;
1246 
1247 	/* Not reached */
1248 	return NULL;
1249 }
1250