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