OpenVPN
buffer.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "common.h"
33 #include "buffer.h"
34 #include "error.h"
35 #include "mtu.h"
36 #include "misc.h"
37 
38 #include "memdbg.h"
39 
40 #include <wchar.h>
41 
42 size_t
43 array_mult_safe(const size_t m1, const size_t m2, const size_t extra)
44 {
45  const size_t limit = 0xFFFFFFFF;
46  unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra;
47  if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit))
48  {
49  msg(M_FATAL, "attempted allocation of excessively large array");
50  }
51  return (size_t) res;
52 }
53 
54 void
55 buf_size_error(const size_t size)
56 {
57  msg(M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size);
58 }
59 
60 struct buffer
61 #ifdef DMALLOC
62 alloc_buf_debug(size_t size, const char *file, int line)
63 #else
64 alloc_buf(size_t size)
65 #endif
66 {
67  struct buffer buf;
68 
69  if (!buf_size_valid(size))
70  {
71  buf_size_error(size);
72  }
73  buf.capacity = (int)size;
74  buf.offset = 0;
75  buf.len = 0;
76 #ifdef DMALLOC
77  buf.data = openvpn_dmalloc(file, line, size);
78 #else
79  buf.data = calloc(1, size);
80 #endif
82 
83  return buf;
84 }
85 
86 struct buffer
87 #ifdef DMALLOC
88 alloc_buf_gc_debug(size_t size, struct gc_arena *gc, const char *file, int line)
89 #else
90 alloc_buf_gc(size_t size, struct gc_arena *gc)
91 #endif
92 {
93  struct buffer buf;
94  if (!buf_size_valid(size))
95  {
96  buf_size_error(size);
97  }
98  buf.capacity = (int)size;
99  buf.offset = 0;
100  buf.len = 0;
101 #ifdef DMALLOC
102  buf.data = (uint8_t *) gc_malloc_debug(size, false, gc, file, line);
103 #else
104  buf.data = (uint8_t *) gc_malloc(size, false, gc);
105 #endif
106  if (size)
107  {
108  *buf.data = 0;
109  }
110  return buf;
111 }
112 
113 struct buffer
114 #ifdef DMALLOC
115 clone_buf_debug(const struct buffer *buf, const char *file, int line)
116 #else
117 clone_buf(const struct buffer *buf)
118 #endif
119 {
120  struct buffer ret;
121  ret.capacity = buf->capacity;
122  ret.offset = buf->offset;
123  ret.len = buf->len;
124 #ifdef DMALLOC
125  ret.data = (uint8_t *) openvpn_dmalloc(file, line, buf->capacity);
126 #else
127  ret.data = (uint8_t *) malloc(buf->capacity);
128 #endif
130  memcpy(BPTR(&ret), BPTR(buf), BLEN(buf));
131  return ret;
132 }
133 
134 #ifdef BUF_INIT_TRACKING
135 
136 bool
137 buf_init_debug(struct buffer *buf, int offset, const char *file, int line)
138 {
139  buf->debug_file = file;
140  buf->debug_line = line;
141  return buf_init_dowork(buf, offset);
142 }
143 
144 static inline int
145 buf_debug_line(const struct buffer *buf)
146 {
147  return buf->debug_line;
148 }
149 
150 static const char *
151 buf_debug_file(const struct buffer *buf)
152 {
153  return buf->debug_file;
154 }
155 
156 #else /* ifdef BUF_INIT_TRACKING */
157 
158 #define buf_debug_line(buf) 0
159 #define buf_debug_file(buf) "[UNDEF]"
160 
161 #endif /* ifdef BUF_INIT_TRACKING */
162 
163 void
164 buf_clear(struct buffer *buf)
165 {
166  if (buf->capacity > 0)
167  {
168  secure_memzero(buf->data, buf->capacity);
169  }
170  buf->len = 0;
171  buf->offset = 0;
172 }
173 
174 bool
175 buf_assign(struct buffer *dest, const struct buffer *src)
176 {
177  if (!buf_init(dest, src->offset))
178  {
179  return false;
180  }
181  return buf_write(dest, BPTR(src), BLEN(src));
182 }
183 
184 void
185 free_buf(struct buffer *buf)
186 {
187  free(buf->data);
188  CLEAR(*buf);
189 }
190 
191 static void
192 free_buf_gc(struct buffer *buf, struct gc_arena *gc)
193 {
194  if (gc)
195  {
196  struct gc_entry **e = &gc->list;
197 
198  while (*e)
199  {
200  /* check if this object is the one we want to delete */
201  if ((uint8_t *)(*e + 1) == buf->data)
202  {
203  struct gc_entry *to_delete = *e;
204 
205  /* remove element from linked list and free it */
206  *e = (*e)->next;
207  free(to_delete);
208 
209  break;
210  }
211 
212  e = &(*e)->next;
213  }
214  }
215 
216  CLEAR(*buf);
217 }
218 
219 /*
220  * Return a buffer for write that is a subset of another buffer
221  */
222 struct buffer
223 buf_sub(struct buffer *buf, int size, bool prepend)
224 {
225  struct buffer ret;
226  uint8_t *data;
227 
228  CLEAR(ret);
229  data = prepend ? buf_prepend(buf, size) : buf_write_alloc(buf, size);
230  if (data)
231  {
232  ret.capacity = size;
233  ret.data = data;
234  }
235  return ret;
236 }
237 
238 /*
239  * printf append to a buffer with overflow check
240  */
241 bool
242 buf_printf(struct buffer *buf, const char *format, ...)
243 {
244  int ret = false;
245  if (buf_defined(buf))
246  {
247  va_list arglist;
248  uint8_t *ptr = BEND(buf);
249  int cap = buf_forward_capacity(buf);
250 
251  if (cap > 0)
252  {
253  int stat;
254  va_start(arglist, format);
255  stat = vsnprintf((char *)ptr, cap, format, arglist);
256  va_end(arglist);
257  *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
258  buf->len += (int) strlen((char *)ptr);
259  if (stat >= 0 && stat < cap)
260  {
261  ret = true;
262  }
263  }
264  }
265  return ret;
266 }
267 
268 bool
269 buf_puts(struct buffer *buf, const char *str)
270 {
271  int ret = false;
272  uint8_t *ptr = BEND(buf);
273  int cap = buf_forward_capacity(buf);
274  if (cap > 0)
275  {
276  strncpynt((char *)ptr,str, cap);
277  *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
278  buf->len += (int) strlen((char *)ptr);
279  ret = true;
280  }
281  return ret;
282 }
283 
284 
285 /*
286  * This is necessary due to certain buggy implementations of snprintf,
287  * that don't guarantee null termination for size > 0.
288  *
289  * Return false on overflow.
290  *
291  * This functionality is duplicated in src/openvpnserv/common.c
292  * Any modifications here should be done to the other place as well.
293  */
294 
295 bool
296 openvpn_snprintf(char *str, size_t size, const char *format, ...)
297 {
298  va_list arglist;
299  int len = -1;
300  if (size > 0)
301  {
302  va_start(arglist, format);
303  len = vsnprintf(str, size, format, arglist);
304  va_end(arglist);
305  str[size - 1] = 0;
306  }
307  return (len >= 0 && len < size);
308 }
309 
310 /*
311  * openvpn_swprintf() is currently only used by Windows code paths
312  * and when enabled for all platforms it will currently break older
313  * OpenBSD versions lacking vswprintf(3) support in their libc.
314  */
315 
316 #ifdef _WIN32
317 bool
318 openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...)
319 {
320  va_list arglist;
321  int len = -1;
322  if (size > 0)
323  {
324  va_start(arglist, format);
325  len = vswprintf(str, size, format, arglist);
326  va_end(arglist);
327  str[size - 1] = L'\0';
328  }
329  return (len >= 0 && len < size);
330 }
331 #endif
332 
333 /*
334  * write a string to the end of a buffer that was
335  * truncated by buf_printf
336  */
337 void
338 buf_catrunc(struct buffer *buf, const char *str)
339 {
340  if (buf_forward_capacity(buf) <= 1)
341  {
342  int len = (int) strlen(str) + 1;
343  if (len < buf_forward_capacity_total(buf))
344  {
345  strncpynt((char *)(buf->data + buf->capacity - len), str, len);
346  }
347  }
348 }
349 
350 /*
351  * convert a multi-line output to one line
352  */
353 void
354 convert_to_one_line(struct buffer *buf)
355 {
356  uint8_t *cp = BPTR(buf);
357  int len = BLEN(buf);
358  while (len--)
359  {
360  if (*cp == '\n')
361  {
362  *cp = '|';
363  }
364  ++cp;
365  }
366 }
367 
368 bool
369 buffer_write_file(const char *filename, const struct buffer *buf)
370 {
371  bool ret = false;
372  int fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY,
373  S_IRUSR | S_IWUSR);
374  if (fd == -1)
375  {
376  msg(M_ERRNO, "Cannot open file '%s' for write", filename);
377  return false;
378  }
379 
380  const int size = write(fd, BPTR(buf), BLEN(buf));
381  if (size != BLEN(buf))
382  {
383  msg(M_ERRNO, "Write error on file '%s'", filename);
384  goto cleanup;
385  }
386 
387  ret = true;
388 cleanup:
389  if (close(fd) < 0)
390  {
391  msg(M_ERRNO, "Close error on file %s", filename);
392  ret = false;
393  }
394  return ret;
395 }
396 
397 /*
398  * Garbage collection
399  */
400 
401 void *
402 #ifdef DMALLOC
403 gc_malloc_debug(size_t size, bool clear, struct gc_arena *a, const char *file, int line)
404 #else
405 gc_malloc(size_t size, bool clear, struct gc_arena *a)
406 #endif
407 {
408  void *ret;
409  if (a)
410  {
411  struct gc_entry *e;
412 #ifdef DMALLOC
413  e = (struct gc_entry *) openvpn_dmalloc(file, line, size + sizeof(struct gc_entry));
414 #else
415  e = (struct gc_entry *) malloc(size + sizeof(struct gc_entry));
416 #endif
418  ret = (char *) e + sizeof(struct gc_entry);
419  e->next = a->list;
420  a->list = e;
421  }
422  else
423  {
424 #ifdef DMALLOC
425  ret = openvpn_dmalloc(file, line, size);
426 #else
427  ret = malloc(size);
428 #endif
429  check_malloc_return(ret);
430  }
431 #ifndef ZERO_BUFFER_ON_ALLOC
432  if (clear)
433 #endif
434  memset(ret, 0, size);
435  return ret;
436 }
437 
438 void
439 x_gc_free(struct gc_arena *a)
440 {
441  struct gc_entry *e;
442  e = a->list;
443  a->list = NULL;
444 
445  while (e != NULL)
446  {
447  struct gc_entry *next = e->next;
448  free(e);
449  e = next;
450  }
451 }
452 
453 /*
454  * Functions to handle special objects in gc_entries
455  */
456 
457 void
458 x_gc_freespecial(struct gc_arena *a)
459 {
460  struct gc_entry_special *e;
461  e = a->list_special;
462  a->list_special = NULL;
463 
464  while (e != NULL)
465  {
466  struct gc_entry_special *next = e->next;
467  e->free_fnc(e->addr);
468  free(e);
469  e = next;
470  }
471 }
472 
473 void
474 gc_addspecial(void *addr, void (*free_function)(void *), struct gc_arena *a)
475 {
476  ASSERT(a);
477  struct gc_entry_special *e;
478 #ifdef DMALLOC
479  e = (struct gc_entry_special *) openvpn_dmalloc(file, line, sizeof(struct gc_entry_special));
480 #else
481  e = (struct gc_entry_special *) malloc(sizeof(struct gc_entry_special));
482 #endif
484  e->free_fnc = free_function;
485  e->addr = addr;
486 
487  e->next = a->list_special;
488  a->list_special = e;
489 }
490 
491 
492 /*
493  * Transfer src arena to dest, resetting src to an empty arena.
494  */
495 void
496 gc_transfer(struct gc_arena *dest, struct gc_arena *src)
497 {
498  if (dest && src)
499  {
500  struct gc_entry *e = src->list;
501  if (e)
502  {
503  while (e->next != NULL)
504  {
505  e = e->next;
506  }
507  e->next = dest->list;
508  dest->list = src->list;
509  src->list = NULL;
510  }
511  }
512 }
513 
514 /*
515  * Hex dump -- Output a binary buffer to a hex string and return it.
516  */
517 
518 char *
519 format_hex_ex(const uint8_t *data, int size, int maxoutput,
520  unsigned int space_break_flags, const char *separator,
521  struct gc_arena *gc)
522 {
523  const size_t bytes_per_hexblock = space_break_flags & FHE_SPACE_BREAK_MASK;
524  const size_t separator_len = separator ? strlen(separator) : 0;
525  static_assert(INT_MAX <= SIZE_MAX, "Code assumes INT_MAX <= SIZE_MAX");
526  const size_t out_len = maxoutput > 0 ? maxoutput :
527  ((size * 2) + ((size / bytes_per_hexblock) * separator_len) + 2);
528 
529  struct buffer out = alloc_buf_gc(out_len, gc);
530  for (int i = 0; i < size; ++i)
531  {
532  if (separator && i && !(i % bytes_per_hexblock))
533  {
534  buf_printf(&out, "%s", separator);
535  }
536  if (space_break_flags & FHE_CAPS)
537  {
538  buf_printf(&out, "%02X", data[i]);
539  }
540  else
541  {
542  buf_printf(&out, "%02x", data[i]);
543  }
544  }
545  buf_catrunc(&out, "[more...]");
546  return (char *)out.data;
547 }
548 
549 /*
550  * remove specific trailing character
551  */
552 
553 void
554 buf_rmtail(struct buffer *buf, uint8_t remove)
555 {
556  uint8_t *cp = BLAST(buf);
557  if (cp && *cp == remove)
558  {
559  *cp = '\0';
560  --buf->len;
561  }
562 }
563 
564 /*
565  * force a null termination even it requires
566  * truncation of the last char.
567  */
568 void
569 buf_null_terminate(struct buffer *buf)
570 {
571  char *last = (char *) BLAST(buf);
572  if (last && *last == '\0') /* already terminated? */
573  {
574  return;
575  }
576 
577  if (!buf_safe(buf, 1)) /* make space for trailing null */
578  {
579  buf_inc_len(buf, -1);
580  }
581 
582  buf_write_u8(buf, 0);
583 }
584 
585 /*
586  * Remove trailing \r and \n chars and ensure
587  * null termination.
588  */
589 void
590 buf_chomp(struct buffer *buf)
591 {
592  while (true)
593  {
594  char *last = (char *) BLAST(buf);
595  if (!last)
596  {
597  break;
598  }
599  if (char_class(*last, CC_CRLF|CC_NULL))
600  {
601  if (!buf_inc_len(buf, -1))
602  {
603  break;
604  }
605  }
606  else
607  {
608  break;
609  }
610  }
611  buf_null_terminate(buf);
612 }
613 
614 const char *
615 skip_leading_whitespace(const char *str)
616 {
617  while (*str)
618  {
619  const char c = *str;
620  if (!(c == ' ' || c == '\t'))
621  {
622  break;
623  }
624  ++str;
625  }
626  return str;
627 }
628 
629 /*
630  * like buf_null_terminate, but operate on strings
631  */
632 void
633 string_null_terminate(char *str, int len, int capacity)
634 {
635  ASSERT(len >= 0 && len <= capacity && capacity > 0);
636  if (len < capacity)
637  {
638  *(str + len) = '\0';
639  }
640  else if (len == capacity)
641  {
642  *(str + len - 1) = '\0';
643  }
644 }
645 
646 /*
647  * Remove trailing \r and \n chars.
648  */
649 void
650 chomp(char *str)
651 {
652  rm_trailing_chars(str, "\r\n");
653 }
654 
655 /*
656  * Remove trailing chars
657  */
658 void
659 rm_trailing_chars(char *str, const char *what_to_delete)
660 {
661  bool modified;
662  do
663  {
664  const size_t len = strlen(str);
665  modified = false;
666  if (len > 0)
667  {
668  char *cp = str + (len - 1);
669  if (strchr(what_to_delete, *cp) != NULL)
670  {
671  *cp = '\0';
672  modified = true;
673  }
674  }
675  } while (modified);
676 }
677 
678 /*
679  * Allocate a string
680  */
681 char *
682 #ifdef DMALLOC
683 string_alloc_debug(const char *str, struct gc_arena *gc, const char *file, int line)
684 #else
685 string_alloc(const char *str, struct gc_arena *gc)
686 #endif
687 {
688  if (str)
689  {
690  const size_t n = strlen(str) + 1;
691  char *ret;
692 
693  if (gc)
694  {
695 #ifdef DMALLOC
696  ret = (char *) gc_malloc_debug(n, false, gc, file, line);
697 #else
698  ret = (char *) gc_malloc(n, false, gc);
699 #endif
700  }
701  else
702  {
703  /* If there are no garbage collector available, it's expected
704  * that the caller cleans up afterwards. This is coherent with the
705  * earlier behaviour when gc_malloc() would be called with gc == NULL
706  */
707 #ifdef DMALLOC
708  ret = openvpn_dmalloc(file, line, n);
709 #else
710  ret = calloc(1, n);
711 #endif
712  check_malloc_return(ret);
713  }
714  memcpy(ret, str, n);
715  return ret;
716  }
717  else
718  {
719  return NULL;
720  }
721 }
722 
723 /*
724  * Erase all characters in a string
725  */
726 void
727 string_clear(char *str)
728 {
729  if (str)
730  {
731  secure_memzero(str, strlen(str));
732  }
733 }
734 
735 /*
736  * Return the length of a string array
737  */
738 int
739 string_array_len(const char **array)
740 {
741  int i = 0;
742  if (array)
743  {
744  while (array[i])
745  {
746  ++i;
747  }
748  }
749  return i;
750 }
751 
752 char *
753 print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
754 {
755  struct buffer out = alloc_buf_gc(256, gc);
756  int i = 0;
757  for (;; )
758  {
759  const char *cp = *p++;
760  if (!cp)
761  {
762  break;
763  }
764  if (i)
765  {
766  buf_printf(&out, " ");
767  }
768  if (flags & PA_BRACKET)
769  {
770  buf_printf(&out, "[%s]", cp);
771  }
772  else
773  {
774  buf_printf(&out, "%s", cp);
775  }
776  ++i;
777  }
778  return BSTR(&out);
779 }
780 
781 /*
782  * Allocate a string inside a buffer
783  */
784 struct buffer
785 #ifdef DMALLOC
786 string_alloc_buf_debug(const char *str, struct gc_arena *gc, const char *file, int line)
787 #else
788 string_alloc_buf(const char *str, struct gc_arena *gc)
789 #endif
790 {
791  struct buffer buf;
792 
793  ASSERT(str);
794 
795 #ifdef DMALLOC
796  buf_set_read(&buf, (uint8_t *) string_alloc_debug(str, gc, file, line), strlen(str) + 1);
797 #else
798  buf_set_read(&buf, (uint8_t *) string_alloc(str, gc), strlen(str) + 1);
799 #endif
800 
801  if (buf.len > 0) /* Don't count trailing '\0' as part of length */
802  {
803  --buf.len;
804  }
805 
806  return buf;
807 }
808 
809 /*
810  * String comparison
811  */
812 
813 bool
814 buf_string_match_head_str(const struct buffer *src, const char *match)
815 {
816  const size_t size = strlen(match);
817  if (size < 0 || size > src->len)
818  {
819  return false;
820  }
821  return memcmp(BPTR(src), match, size) == 0;
822 }
823 
824 bool
825 buf_string_compare_advance(struct buffer *src, const char *match)
826 {
827  if (buf_string_match_head_str(src, match))
828  {
829  buf_advance(src, (int)strlen(match));
830  return true;
831  }
832  else
833  {
834  return false;
835  }
836 }
837 
838 int
839 buf_substring_len(const struct buffer *buf, int delim)
840 {
841  int i = 0;
842  struct buffer tmp = *buf;
843  int c;
844 
845  while ((c = buf_read_u8(&tmp)) >= 0)
846  {
847  ++i;
848  if (c == delim)
849  {
850  return i;
851  }
852  }
853  return -1;
854 }
855 
856 /*
857  * String parsing
858  */
859 
860 bool
861 buf_parse(struct buffer *buf, const int delim, char *line, const int size)
862 {
863  bool eol = false;
864  int n = 0;
865  int c;
866 
867  ASSERT(size > 0);
868 
869  do
870  {
871  c = buf_read_u8(buf);
872  if (c < 0)
873  {
874  eol = true;
875  }
876  if (c <= 0 || c == delim)
877  {
878  c = 0;
879  }
880  if (n >= size)
881  {
882  break;
883  }
884  line[n++] = c;
885  }
886  while (c);
887 
888  line[size-1] = '\0';
889  return !(eol && !strlen(line));
890 }
891 
892 /*
893  * Print a string which might be NULL
894  */
895 const char *
896 np(const char *str)
897 {
898  if (str)
899  {
900  return str;
901  }
902  else
903  {
904  return "[NULL]";
905  }
906 }
907 
908 /*
909  * Classify and mutate strings based on character types.
910  */
911 
912 bool
913 char_class(const unsigned char c, const unsigned int flags)
914 {
915  if (!flags)
916  {
917  return false;
918  }
919  if (flags & CC_ANY)
920  {
921  return true;
922  }
923 
924  if ((flags & CC_NULL) && c == '\0')
925  {
926  return true;
927  }
928 
929  if ((flags & CC_ALNUM) && isalnum(c))
930  {
931  return true;
932  }
933  if ((flags & CC_ALPHA) && isalpha(c))
934  {
935  return true;
936  }
937  if ((flags & CC_ASCII) && isascii(c))
938  {
939  return true;
940  }
941  if ((flags & CC_CNTRL) && iscntrl(c))
942  {
943  return true;
944  }
945  if ((flags & CC_DIGIT) && isdigit(c))
946  {
947  return true;
948  }
949  if ((flags & CC_PRINT) && (c >= 32 && c != 127)) /* allow ascii non-control and UTF-8, consider DEL to be a control */
950  {
951  return true;
952  }
953  if ((flags & CC_PUNCT) && ispunct(c))
954  {
955  return true;
956  }
957  if ((flags & CC_SPACE) && isspace(c))
958  {
959  return true;
960  }
961  if ((flags & CC_XDIGIT) && isxdigit(c))
962  {
963  return true;
964  }
965 
966  if ((flags & CC_BLANK) && (c == ' ' || c == '\t'))
967  {
968  return true;
969  }
970  if ((flags & CC_NEWLINE) && c == '\n')
971  {
972  return true;
973  }
974  if ((flags & CC_CR) && c == '\r')
975  {
976  return true;
977  }
978 
979  if ((flags & CC_BACKSLASH) && c == '\\')
980  {
981  return true;
982  }
983  if ((flags & CC_UNDERBAR) && c == '_')
984  {
985  return true;
986  }
987  if ((flags & CC_DASH) && c == '-')
988  {
989  return true;
990  }
991  if ((flags & CC_DOT) && c == '.')
992  {
993  return true;
994  }
995  if ((flags & CC_COMMA) && c == ',')
996  {
997  return true;
998  }
999  if ((flags & CC_COLON) && c == ':')
1000  {
1001  return true;
1002  }
1003  if ((flags & CC_SLASH) && c == '/')
1004  {
1005  return true;
1006  }
1007  if ((flags & CC_SINGLE_QUOTE) && c == '\'')
1008  {
1009  return true;
1010  }
1011  if ((flags & CC_DOUBLE_QUOTE) && c == '\"')
1012  {
1013  return true;
1014  }
1015  if ((flags & CC_REVERSE_QUOTE) && c == '`')
1016  {
1017  return true;
1018  }
1019  if ((flags & CC_AT) && c == '@')
1020  {
1021  return true;
1022  }
1023  if ((flags & CC_EQUAL) && c == '=')
1024  {
1025  return true;
1026  }
1027  if ((flags & CC_LESS_THAN) && c == '<')
1028  {
1029  return true;
1030  }
1031  if ((flags & CC_GREATER_THAN) && c == '>')
1032  {
1033  return true;
1034  }
1035  if ((flags & CC_PIPE) && c == '|')
1036  {
1037  return true;
1038  }
1039  if ((flags & CC_QUESTION_MARK) && c == '?')
1040  {
1041  return true;
1042  }
1043  if ((flags & CC_ASTERISK) && c == '*')
1044  {
1045  return true;
1046  }
1047 
1048  return false;
1049 }
1050 
1051 static inline bool
1052 char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive)
1053 {
1054  return char_class(c, inclusive) && !char_class(c, exclusive);
1055 }
1056 
1057 bool
1058 string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
1059 {
1060  char c;
1061  ASSERT(str);
1062  while ((c = *str++))
1063  {
1064  if (!char_inc_exc(c, inclusive, exclusive))
1065  {
1066  return false;
1067  }
1068  }
1069  return true;
1070 }
1071 
1072 /*
1073  * Modify string in place.
1074  * Guaranteed to not increase string length.
1075  */
1076 bool
1077 string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
1078 {
1079  const char *in = str;
1080  bool ret = true;
1081 
1082  ASSERT(str);
1083 
1084  while (true)
1085  {
1086  char c = *in++;
1087  if (c)
1088  {
1089  if (!char_inc_exc(c, inclusive, exclusive))
1090  {
1091  c = replace;
1092  ret = false;
1093  }
1094  if (c)
1095  {
1096  *str++ = c;
1097  }
1098  }
1099  else
1100  {
1101  *str = '\0';
1102  break;
1103  }
1104  }
1105  return ret;
1106 }
1107 
1108 const char *
1109 string_mod_const(const char *str,
1110  const unsigned int inclusive,
1111  const unsigned int exclusive,
1112  const char replace,
1113  struct gc_arena *gc)
1114 {
1115  if (str)
1116  {
1117  char *buf = string_alloc(str, gc);
1118  string_mod(buf, inclusive, exclusive, replace);
1119  return buf;
1120  }
1121  else
1122  {
1123  return NULL;
1124  }
1125 }
1126 
1127 void
1128 string_replace_leading(char *str, const char match, const char replace)
1129 {
1130  ASSERT(match != '\0');
1131  while (*str)
1132  {
1133  if (*str == match)
1134  {
1135  *str = replace;
1136  }
1137  else
1138  {
1139  break;
1140  }
1141  ++str;
1142  }
1143 }
1144 
1145 #ifdef CHARACTER_CLASS_DEBUG
1146 
1147 #define CC_INCLUDE (CC_PRINT)
1148 #define CC_EXCLUDE (0)
1149 #define CC_REPLACE ('.')
1150 
1151 void
1152 character_class_debug(void)
1153 {
1154  char buf[256];
1155 
1156  while (fgets(buf, sizeof(buf), stdin) != NULL)
1157  {
1158  string_mod(buf, CC_INCLUDE, CC_EXCLUDE, CC_REPLACE);
1159  printf("%s", buf);
1160  }
1161 }
1162 
1163 #endif
1164 
1165 #ifdef VERIFY_ALIGNMENT
1166 void
1167 valign4(const struct buffer *buf, const char *file, const int line)
1168 {
1169  if (buf && buf->len)
1170  {
1171  int msglevel = D_ALIGN_DEBUG;
1172  const unsigned int u = (unsigned int) BPTR(buf);
1173 
1174  if (u & (PAYLOAD_ALIGN-1))
1175  {
1176  msglevel = D_ALIGN_ERRORS;
1177  }
1178 
1179  msg(msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d",
1180  (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "",
1181  file,
1182  line,
1183  (ptr_type)buf->data,
1184  buf->offset,
1185  buf->len,
1186  buf->capacity,
1187  buf_debug_file(buf),
1188  buf_debug_line(buf));
1189  }
1190 }
1191 #endif /* ifdef VERIFY_ALIGNMENT */
1192 
1193 /*
1194  * struct buffer_list
1195  */
1196 struct buffer_list *
1198 {
1199  struct buffer_list *ret;
1200  ALLOC_OBJ_CLEAR(ret, struct buffer_list);
1201  ret->max_size = max_size;
1202  ret->size = 0;
1203  return ret;
1204 }
1205 
1206 void
1208 {
1209  if (ol)
1210  {
1211  buffer_list_reset(ol);
1212  free(ol);
1213  }
1214 }
1215 
1216 bool
1218 {
1219  return ol && ol->head != NULL;
1220 }
1221 
1222 void
1224 {
1225  struct buffer_entry *e = ol->head;
1226  while (e)
1227  {
1228  struct buffer_entry *next = e->next;
1229  free_buf(&e->buf);
1230  free(e);
1231  e = next;
1232  }
1233  ol->head = ol->tail = NULL;
1234  ol->size = 0;
1235 }
1236 
1237 void
1238 buffer_list_push(struct buffer_list *ol, const char *str)
1239 {
1240  if (str)
1241  {
1242  const size_t len = strlen((const char *)str);
1243  struct buffer_entry *e = buffer_list_push_data(ol, str, len+1);
1244  if (e)
1245  {
1246  e->buf.len = (int)len; /* Don't count trailing '\0' as part of length */
1247  }
1248  }
1249 }
1250 
1251 struct buffer_entry *
1252 buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size)
1253 {
1254  struct buffer_entry *e = NULL;
1255  if (data && (!ol->max_size || ol->size < ol->max_size))
1256  {
1257  ALLOC_OBJ_CLEAR(e, struct buffer_entry);
1258 
1259  ++ol->size;
1260  if (ol->tail)
1261  {
1262  ASSERT(ol->head);
1263  ol->tail->next = e;
1264  }
1265  else
1266  {
1267  ASSERT(!ol->head);
1268  ol->head = e;
1269  }
1270  e->buf = alloc_buf(size);
1271  memcpy(e->buf.data, data, size);
1272  e->buf.len = (int)size;
1273  ol->tail = e;
1274  }
1275  return e;
1276 }
1277 
1278 struct buffer *
1280 {
1281  if (ol && ol->head)
1282  {
1283  return &ol->head->buf;
1284  }
1285  else
1286  {
1287  return NULL;
1288  }
1289 }
1290 
1291 void
1292 buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len,
1293  const char *sep)
1294 {
1295  const size_t sep_len = strlen(sep);
1296  struct buffer_entry *more = bl->head;
1297  size_t size = 0;
1298  int count = 0;
1299  for (count = 0; more; ++count)
1300  {
1301  size_t extra_len = BLEN(&more->buf) + sep_len;
1302  if (size + extra_len > max_len)
1303  {
1304  break;
1305  }
1306 
1307  size += extra_len;
1308  more = more->next;
1309  }
1310 
1311  if (count >= 2)
1312  {
1313  struct buffer_entry *f;
1314  ALLOC_OBJ_CLEAR(f, struct buffer_entry);
1315  f->buf = alloc_buf(size + 1); /* prevent 0-byte malloc */
1316 
1317  struct buffer_entry *e = bl->head;
1318  for (size_t i = 0; e && i < count; ++i)
1319  {
1320  struct buffer_entry *next = e->next;
1321  buf_copy(&f->buf, &e->buf);
1322  buf_write(&f->buf, sep, sep_len);
1323  free_buf(&e->buf);
1324  free(e);
1325  e = next;
1326  }
1327  bl->head = f;
1328  bl->size -= count - 1;
1329  f->next = more;
1330  if (!more)
1331  {
1332  bl->tail = f;
1333  }
1334  }
1335 }
1336 
1337 void
1338 buffer_list_aggregate(struct buffer_list *bl, const size_t max)
1339 {
1340  buffer_list_aggregate_separator(bl, max, "");
1341 }
1342 
1343 void
1345 {
1346  if (ol && ol->head)
1347  {
1348  struct buffer_entry *e = ol->head->next;
1349  free_buf(&ol->head->buf);
1350  free(ol->head);
1351  ol->head = e;
1352  --ol->size;
1353  if (!e)
1354  {
1355  ol->tail = NULL;
1356  }
1357  }
1358 }
1359 
1360 void
1362 {
1363  if (ol->head)
1364  {
1365  struct buffer *buf = &ol->head->buf;
1366  ASSERT(buf_advance(buf, n));
1367  if (!BLEN(buf))
1368  {
1369  buffer_list_pop(ol);
1370  }
1371  }
1372 }
1373 
1374 struct buffer_list *
1375 buffer_list_file(const char *fn, int max_line_len)
1376 {
1377  FILE *fp = platform_fopen(fn, "r");
1378  struct buffer_list *bl = NULL;
1379 
1380  if (fp)
1381  {
1382  char *line = (char *) malloc(max_line_len);
1383  if (line)
1384  {
1385  bl = buffer_list_new(0);
1386  while (fgets(line, max_line_len, fp) != NULL)
1387  {
1388  buffer_list_push(bl, line);
1389  }
1390  free(line);
1391  }
1392  fclose(fp);
1393  }
1394  return bl;
1395 }
1396 
1397 struct buffer
1398 buffer_read_from_file(const char *filename, struct gc_arena *gc)
1399 {
1400  struct buffer ret = { 0 };
1401 
1402  platform_stat_t file_stat = { 0 };
1403  if (platform_stat(filename, &file_stat) < 0)
1404  {
1405  return ret;
1406  }
1407 
1408  FILE *fp = platform_fopen(filename, "r");
1409  if (!fp)
1410  {
1411  return ret;
1412  }
1413 
1414  const size_t size = file_stat.st_size;
1415  ret = alloc_buf_gc(size + 1, gc); /* space for trailing \0 */
1416  size_t read_size = fread(BPTR(&ret), 1, size, fp);
1417  if (read_size == 0)
1418  {
1419  free_buf_gc(&ret, gc);
1420  goto cleanup;
1421  }
1422  ASSERT(buf_inc_len(&ret, (int)read_size));
1423  buf_null_terminate(&ret);
1424 
1425 cleanup:
1426  fclose(fp);
1427  return ret;
1428 }
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
Definition: buffer.c:1058
static bool buf_write_u8(struct buffer *dest, int data)
Definition: buffer.h:713
#define CC_ALNUM
Definition: buffer.h:910
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition: buffer.h:348
bool buffer_list_defined(const struct buffer_list *ol)
Checks if the list is valid and non-empty.
Definition: buffer.c:1217
void free_buf(struct buffer *buf)
Definition: buffer.c:185
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:685
static uint8_t * buf_write_alloc(struct buffer *buf, size_t size)
Definition: buffer.h:656
struct buffer_list * buffer_list_file(const char *fn, int max_line_len)
Definition: buffer.c:1375
void string_clear(char *str)
Definition: buffer.c:727
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition: buffer.h:401
static bool buf_advance(struct buffer *buf, int size)
Definition: buffer.h:639
#define FHE_SPACE_BREAK_MASK
Definition: buffer.h:518
struct buffer_entry * head
Definition: buffer.h:1112
#define CC_LESS_THAN
Definition: buffer.h:936
unsigned long ptr_type
Definition: common.h:58
bool char_class(const unsigned char c, const unsigned int flags)
Definition: buffer.c:913
#define PAYLOAD_ALIGN
Definition: mtu.h:86
struct buffer string_alloc_buf(const char *str, struct gc_arena *gc)
Definition: buffer.c:788
#define buf_debug_file(buf)
Definition: buffer.c:159
bool buf_assign(struct buffer *dest, const struct buffer *src)
Definition: buffer.c:175
#define CC_PRINT
Definition: buffer.h:915
struct buffer_list * buffer_list_new(const int max_size)
Allocate an empty buffer list of capacity max_size.
Definition: buffer.c:1197
void gc_transfer(struct gc_arena *dest, struct gc_arena *src)
Definition: buffer.c:496
struct gc_entry_special * next
Definition: buffer.h:100
#define static_assert(expr, diagnostic)
Definition: error.h:221
#define unlikely(x)
Definition: syshead.h:36
struct gc_entry * next
Pointer to the next item in the linked list.
Definition: buffer.h:89
#define CC_REVERSE_QUOTE
Definition: buffer.h:933
#define CC_DIGIT
Definition: buffer.h:914
struct buffer alloc_buf(size_t size)
Definition: buffer.c:64
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
Definition: buffer.c:1207
void buffer_list_aggregate(struct buffer_list *bl, const size_t max)
Aggregates as many buffers as possible from bl in a new buffer of maximum length max_len ...
Definition: buffer.c:1338
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:242
#define CC_XDIGIT
Definition: buffer.h:918
#define CC_CR
Definition: buffer.h:922
static int buf_read_u8(struct buffer *buf)
Definition: buffer.h:812
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Definition: buffer.h:335
#define CC_EQUAL
Definition: buffer.h:935
#define CC_CNTRL
Definition: buffer.h:913
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
Definition: buffer.c:753
struct buffer buffer_read_from_file(const char *filename, struct gc_arena *gc)
buffer_read_from_file - copy the content of a file into a buffer
Definition: buffer.c:1398
struct buffer_entry * tail
Definition: buffer.h:1113
static bool char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive)
Definition: buffer.c:1052
bool buffer_write_file(const char *filename, const struct buffer *buf)
Write buffer contents to file.
Definition: buffer.c:369
#define ASSERT(x)
Definition: error.h:204
const char * np(const char *str)
Definition: buffer.c:896
#define CC_BACKSLASH
Definition: buffer.h:924
int max_size
Definition: buffer.h:1115
#define CC_AT
Definition: buffer.h:934
const char * skip_leading_whitespace(const char *str)
Definition: buffer.c:615
#define CC_DOT
Definition: buffer.h:927
#define S_IWUSR
Definition: config-msvc.h:107
int offset
Offset in bytes of the actual content within the allocated memory.
Definition: buffer.h:64
Garbage collection entry for a specially allocated structure that needs a custom free function to be ...
Definition: buffer.h:98
#define CC_COMMA
Definition: buffer.h:928
int capacity
Size in bytes of memory allocated by malloc().
Definition: buffer.h:62
list flags
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
void string_null_terminate(char *str, int len, int capacity)
Definition: buffer.c:633
FILE * platform_fopen(const char *path, const char *mode)
Definition: platform.c:363
Garbage collection entry for one dynamically allocated block of memory.
Definition: buffer.h:87
#define CLEAR(x)
Definition: basic.h:33
#define BPTR(buf)
Definition: buffer.h:124
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
Definition: buffer.c:296
#define D_ALIGN_ERRORS
Definition: errlevel.h:70
#define D_ALIGN_DEBUG
Definition: errlevel.h:138
static bool buf_size_valid(const size_t size)
Definition: buffer.h:272
static uint8_t * buf_prepend(struct buffer *buf, int size)
Definition: buffer.h:627
#define CC_UNDERBAR
Definition: buffer.h:925
#define CC_ASTERISK
Definition: buffer.h:940
static bool buf_init_dowork(struct buffer *buf, int offset)
Definition: buffer.h:306
int platform_open(const char *path, int flags, int mode)
Definition: platform.c:376
void gc_addspecial(void *addr, void(*free_function)(void *), struct gc_arena *a)
Definition: buffer.c:474
bool buf_puts(struct buffer *buf, const char *str)
Definition: buffer.c:269
void x_gc_free(struct gc_arena *a)
Definition: buffer.c:439
void rm_trailing_chars(char *str, const char *what_to_delete)
Definition: buffer.c:659
string f
Definition: http-client.py:6
void buf_null_terminate(struct buffer *buf)
Definition: buffer.c:569
#define malloc
Definition: cmocka.c:1795
int size
Definition: buffer.h:1114
void chomp(char *str)
Definition: buffer.c:650
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1050
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Definition: buffer.c:223
void buffer_list_advance(struct buffer_list *ol, int n)
Definition: buffer.c:1361
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:405
#define CC_NULL
Definition: buffer.h:908
size_t array_mult_safe(const size_t m1, const size_t m2, const size_t extra)
Definition: buffer.c:43
struct buffer buf
Definition: buffer.h:1106
struct gc_entry * list
First element of the linked list of gc_entry structures.
Definition: buffer.h:118
static int buf_forward_capacity(const struct buffer *buf)
Definition: buffer.h:562
#define vsnprintf
#define S_IRUSR
Definition: config-msvc.h:106
void buf_clear(struct buffer *buf)
Definition: buffer.c:164
void buffer_list_reset(struct buffer_list *ol)
Empty the list ol and frees all the contained buffers.
Definition: buffer.c:1223
static bool buf_copy(struct buffer *dest, const struct buffer *src)
Definition: buffer.h:734
#define M_ERRNO
Definition: error.h:103
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition: buffer.c:519
int buf_substring_len(const struct buffer *buf, int delim)
Definition: buffer.c:839
#define buf_debug_line(buf)
Definition: buffer.c:158
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68
void buf_chomp(struct buffer *buf)
Definition: buffer.c:590
int platform_stat(const char *path, platform_stat_t *buf)
Definition: platform.c:389
void buf_size_error(const size_t size)
Definition: buffer.c:55
#define CC_QUESTION_MARK
Definition: buffer.h:939
void buf_catrunc(struct buffer *buf, const char *str)
Definition: buffer.c:338
#define CC_SINGLE_QUOTE
Definition: buffer.h:931
#define BLEN(buf)
Definition: buffer.h:127
const char * string_mod_const(const char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace, struct gc_arena *gc)
Definition: buffer.c:1109
void x_gc_freespecial(struct gc_arena *a)
Definition: buffer.c:458
#define msg(flags,...)
Definition: error.h:153
void * addr
Definition: buffer.h:102
struct buffer_entry * next
Definition: buffer.h:1107
static bool buf_defined(const struct buffer *buf)
Definition: buffer.h:215
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Definition: buffer.c:1077
void buffer_list_push(struct buffer_list *ol, const char *str)
Allocates and appends a new buffer containing str as data to ol.
Definition: buffer.c:1238
int string_array_len(const char **array)
Definition: buffer.c:739
struct gc_entry_special * list_special
Definition: buffer.h:120
#define CC_GREATER_THAN
Definition: buffer.h:937
static bool buf_inc_len(struct buffer *buf, int inc)
Definition: buffer.h:611
static void check_malloc_return(const void *p)
Definition: buffer.h:1093
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition: buffer.c:861
void string_replace_leading(char *str, const char match, const char replace)
Definition: buffer.c:1128
#define CC_SLASH
Definition: buffer.h:930
#define PA_BRACKET
Definition: buffer.h:144
#define CC_PIPE
Definition: buffer.h:938
static bool buf_safe(const struct buffer *buf, size_t len)
Definition: buffer.h:541
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
#define M_FATAL
Definition: error.h:98
#define buf_init(buf, offset)
Definition: buffer.h:196
void buf_rmtail(struct buffer *buf, uint8_t remove)
Definition: buffer.c:554
#define CC_BLANK
Definition: buffer.h:920
#define FHE_CAPS
Definition: buffer.h:519
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:90
void convert_to_one_line(struct buffer *buf)
Definition: buffer.c:354
static int buf_forward_capacity_total(const struct buffer *buf)
Definition: buffer.h:580
#define free
Definition: cmocka.c:1850
bool openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format,...)
Definition: buffer.c:318
Definition: buffer.h:1104
#define CC_SPACE
Definition: buffer.h:917
#define CC_ASCII
Definition: buffer.h:912
#define BLAST(buf)
Definition: buffer.h:126
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition: buffer.h:689
#define BSTR(buf)
Definition: buffer.h:129
#define BEND(buf)
Definition: buffer.h:125
static void free_buf_gc(struct buffer *buf, struct gc_arena *gc)
Definition: buffer.c:192
void(* free_fnc)(void *)
Definition: buffer.h:101
struct buffer clone_buf(const struct buffer *buf)
Definition: buffer.c:117
#define CC_COLON
Definition: buffer.h:929
#define CC_CRLF
Definition: buffer.h:944
#define CC_DASH
Definition: buffer.h:926
#define CC_PUNCT
Definition: buffer.h:916
void buffer_list_pop(struct buffer_list *ol)
Definition: buffer.c:1344
struct buffer * buffer_list_peek(struct buffer_list *ol)
Retrieve the head buffer.
Definition: buffer.c:1279
void buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len, const char *sep)
Aggregates as many buffers as possible from bl in a new buffer of maximum length max_len ...
Definition: buffer.c:1292
struct buffer_entry * buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size)
Allocates and appends a new buffer containing data of length size.
Definition: buffer.c:1252
#define CC_ANY
Definition: buffer.h:907
bool buf_string_match_head_str(const struct buffer *src, const char *match)
Definition: buffer.c:814
struct _stat platform_stat_t
Definition: platform.h:148
#define CC_NEWLINE
Definition: buffer.h:921
#define CC_DOUBLE_QUOTE
Definition: buffer.h:932
bool buf_string_compare_advance(struct buffer *src, const char *match)
Definition: buffer.c:825
#define CC_ALPHA
Definition: buffer.h:911
#define ptr_format
Definition: common.h:49