|
@@ -0,0 +1,90 @@
|
|
|
+/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
|
|
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
|
|
|
+/* See LICENSE for licensing information */
|
|
|
+
|
|
|
+/**
|
|
|
+ * \file qstring.c
|
|
|
+ * \brief Implement QuotedString parsing.
|
|
|
+ *
|
|
|
+ * Note that this is only used for controller authentication; do not
|
|
|
+ * create new users for this. Instead, prefer the cstring.c functions.
|
|
|
+ **/
|
|
|
+
|
|
|
+#include "orconfig.h"
|
|
|
+#include "lib/encoding/qstring.h"
|
|
|
+#include "lib/malloc/malloc.h"
|
|
|
+#include "lib/log/util_bug.h"
|
|
|
+
|
|
|
+/** If the first <b>in_len_max</b> characters in <b>start</b> contain a
|
|
|
+ * QuotedString, return the length of that
|
|
|
+ * string (as encoded, including quotes). Otherwise return -1. */
|
|
|
+static inline int
|
|
|
+get_qstring_length(const char *start, size_t in_len_max,
|
|
|
+ int *chars_out)
|
|
|
+{
|
|
|
+ const char *cp, *end;
|
|
|
+ int chars = 0;
|
|
|
+
|
|
|
+ if (*start != '\"')
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ cp = start+1;
|
|
|
+ end = start+in_len_max;
|
|
|
+
|
|
|
+ /* Calculate length. */
|
|
|
+ while (1) {
|
|
|
+ if (cp >= end) {
|
|
|
+ return -1; /* Too long. */
|
|
|
+ } else if (*cp == '\\') {
|
|
|
+ if (++cp == end)
|
|
|
+ return -1; /* Can't escape EOS. */
|
|
|
+ ++cp;
|
|
|
+ ++chars;
|
|
|
+ } else if (*cp == '\"') {
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ ++cp;
|
|
|
+ ++chars;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (chars_out)
|
|
|
+ *chars_out = chars;
|
|
|
+ return (int)(cp - start+1);
|
|
|
+}
|
|
|
+
|
|
|
+/** Given a pointer to a string starting at <b>start</b> containing
|
|
|
+ * <b>in_len_max</b> characters, decode a string beginning with one double
|
|
|
+ * quote, containing any number of non-quote characters or characters escaped
|
|
|
+ * with a backslash, and ending with a final double quote. Place the resulting
|
|
|
+ * string (unquoted, unescaped) into a newly allocated string in *<b>out</b>;
|
|
|
+ * store its length in <b>out_len</b>. On success, return a pointer to the
|
|
|
+ * character immediately following the escaped string. On failure, return
|
|
|
+ * NULL. */
|
|
|
+const char *
|
|
|
+decode_qstring(const char *start, size_t in_len_max,
|
|
|
+ char **out, size_t *out_len)
|
|
|
+{
|
|
|
+ const char *cp, *end;
|
|
|
+ char *outp;
|
|
|
+ int len, n_chars = 0;
|
|
|
+
|
|
|
+ len = get_qstring_length(start, in_len_max, &n_chars);
|
|
|
+ if (len<0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ end = start+len-1; /* Index of last quote. */
|
|
|
+ tor_assert(*end == '\"');
|
|
|
+ outp = *out = tor_malloc(len+1);
|
|
|
+ *out_len = n_chars;
|
|
|
+
|
|
|
+ cp = start+1;
|
|
|
+ while (cp < end) {
|
|
|
+ if (*cp == '\\')
|
|
|
+ ++cp;
|
|
|
+ *outp++ = *cp++;
|
|
|
+ }
|
|
|
+ *outp = '\0';
|
|
|
+ tor_assert((outp - *out) == (int)*out_len);
|
|
|
+
|
|
|
+ return end+1;
|
|
|
+}
|