]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/libucl/src/ucl_util.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[FreeBSD/releng/9.3.git] / contrib / libucl / src / ucl_util.c
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 }