The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
print.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** Functions to produce and parse the FreeRADIUS presentation format
18  *
19  * @file src/lib/util/print.c
20  *
21  * @copyright 2000,2006 The FreeRADIUS server project
22  */
23 RCSID("$Id: e9fd3b0645e98181df408fd187d6e3ec460cfeab $")
24 
25 #include <freeradius-devel/util/debug.h>
26 #include <freeradius-devel/util/base16.h>
27 #include <freeradius-devel/util/pair.h>
28 
29 
30 /** Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8
31  *
32  * @param[in] str input string.
33  * @param[in] inlen length of input string. May be -1 if str
34  * is \0 terminated.
35  * @return
36  * - 0 if the character is invalid.
37  * - >0 the number of bytes the character consists of.
38  */
39 inline size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
40 {
41  if (inlen == 0) return 0;
42 
43  if (inlen < 0) inlen = 4; /* longest char */
44 
45  if (*str <= 0x7f) return 1; /* 1 */
46 
47  if (*str <= 0xc1) return 0;
48 
49  if (inlen < 2) return 0;
50 
51  if ((str[0] >= 0xc2) && /* 2 */
52  (str[0] <= 0xdf) &&
53  (str[1] >= 0x80) &&
54  (str[1] <= 0xbf)) {
55  return 2;
56  }
57 
58  if (inlen < 3) return 0;
59 
60  if ((str[0] == 0xe0) && /* 3 */
61  (str[1] >= 0xa0) &&
62  (str[1] <= 0xbf) &&
63  (str[2] >= 0x80) &&
64  (str[2] <= 0xbf)) {
65  return 3;
66  }
67 
68  if ((str[0] >= 0xe1) && /* 4a */
69  (str[0] <= 0xec) &&
70  (str[1] >= 0x80) &&
71  (str[1] <= 0xbf) &&
72  (str[2] >= 0x80) &&
73  (str[2] <= 0xbf)) {
74  return 3;
75  }
76 
77  if ((str[0] >= 0xee) && /* 4b */
78  (str[0] <= 0xef) &&
79  (str[1] >= 0x80) &&
80  (str[1] <= 0xbf) &&
81  (str[2] >= 0x80) &&
82  (str[2] <= 0xbf)) {
83  return 3;
84  }
85 
86  if ((str[0] == 0xed) && /* 5 */
87  (str[1] >= 0x80) &&
88  (str[1] <= 0x9f) &&
89  (str[2] >= 0x80) &&
90  (str[2] <= 0xbf)) {
91  return 3;
92  }
93 
94  if (inlen < 4) return 0;
95 
96  if ((str[0] == 0xf0) && /* 6 */
97  (str[1] >= 0x90) &&
98  (str[1] <= 0xbf) &&
99  (str[2] >= 0x80) &&
100  (str[2] <= 0xbf) &&
101  (str[3] >= 0x80) &&
102  (str[3] <= 0xbf)) {
103  return 4;
104  }
105 
106  if ((str[0] >= 0xf1) && /* 6 */
107  (str[0] <= 0xf3) &&
108  (str[1] >= 0x80) &&
109  (str[1] <= 0xbf) &&
110  (str[2] >= 0x80) &&
111  (str[2] <= 0xbf) &&
112  (str[3] >= 0x80) &&
113  (str[3] <= 0xbf)) {
114  return 4;
115  }
116 
117 
118  if ((str[0] == 0xf4) && /* 7 */
119  (str[1] >= 0x80) &&
120  (str[1] <= 0x8f) &&
121  (str[2] >= 0x80) &&
122  (str[2] <= 0xbf) &&
123  (str[3] >= 0x80) &&
124  (str[3] <= 0xbf)) {
125  return 4;
126  }
127 
128  /*
129  * Invalid UTF-8 Character
130  */
131  return 0;
132 }
133 
134 /** Validate a complete UTF8 string
135  *
136  * @param[in] str input string.
137  * @param[in] inlen length of input string. May be -1 if str
138  * is \0 terminated.
139  * @return The number of bytes validated. If ret == inlen the entire
140  * string is valid. Else ret gives the negative offset at
141  * which the first invalid byte sequence was found.
142  */
144 {
145  uint8_t const *p, *end;
146  size_t len;
147 
148  len = inlen < 0 ? strlen((char const *)str) : (size_t) inlen;
149 
150  p = str;
151  end = p + len;
152 
153  do {
154  size_t clen;
155 
156  clen = fr_utf8_char(p, end - p);
157  if (clen == 0) return p - end;
158  p += clen;
159  } while (p < end);
160 
161  return inlen;
162 }
163 
164 /** Return a pointer to the first UTF8 char in a string.
165  *
166  * @param[out] out_chr_len Where to write the length of the multibyte char passed in chr (may be NULL).
167  * @param[in] str Haystack.
168  * @param[in] inlen Length of string (in bytes). Pass -1 to determine the length of the string.
169  * @param[in] chr Multibyte needle.
170  * @return
171  * - Position of chr in str.
172  * - NULL if not found.
173  */
174 char const *fr_utf8_strchr(int *out_chr_len, char const *str, ssize_t inlen, char const *chr)
175 {
176  char const *p = str, *end;
177  int needle_len;
178 
179  if (inlen < 0) inlen = strlen(str);
180 
181  end = str + inlen;
182 
183  /*
184  * Figure out how big the multibyte sequence
185  * we're looking for is.
186  */
187  needle_len = fr_utf8_char((uint8_t const *)chr, -1);
188  if (needle_len == 0) needle_len = 1; /* Invalid UTF8 sequence - ignore - needle is one byte */
189  if (out_chr_len) *out_chr_len = needle_len;
190 
191  /*
192  * Loop over the input sequence, advancing
193  * UTF8 sequence by utf8 seqnce.
194  */
195  while (p < end) {
196  int schr_len;
197 
198  schr_len = fr_utf8_char((uint8_t const *)p, end - p);
199  if (schr_len == 0) schr_len = 1; /* Invalid UTF8 sequence - ignore - advance by 1 */
200  if (schr_len != needle_len) goto next;
201 
202  /*
203  * See if this matches out multibyte needle
204  */
205  if (memcmp(p, chr, schr_len) == 0) return p;
206  next:
207  p += schr_len;
208  }
209 
210  return NULL;
211 }
212 
213 /** Escape any non printable or non-UTF8 characters in the input string
214  *
215  * @note Return value should be checked with is_truncated
216  * @note Will always \0 terminate unless outlen == 0.
217  *
218  * @param[out] out where to write the escaped string.
219  * @param[out] outlen the length of the buffer pointed to by out.
220  * @param[in] in string to escape.
221  * @param[in] inlen length of string to escape (lets us deal with embedded NULs)
222  * @param[in] quote the quotation character
223  * @return
224  * - The number of bytes written to the out buffer.
225  * - A number >= outlen if truncation has occurred.
226  */
227 size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
228 {
229  uint8_t const *p = (uint8_t const *) in;
230  size_t utf8;
231  size_t used;
232  size_t freespace;
233 
234  /* No input, so no output... */
235  if (!in) {
236  if (out && outlen) *out = '\0';
237  return 0;
238  }
239 
240  /* Figure out the length of the input string */
241  if (inlen < 0) inlen = strlen(in);
242 
243  /*
244  * No quotation character, just use memcpy, ensuring we
245  * don't overflow the output buffer.
246  */
247  if (!quote) {
248  if (!out) return inlen;
249 
250  if ((size_t)inlen >= outlen) {
251  memcpy(out, in, outlen - 1);
252  out[outlen - 1] = '\0';
253  } else {
254  memcpy(out, in, inlen);
255  out[inlen] = '\0';
256  }
257 
258  return inlen;
259  }
260 
261  /*
262  * Check the output buffer and length. Zero both of them
263  * out if either are zero.
264  */
265  freespace = outlen;
266  if (freespace == 0) out = NULL;
267  if (!out) freespace = 0;
268 
269  used = 0;
270 
271  while (inlen > 0) {
272  int sp = 0;
273 
274  /*
275  * Always escape the quotation character.
276  */
277  if (*p == quote) {
278  sp = quote;
279  goto do_escape;
280  }
281 
282  /*
283  * Escape the backslash ONLY for single quoted strings.
284  */
285  if (quote == '\'') {
286  if (*p == '\\') {
287  sp = '\\';
288  }
289  goto do_escape;
290  }
291 
292  /*
293  * Try to convert 0x0a --> \r, etc.
294  * Backslashes get handled specially.
295  */
296  switch (*p) {
297  case '\r':
298  sp = 'r';
299  break;
300 
301  case '\n':
302  sp = 'n';
303  break;
304 
305  case '\t':
306  sp = 't';
307  break;
308 
309  case '\\':
310  sp = '\\';
311  break;
312 
313  default:
314  sp = '\0';
315  break;
316  } /* escape the character at *p */
317 
318  do_escape:
319  if (sp) {
320  if ((freespace > 0) && (freespace <= 2)) {
321  if (out) out[used] = '\0';
322  out = NULL;
323  freespace = 0;
324 
325  } else if (freespace > 2) { /* room for char AND trailing zero */
326  if (out) {
327  out[used] = '\\';
328  out[used + 1] = sp;
329  }
330  freespace -= 2;
331  }
332 
333  used += 2;
334  p++;
335  inlen--;
336  continue;
337  }
338 
339  /*
340  * All strings are UTF-8 clean.
341  */
342  utf8 = fr_utf8_char(p, inlen);
343 
344  /*
345  * If we have an invalid UTF-8 character, it gets
346  * copied over as a 1-byte character for single
347  * quoted strings. Which means that the output
348  * isn't strictly UTF-8, but oh well...
349  *
350  * For double quoted strints, the invalid
351  * characters get escaped as octal encodings.
352  */
353  if (utf8 == 0) {
354  if (quote == '\'') {
355  utf8 = 1;
356 
357  } else {
358  if ((freespace > 0) && (freespace <= 4)) {
359  if (out) out[used] = '\0';
360  out = NULL;
361  freespace = 0;
362 
363  } else if (freespace > 4) { /* room for char AND trailing zero */
364  if (out) snprintf(out + used, freespace, "\\%03o", *p);
365  freespace -= 4;
366  }
367 
368  used += 4;
369  p++;
370  inlen--;
371  continue;
372  }
373  }
374 
375  if ((freespace > 0) && (freespace <= utf8)) {
376  if (out) out[used] = '\0';
377  out = NULL;
378  freespace = 0;
379 
380  } else if (freespace > utf8) { /* room for char AND trailing zero */
381  if (out) memcpy(out + used, p, utf8);
382  freespace -= utf8;
383  }
384 
385  used += utf8;
386  p += utf8;
387  inlen -= utf8;
388  }
389 
390  /*
391  * Ensure that the output buffer is always zero terminated.
392  */
393  if (out && freespace) out[used] = '\0';
394 
395  return used;
396 }
397 
398 /** Find the length of the buffer required to fully escape a string with fr_prints
399  *
400  * Were assuming here that's it's cheaper to figure out the length and do one
401  * alloc than repeatedly expand the buffer when we find extra chars which need
402  * to be added.
403  *
404  * @param in string to calculate the escaped length for.
405  * @param inlen length of the input string, if < 0 strlen will be used to check the length.
406  * @param[in] quote the quotation character.
407  * @return the size of buffer required to hold the escaped string including the NUL byte.
408  */
409 size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
410 {
411  return fr_snprint(NULL, 0, in, inlen, quote) + 1;
412 }
413 
414 /** Escape string that may contain binary data, and write it to a new buffer
415  *
416  * This is useful in situations where we expect printable strings as input,
417  * but under some conditions may get binary data. A good example is libldap
418  * and the arrays of struct berval ldap_get_values_len returns.
419  *
420  * @param[in] ctx To allocate new buffer in.
421  * @param[in] in String to escape.
422  * @param[in] inlen Length of string. Should be >= 0 if the data may contain
423  * embedded \0s. Must be >= 0 if data may not be \0 terminated.
424  * If < 0 inlen will be calculated using strlen.
425  * @param[in] quote the quotation character.
426  * @return new buffer holding the escaped string.
427  */
428 char *fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
429 {
430  size_t len, ret;
431  char *out;
432 
433  len = fr_snprint_len(in, inlen, quote);
434 
435  out = talloc_array(ctx, char, len);
436  ret = fr_snprint(out, len, in, inlen, quote);
437  /*
438  * This is a fatal error, but fr_cond_assert is the strongest
439  * assert we're allowed to use in library functions.
440  */
441  if (!fr_cond_assert(ret == (len - 1))) {
442  talloc_free(out);
443  return NULL;
444  }
445 
446  return out;
447 }
448 
449 DIAG_OFF(format-nonliteral)
450 /** Special version of vasprintf which implements custom format specifiers
451  *
452  * @todo Do something sensible with 'n$', though it's probably not actually used
453  * anywhere in our code base.
454  *
455  * - %pV prints a value box as a string.
456  * - %pM prints a list of value boxes, concatenating them.
457  * - %pH prints a value box as a hex string.
458  * - %pP prints a fr_pair_t.
459  *
460  * This breaks strict compatibility with printf but allows us to continue using
461  * the static format string and argument type validation.
462  *
463  * This same idea is used in Linux for the printk function.
464  *
465  * @param[in] ctx to allocate buffer in.
466  * @param[in] fmt string.
467  * @param[in] ap variadic argument list.
468  * @param[in] suppress_secrets as described
469  * @return
470  * - The result of string interpolation.
471  * - NULL if OOM.
472  */
473 static char *fr_vasprintf_internal(TALLOC_CTX *ctx, char const *fmt, va_list ap, bool suppress_secrets)
474 {
475  char const *p = fmt, *end = p + strlen(fmt), *fmt_p = p, *fmt_q = p;
476  char *out = NULL, *out_tmp;
477  va_list ap_p, ap_q;
478  char *subst;
479 
480  out = talloc_strdup(ctx, "");
481  va_copy(ap_p, ap);
482  va_copy(ap_q, ap_p);
483 
484  do {
485  char const *q;
486  char len[2] = { '\0', '\0' };
487 
488  subst = NULL;
489 
490  if ((*p != '%') || (*++p == '%')) {
491  fmt_q = p + 1;
492  continue; /* literal char */
493  }
494 
495  /*
496  * Check for parameter field
497  */
498  for (q = p; isdigit((uint8_t) *q); q++);
499  if ((q != p) && (*q == '$')) {
500  p = q + 1;
501  }
502 
503  /*
504  * Check for flags
505  */
506  do {
507  switch (*p) {
508  case '-':
509  continue;
510 
511  case '+':
512  continue;
513 
514  case ' ':
515  continue;
516 
517  case '0':
518  continue;
519 
520  case '#':
521  continue;
522 
523  default:
524  goto done_flags;
525  }
526  } while (++p < end);
527  done_flags:
528 
529  /*
530  * Check for width field. First for strings, and
531  * then for other parameters.
532  */
533  if ((*p == '.') && (*(p + 1) == '*') && (*(p + 2) == 's')) {
534  (void) va_arg(ap_q, int);
535  p += 2;
536  } else if (*p == '*') {
537  (void) va_arg(ap_q, int);
538  p++;
539  } else {
540  for (q = p; isdigit((uint8_t) *q); q++);
541  p = q;
542  }
543 
544  /*
545  * Check for precision field
546  */
547  if (*p == '.') {
548  char *r;
549 
550  p++;
551  (void) strtoul(p, &r, 10);
552  p = r;
553  }
554 
555  /*
556  * Length modifiers
557  */
558  switch (*p) {
559  case 'h':
560  case 'l':
561  len[0] = *p++;
562  if ((*p == 'h') || (*p == 'l')) len[1] = *p++;
563  break;
564 
565  case 'L':
566  case 'z':
567  case 'j':
568  case 't':
569  len[0] = *p++;
570  break;
571  }
572 
573  /*
574  * Types
575  */
576  switch (*p) {
577  case 'i': /* int */
578  case 'd': /* int */
579  case 'u': /* unsigned int */
580  case 'x': /* unsigned int */
581  case 'X': /* unsigned int */
582  case 'o': /* unsigned int */
583  switch (len[0]) {
584  case 'h':
585  if (len[1] == 'h') { /* char (promoted to int) */
586  (void) va_arg(ap_q, int);
587  } else {
588  (void) va_arg(ap_q, int); /* short (promoted to int) */
589  }
590  break;
591 
592  case 'l':
593  if ((*p == 'i') || (*p == 'd')) {
594  if (len[1] == 'l') {
595  (void) va_arg(ap_q, long); /* long */
596  } else {
597  (void) va_arg(ap_q, long long); /* long long */
598  }
599  } else {
600  if (len[1] == 'l') {
601  (void) va_arg(ap_q, unsigned long); /* unsigned long */
602  } else {
603  (void) va_arg(ap_q, unsigned long long);/* unsigned long long */
604  }
605  }
606  break;
607 
608  case 'z':
609  (void) va_arg(ap_q, size_t); /* size_t */
610  break;
611 
612  case 'j':
613  (void) va_arg(ap_q, intmax_t); /* intmax_t */
614  break;
615 
616  case 't':
617  (void) va_arg(ap_q, ptrdiff_t); /* ptrdiff_t */
618  break;
619 
620  case '\0': /* no length modifier */
621  if ((*p == 'i') || (*p == 'd')) {
622  (void) va_arg(ap_q, int); /* int */
623  } else {
624  (void) va_arg(ap_q, unsigned int); /* unsigned int */
625  }
626  }
627  break;
628 
629  case 'f': /* double */
630  case 'F': /* double */
631  case 'e': /* double */
632  case 'E': /* double */
633  case 'g': /* double */
634  case 'G': /* double */
635  case 'a': /* double */
636  case 'A': /* double */
637  switch (len[0]) {
638  case 'L':
639  (void) va_arg(ap_q, long double); /* long double */
640  break;
641 
642  case 'l': /* does nothing */
643  default: /* no length modifier */
644  (void) va_arg(ap_q, double); /* double */
645  }
646  break;
647 
648  case 's':
649  (void) va_arg(ap_q, char *); /* char * */
650  break;
651 
652  case 'c':
653  (void) va_arg(ap_q, int); /* char (promoted to int) */
654  break;
655 
656  case 'p':
657  /*
658  * subst types
659  */
660  switch (*(p + 1)) {
661  case 'V':
662  case 'R':
663  {
664  fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
665  fr_sbuff_escape_rules_t const *e_rules = NULL;
666 
667  /*
668  * Value boxes get escaped as double-quoted strings, unless the value-box
669  * in question is secret, AND we've been asked to hide secrets.
670  *
671  * Note that the secret_rules only hides secrets of data type "string",
672  * which should be good enough for most purposes.
673  */
674  if (*(p + 1) == 'V') {
675  e_rules = &fr_value_escape_double;
676  }
677 
678  /*
679  * Allocations that are not part of the output
680  * string need to occur in the NULL ctx so we don't fragment
681  * any pool associated with it.
682  */
683  if (unlikely(in && in->secret && suppress_secrets)) {
684  subst = talloc_typed_strdup(NULL, "<<< secret >>>");
685 
686  } else if (in) {
687  fr_value_box_aprint(NULL, &subst, in, e_rules);
688  } else {
689  subst = talloc_typed_strdup(NULL, "(null)");
690  }
691 
692  do_splice:
693  if (!subst) goto oom;
694 
695  p++;
696 
697  /*
698  * Pass part of a format string to printf
699  */
700  if (fmt_q != fmt_p) {
701  char *sub_fmt;
702 
703  sub_fmt = talloc_strndup(NULL, fmt_p, fmt_q - fmt_p);
704  out_tmp = talloc_vasprintf_append_buffer(out, sub_fmt, ap_p);
705  talloc_free(sub_fmt);
706  if (!out_tmp) {
707  oom:
708  fr_strerror_const("Out of memory");
709  talloc_free(out);
710  TALLOC_FREE(subst);
711  va_end(ap_p);
712  va_end(ap_q);
713  return NULL;
714  }
715  out = out_tmp;
716 
717  out_tmp = talloc_strdup_append_buffer(out, subst);
718  if (!out_tmp) goto oom;
719  TALLOC_FREE(subst);
720  out = out_tmp;
721 
722  va_end(ap_p); /* one time use only */
723  } else {
724  out_tmp = talloc_strdup_append_buffer(out, subst);
725  if (!out_tmp) goto oom;
726  TALLOC_FREE(subst);
727  out = out_tmp;
728  }
729 
730  va_copy(ap_p, ap_q); /* already advanced to the next argument */
731 
732  fmt_p = p + 1;
733  }
734  break;
735 
736  case 'H':
737  {
738  fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
739 
740  if (!in) {
741  subst = talloc_strdup(NULL, "(null)");
742  goto do_splice;
743  }
744 
745  switch (in->type) {
746  case FR_TYPE_OCTETS:
747  if (in->vb_octets) {
748  fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP(in->vb_octets, in->vb_length));
749  } else {
750  subst = talloc_strdup(NULL, "");
751  }
752  break;
753 
754  case FR_TYPE_STRING:
755  fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP((uint8_t const *)in->vb_strvalue, in->vb_length));
756  break;
757 
758  default:
759  {
760  fr_value_box_t dst;
761 
762  /*
763  * Convert the boxed value into a octets buffer
764  */
765  if (fr_value_box_cast(NULL, &dst, FR_TYPE_OCTETS, NULL, in) < 0) {
766  subst = talloc_strdup(NULL, fr_strerror()); /* splice in the error */
767  if (!subst) goto oom;
768  }
769 
770  fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP((uint8_t const *)dst.vb_octets, dst.vb_length));
771  fr_value_box_clear(&dst);
772  break;
773  }
774  }
775  }
776  goto do_splice;
777 
778  case 'M':
779  {
780  fr_value_box_list_t const *in = va_arg(ap_q, fr_value_box_list_t const *);
781 
782  if (!in) {
783  subst = talloc_strdup(NULL, "(null)");
784  goto do_splice;
785  }
786 
787  if (suppress_secrets) {
789  } else {
790  subst = fr_value_box_list_aprint(NULL, in, NULL, &fr_value_escape_double);
791  }
792  }
793  goto do_splice;
794 
795  case 'P':
796  {
797  fr_pair_t const *in = va_arg(ap_q, fr_pair_t const *);
798 
799  if (!in) {
800  subst = talloc_strdup(NULL, "(null)");
801  goto do_splice;
802  }
803 
804  PAIR_VERIFY(in);
805 
806  if (unlikely(in && in->data.secret && suppress_secrets)) {
807  fr_pair_aprint_secure(NULL, &subst, NULL, in);
808  } else {
809  fr_pair_aprint(NULL, &subst, NULL, in);
810  }
811  }
812  goto do_splice;
813 
814  default:
815  (void) va_arg(ap_q, void *); /* void * */
816  }
817  break;
818 
819  case 'n':
820  (void) va_arg(ap_q, int *); /* int * */
821  break;
822 
823  default:
824  break;
825  }
826  fmt_q = p + 1;
827  } while (++p < end);
828 
829  /*
830  * Print out the rest of the format string.
831  */
832  if (*fmt_p) {
833  out_tmp = talloc_vasprintf_append_buffer(out, fmt_p, ap_p);
834  if (!out_tmp) goto oom;
835  out = out_tmp;
836  }
837 
838  va_end(ap_p);
839  va_end(ap_q);
840 
841  /*
842  * One of the above talloc calls sets the type to
843  * be the string. We correct this here so we
844  * don't trigger talloc_aborts later...
845  */
846  talloc_set_type(out, char);
847 
848  return out;
849 }
850 
851 char *fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
852 {
853  return fr_vasprintf_internal(ctx, fmt, ap, false);
854 }
855 
856 char *fr_vasprintf_secure(TALLOC_CTX *ctx, char const *fmt, va_list ap)
857 {
858  return fr_vasprintf_internal(ctx, fmt, ap, true);
859 }
860 
861 
862 DIAG_ON(format-nonliteral)
863 
864 /** Special version of asprintf which implements custom format specifiers
865  *
866  * @copybrief fr_vasprintf
867  *
868  * @param[in] ctx to allocate buffer in.
869  * @param[in] fmt string.
870  * @param[in] ... variadic argument list.
871  * @return
872  * - The result of string interpolation.
873  */
874 char *fr_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
875 {
876  va_list ap;
877  char *ret;
878 
879  va_start(ap, fmt);
880  ret = fr_vasprintf(ctx, fmt, ap);
881  va_end(ap);
882 
883  return ret;
884 }
885 
886 /** Special version of fprintf which implements custom format specifiers
887  *
888  * @copybrief fr_vasprintf
889  *
890  * @param[in] fp to write the result of fmt string.
891  * @param[in] fmt string.
892  * @param[in] ... variadic argument list.
893  * @return
894  * - On success, the number of bytes written is returned (zero indicates nothing was written).
895  * - On error, -1 is returned, and errno is set appropriately
896  */
897 ssize_t fr_fprintf(FILE *fp, char const *fmt, ...)
898 {
899  va_list ap;
900  char *buf;
901  int ret;
902 
903  if (!fp) {
904  fr_strerror_const("Invalid 'fp'");
905  return -1;
906  }
907 
908  va_start(ap, fmt);
909  buf = fr_vasprintf(NULL, fmt, ap);
910  va_end(ap);
911 
912  ret = fputs(buf, fp);
913 
914  TALLOC_FREE(buf);
915 
916  return ret;
917 }
va_end(args)
static int const char * fmt
Definition: acutest.h:573
va_start(args, fmt)
static fr_slen_t fr_base16_aencode(TALLOC_CTX *ctx, char **out, fr_dbuff_t *in)
Convert binary data to a hex string, allocating the output buffer.
Definition: base16.h:71
#define RCSID(id)
Definition: build.h:481
#define DIAG_ON(_x)
Definition: build.h:456
#define unlikely(_x)
Definition: build.h:379
#define DIAG_OFF(_x)
Definition: build.h:455
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:514
next
Definition: dcursor.h:178
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
static fr_slen_t in
Definition: dict.h:821
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
unsigned long int size_t
Definition: merged_model.c:25
static size_t used
ssize_t fr_fprintf(FILE *fp, char const *fmt,...)
Special version of fprintf which implements custom format specifiers.
Definition: print.c:897
size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
Escape any non printable or non-UTF8 characters in the input string.
Definition: print.c:227
char const * fr_utf8_strchr(int *out_chr_len, char const *str, ssize_t inlen, char const *chr)
Return a pointer to the first UTF8 char in a string.
Definition: print.c:174
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition: print.c:851
fr_slen_t fr_utf8_str(uint8_t const *str, ssize_t inlen)
Validate a complete UTF8 string.
Definition: print.c:143
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
Definition: print.c:428
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition: print.c:39
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition: print.c:874
size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
Find the length of the buffer required to fully escape a string with fr_prints.
Definition: print.c:409
static char * fr_vasprintf_internal(TALLOC_CTX *ctx, char const *fmt, va_list ap, bool suppress_secrets)
Special version of vasprintf which implements custom format specifiers.
Definition: print.c:473
char * fr_vasprintf_secure(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition: print.c:856
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:445
static fr_slen_t fr_pair_aprint(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print
#define PAIR_VERIFY(_x)
Definition: pair.h:191
static fr_slen_t static vp fr_slen_t fr_pair_aprint_secure(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print_secure
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
#define fr_strerror_const(_msg)
Definition: strerror.h:223
fr_sbuff_escape_rules_t fr_value_escape_double
Definition: value.c:350
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition: value.c:3352
char * fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together.
Definition: value.c:6028
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3723
char * fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together hiding "secret" values.
Definition: value.c:6078
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:997
int format(printf, 5, 0))
static size_t char ** out
Definition: value.h:997