summaryrefslogtreecommitdiff
path: root/src/common/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/util.c')
-rw-r--r--src/common/util.c148
1 files changed, 27 insertions, 121 deletions
diff --git a/src/common/util.c b/src/common/util.c
index f642c6a6dd..6a5b13e07a 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -27,6 +27,7 @@
#include "sandbox.h"
#include "backtrace.h"
#include "util_process.h"
+#include "util_format.h"
#ifdef _WIN32
#include <io.h>
@@ -1063,6 +1064,9 @@ string_is_valid_ipv6_address(const char *string)
/** Return true iff <b>string</b> matches a pattern of DNS names
* that we allow Tor clients to connect to.
+ *
+ * Note: This allows certain technically invalid characters ('_') to cope
+ * with misconfigured zones that have been encountered in the wild.
*/
int
string_is_valid_hostname(const char *string)
@@ -1075,16 +1079,22 @@ string_is_valid_hostname(const char *string)
smartlist_split_string(components,string,".",0,0);
SMARTLIST_FOREACH_BEGIN(components, char *, c) {
- if (c[0] == '-') {
+ if ((c[0] == '-') || (*c == '_')) {
result = 0;
break;
}
+ /* Allow a single terminating '.' used rarely to indicate domains
+ * are FQDNs rather than relative. */
+ if ((c_sl_idx > 0) && (c_sl_idx + 1 == c_sl_len) && !*c) {
+ continue;
+ }
+
do {
if ((*c >= 'a' && *c <= 'z') ||
(*c >= 'A' && *c <= 'Z') ||
(*c >= '0' && *c <= '9') ||
- (*c == '-'))
+ (*c == '-') || (*c == '_'))
c++;
else
result = 0;
@@ -1229,91 +1239,6 @@ tor_parse_uint64(const char *s, int base, uint64_t min,
CHECK_STRTOX_RESULT();
}
-/** Encode the <b>srclen</b> bytes at <b>src</b> in a NUL-terminated,
- * uppercase hexadecimal string; store it in the <b>destlen</b>-byte buffer
- * <b>dest</b>.
- */
-void
-base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- const char *end;
- char *cp;
-
- tor_assert(destlen >= srclen*2+1);
- tor_assert(destlen < SIZE_T_CEILING);
-
- cp = dest;
- end = src+srclen;
- while (src<end) {
- *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) >> 4 ];
- *cp++ = "0123456789ABCDEF"[ (*(const uint8_t*)src) & 0xf ];
- ++src;
- }
- *cp = '\0';
-}
-
-/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
-static INLINE int
-hex_decode_digit_(char c)
-{
- switch (c) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'A': case 'a': return 10;
- case 'B': case 'b': return 11;
- case 'C': case 'c': return 12;
- case 'D': case 'd': return 13;
- case 'E': case 'e': return 14;
- case 'F': case 'f': return 15;
- default:
- return -1;
- }
-}
-
-/** Helper: given a hex digit, return its value, or -1 if it isn't hex. */
-int
-hex_decode_digit(char c)
-{
- return hex_decode_digit_(c);
-}
-
-/** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode it
- * and store the result in the <b>destlen</b>-byte buffer at <b>dest</b>.
- * Return 0 on success, -1 on failure. */
-int
-base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
-{
- const char *end;
-
- int v1,v2;
- if ((srclen % 2) != 0)
- return -1;
- if (destlen < srclen/2 || destlen > SIZE_T_CEILING)
- return -1;
-
- memset(dest, 0, destlen);
-
- end = src+srclen;
- while (src<end) {
- v1 = hex_decode_digit_(*src);
- v2 = hex_decode_digit_(*(src+1));
- if (v1<0||v2<0)
- return -1;
- *(uint8_t*)dest = (v1<<4)|v2;
- ++dest;
- src+=2;
- }
- return 0;
-}
-
/** Allocate and return a new string representing the contents of <b>s</b>,
* surrounded by quotes and using standard C escapes.
*
@@ -2021,8 +1946,10 @@ read_all(tor_socket_t fd, char *buf, size_t count, int isSocket)
size_t numread = 0;
ssize_t result;
- if (count > SIZE_T_CEILING || count > SSIZE_MAX)
+ if (count > SIZE_T_CEILING || count > SSIZE_MAX) {
+ errno = EINVAL;
return -1;
+ }
while (numread != count) {
if (isSocket)
@@ -2582,8 +2509,10 @@ read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
char *string = NULL;
size_t string_max = 0;
- if (max_bytes_to_read+1 >= SIZE_T_CEILING)
+ if (max_bytes_to_read+1 >= SIZE_T_CEILING) {
+ errno = EINVAL;
return NULL;
+ }
do {
/* XXXX This "add 1K" approach is a little goofy; if we care about
@@ -2595,7 +2524,9 @@ read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
string = tor_realloc(string, string_max);
r = read(fd, string + pos, string_max - pos - 1);
if (r < 0) {
+ int save_errno = errno;
tor_free(string);
+ errno = save_errno;
return NULL;
}
@@ -2663,17 +2594,21 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
if (S_ISFIFO(statbuf.st_mode)) {
size_t sz = 0;
string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz);
+ int save_errno = errno;
if (string && stat_out) {
statbuf.st_size = sz;
memcpy(stat_out, &statbuf, sizeof(struct stat));
}
close(fd);
+ if (!string)
+ errno = save_errno;
return string;
}
#endif
if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
close(fd);
+ errno = EINVAL;
return NULL;
}
@@ -2843,38 +2778,9 @@ parse_config_line_from_str_verbose(const char *line, char **key_out,
char **value_out,
const char **err_out)
{
- /* I believe the file format here is supposed to be:
- FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)?
-
- EMPTYLASTLINE = SPACE* | COMMENT
- EMPTYLINE = EMPTYLASTLINE NL
- SPACE = ' ' | '\r' | '\t'
- COMMENT = '#' NOT-NL*
- NOT-NL = Any character except '\n'
- NL = '\n'
-
- LASTLINE = SPACE* KEY SPACE* VALUES
- LINE = LASTLINE NL
- KEY = KEYCHAR+
- KEYCHAR = Any character except ' ', '\r', '\n', '\t', '#', "\"
-
- VALUES = QUOTEDVALUE | NORMALVALUE
- QUOTEDVALUE = QUOTE QVCHAR* QUOTE EOLSPACE?
- QUOTE = '"'
- QVCHAR = KEYCHAR | ESC ('n' | 't' | 'r' | '"' | ESC |'\'' | OCTAL | HEX)
- ESC = "\\"
- OCTAL = ODIGIT (ODIGIT ODIGIT?)?
- HEX = ('x' | 'X') HEXDIGIT HEXDIGIT
- ODIGIT = '0' .. '7'
- HEXDIGIT = '0'..'9' | 'a' .. 'f' | 'A' .. 'F'
- EOLSPACE = SPACE* COMMENT?
-
- NORMALVALUE = (VALCHAR | ESC ESC_IGNORE | CONTINUATION)* EOLSPACE?
- VALCHAR = Any character except ESC, '#', and '\n'
- ESC_IGNORE = Any character except '#' or '\n'
- CONTINUATION = ESC NL ( COMMENT NL )*
+ /*
+ See torrc_format.txt for a description of the (silly) format this parses.
*/
-
const char *key, *val, *cp;
int continuation = 0;
@@ -3582,7 +3488,7 @@ finish_daemon(const char *cp)
/** Write the current process ID, followed by NL, into <b>filename</b>.
*/
void
-write_pidfile(char *filename)
+write_pidfile(const char *filename)
{
FILE *pidfile;