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