qstring.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  2. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  3. /* See LICENSE for licensing information */
  4. /**
  5. * \file qstring.c
  6. * \brief Implement QuotedString parsing.
  7. *
  8. * Note that this is only used for controller authentication; do not
  9. * create new users for this. Instead, prefer the cstring.c functions.
  10. **/
  11. #include "orconfig.h"
  12. #include "lib/encoding/qstring.h"
  13. #include "lib/malloc/malloc.h"
  14. #include "lib/log/util_bug.h"
  15. /** If the first <b>in_len_max</b> characters in <b>start</b> contain a
  16. * QuotedString, return the length of that
  17. * string (as encoded, including quotes). Otherwise return -1. */
  18. static inline int
  19. get_qstring_length(const char *start, size_t in_len_max,
  20. int *chars_out)
  21. {
  22. const char *cp, *end;
  23. int chars = 0;
  24. if (*start != '\"')
  25. return -1;
  26. cp = start+1;
  27. end = start+in_len_max;
  28. /* Calculate length. */
  29. while (1) {
  30. if (cp >= end) {
  31. return -1; /* Too long. */
  32. } else if (*cp == '\\') {
  33. if (++cp == end)
  34. return -1; /* Can't escape EOS. */
  35. ++cp;
  36. ++chars;
  37. } else if (*cp == '\"') {
  38. break;
  39. } else {
  40. ++cp;
  41. ++chars;
  42. }
  43. }
  44. if (chars_out)
  45. *chars_out = chars;
  46. return (int)(cp - start+1);
  47. }
  48. /** Given a pointer to a string starting at <b>start</b> containing
  49. * <b>in_len_max</b> characters, decode a string beginning with one double
  50. * quote, containing any number of non-quote characters or characters escaped
  51. * with a backslash, and ending with a final double quote. Place the resulting
  52. * string (unquoted, unescaped) into a newly allocated string in *<b>out</b>;
  53. * store its length in <b>out_len</b>. On success, return a pointer to the
  54. * character immediately following the escaped string. On failure, return
  55. * NULL. */
  56. const char *
  57. decode_qstring(const char *start, size_t in_len_max,
  58. char **out, size_t *out_len)
  59. {
  60. const char *cp, *end;
  61. char *outp;
  62. int len, n_chars = 0;
  63. len = get_qstring_length(start, in_len_max, &n_chars);
  64. if (len<0)
  65. return NULL;
  66. end = start+len-1; /* Index of last quote. */
  67. tor_assert(*end == '\"');
  68. outp = *out = tor_malloc(len+1);
  69. *out_len = n_chars;
  70. cp = start+1;
  71. while (cp < end) {
  72. if (*cp == '\\')
  73. ++cp;
  74. *outp++ = *cp++;
  75. }
  76. *outp = '\0';
  77. tor_assert((outp - *out) == (int)*out_len);
  78. return end+1;
  79. }