You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2023/03/17 04:32:04 UTC

[trafficserver] branch master updated: Refresh SOCKs logic, remove IpMapConf (#9523)

This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 61c56b19c Refresh SOCKs logic, remove IpMapConf (#9523)
61c56b19c is described below

commit 61c56b19c3bbfeb0e67de0fc64e172636de9c5d3
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Thu Mar 16 23:31:57 2023 -0500

    Refresh SOCKs logic, remove IpMapConf (#9523)
    
    * SOCKS: Update for libswoc, remove IpMap dependency.
    
    * swoc: Remove IpMapConf
---
 include/tscore/IpMapConf.h     |  35 --------
 iocore/net/P_Socks.h           |  15 ++--
 iocore/net/Socks.cc            | 115 +++++++++++++------------
 iocore/net/UnixNetProcessor.cc |   2 +-
 src/tscore/IpMapConf.cc        | 187 -----------------------------------------
 src/tscore/Makefile.am         |   1 -
 6 files changed, 71 insertions(+), 284 deletions(-)

diff --git a/include/tscore/IpMapConf.h b/include/tscore/IpMapConf.h
deleted file mode 100644
index 7d229adf1..000000000
--- a/include/tscore/IpMapConf.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @file
-
-  Loading @c IpMap from a configuration file.
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- */
-
-// Copied from IPRange.cc for backwards compatibility.
-
-#pragma once
-
-class IpMap; // declare in name only.
-
-// Returns 0 if successful, error string otherwise
-int read_addr(char *line, int n, int *i, sockaddr *addr, char *err);
-// Returns 0 if successful, error string otherwise
-char *Load_IpMap_From_File(IpMap *map, int fd, char const *key_str);
-// Returns 0 if successful, error string otherwise
-char *Load_IpMap_From_File(IpMap *map, FILE *f, char const *key_str);
diff --git a/iocore/net/P_Socks.h b/iocore/net/P_Socks.h
index 2f875c1e4..d924796af 100644
--- a/iocore/net/P_Socks.h
+++ b/iocore/net/P_Socks.h
@@ -22,12 +22,16 @@
  */
 
 #pragma once
+
+#include "swoc/TextView.h"
+#include "swoc/swoc_ip.h"
+
 #include "P_EventSystem.h"
 #include "I_Socks.h"
+#include "tscpp/util/ts_errata.h"
 
 #ifdef SOCKS_WITH_TS
 #include "ParentSelection.h"
-#include "tscore/IpMap.h"
 #endif
 
 enum {
@@ -43,8 +47,7 @@ struct socks_conf_struct {
   int server_connect_timeout    = 0;
   int socks_timeout             = 100;
   unsigned char default_version = 5;
-  char *user_name_n_passwd      = nullptr;
-  int user_name_n_passwd_len    = 0;
+  std::string user_name_n_passwd;
 
   int per_server_connection_attempts = 1;
   int connection_attempts            = 0;
@@ -55,7 +58,7 @@ struct socks_conf_struct {
   unsigned short http_port = 1080;
 
 #ifdef SOCKS_WITH_TS
-  IpMap ip_map;
+  swoc::IPRangeSet ip_addrs;
 #endif
 
 #ifndef SOCKS_WITH_TS
@@ -75,7 +78,9 @@ extern struct socks_conf_struct *g_socks_conf_stuff;
 
 void start_SocksProxy(int port);
 
-int loadSocksAuthInfo(int fd, socks_conf_struct *socks_stuff);
+int loadSocksAuthInfo(swoc::TextView content, socks_conf_struct *socks_stuff);
+
+swoc::Errata loadSocksIPAddrs(swoc::TextView content, socks_conf_struct *socks_stuff);
 
 // umm.. the following typedef should take _its own_ type as one of the args
 // not possible with C
diff --git a/iocore/net/Socks.cc b/iocore/net/Socks.cc
index aceddf700..ecb282d57 100644
--- a/iocore/net/Socks.cc
+++ b/iocore/net/Socks.cc
@@ -30,11 +30,16 @@
   duplicated in UnixNet.cc and NTNetProcessor.cc
 */
 
+#include "swoc/swoc_file.h"
+#include "swoc/bwf_std.h"
+#include "swoc/bwf_ex.h"
+
 #include "P_Net.h"
 #include "tscore/I_Layout.h"
 #include "tscore/ink_sock.h"
 #include "tscore/InkErrno.h"
-#include "tscore/IpMapConf.h"
+
+using namespace swoc::literals;
 
 socks_conf_struct *g_socks_conf_stuff = nullptr;
 
@@ -460,8 +465,10 @@ loadSocksConfiguration(socks_conf_struct *socks_conf_stuff)
   int socks_config_fd = -1;
   ats_scoped_str config_pathname;
 #ifdef SOCKS_WITH_TS
-  char *tmp;
+  swoc::Errata errata;
 #endif
+  std::error_code ec;
+  std::string config_text;
 
   socks_conf_stuff->accept_enabled = 0; // initialize it INKqa08593
   socks_conf_stuff->socks_needed   = REC_ConfigReadInteger("proxy.config.socks.socks_needed");
@@ -506,28 +513,28 @@ loadSocksConfiguration(socks_conf_struct *socks_conf_stuff)
     goto error;
   }
 
-  socks_config_fd = ::open(config_pathname, O_RDONLY);
-
-  if (socks_config_fd < 0) {
-    Error("SOCKS Config: could not open config file '%s'. SOCKS Turned off", (const char *)config_pathname);
+  config_text = swoc::file::load(swoc::file::path(config_pathname), ec);
+  if (ec) {
+    swoc::bwprint(config_text, "SOCK Config: Disabled, could not open config file \"{}\" {}", config_pathname, ec);
+    Error("%s", config_text.c_str());
     goto error;
   }
+
 #ifdef SOCKS_WITH_TS
-  tmp = Load_IpMap_From_File(&socks_conf_stuff->ip_map, socks_config_fd, "no_socks");
+  errata = loadSocksIPAddrs(config_text, socks_conf_stuff);
 
-  if (tmp) {
-    Error("SOCKS Config: Error while reading ip_range: %s.", tmp);
-    ats_free(tmp);
+  if (!errata.is_ok()) {
+    swoc::bwprint(config_text, "SOCK Config: Error\n{}", errata);
+    Error("%s", config_text.c_str());
     goto error;
   }
 #endif
 
-  if (loadSocksAuthInfo(socks_config_fd, socks_conf_stuff) != 0) {
+  if (loadSocksAuthInfo(config_text, socks_conf_stuff) != 0) {
     Error("SOCKS Config: Error while reading Socks auth info");
     goto error;
   }
   Debug("Socks", "Socks Turned on");
-  ::close(socks_config_fd);
 
   return;
 error:
@@ -540,60 +547,58 @@ error:
 }
 
 int
-loadSocksAuthInfo(int fd, socks_conf_struct *socks_stuff)
+loadSocksAuthInfo(swoc::TextView content, socks_conf_struct *socks_stuff)
 {
-  char c              = '\0';
-  char line[256]      = {0}; // initialize all chars to nil
-  char user_name[256] = {0};
-  char passwd[256]    = {0};
-
-  if (lseek(fd, 0, SEEK_SET) < 0) {
-    Warning("Can not seek on Socks configuration file\n");
-    return -1;
-  }
-
-  bool end_of_file = false;
-  do {
-    int n = 0, rc;
-    while (((rc = read(fd, &c, 1)) == 1) && (c != '\n') && (n < 254)) {
-      line[n++] = c;
-    }
-    if (rc <= 0) {
-      end_of_file = true;
-    }
-    line[n] = '\0';
-
-    // coverity[secure_coding]
-    rc = sscanf(line, " auth u %255s %255s ", user_name, passwd);
-    if (rc >= 2) {
-      int len1 = strlen(user_name);
-      int len2 = strlen(passwd);
-
-      Debug("Socks", "Read user_name(%s) and passwd(%s) from config file", user_name, passwd);
-
-      socks_stuff->user_name_n_passwd_len = len1 + len2 + 2;
+  static constexpr swoc::TextView PREFIX = "auth u ";
+  std::string text;
 
-      char *ptr = static_cast<char *>(ats_malloc(socks_stuff->user_name_n_passwd_len));
-      ptr[0]    = len1;
-      memcpy(&ptr[1], user_name, len1);
-      ptr[len1 + 1] = len2;
-      memcpy(&ptr[len1 + 2], passwd, len2);
+  while (content.ltrim_if(&isspace)) {
+    auto line = content.take_prefix_at('\n');
 
-      socks_stuff->user_name_n_passwd = ptr;
+    if (line.starts_with(PREFIX)) {
+      line.remove_prefix(PREFIX.size()).ltrim_if(&isspace);
+      auto user_name = line.take_prefix_if(&isspace);
+      auto password  = line.take_prefix_if(&isspace);
 
-      return 0;
+      if (!user_name.empty() && !password.empty()) {
+        Debug("Socks", "%s", swoc::bwprint(text, "Read auth credentials \"{}\" : \"{}\"", user_name, password).c_str());
+        swoc::bwprint(socks_stuff->user_name_n_passwd, "{}{}{}{}", char(user_name.size()), user_name, char(password.size()),
+                      password);
+      }
     }
-  } while (!end_of_file);
-
+  }
   return 0;
 }
 
+swoc::Errata
+loadSocksIPAddrs(swoc::TextView content, socks_conf_struct *socks_stuff)
+{
+  static constexpr swoc::TextView PREFIX = "no_socks ";
+  std::string text;
+
+  while (content.ltrim_if(&isspace)) {
+    auto line = content.take_prefix_at('\n');
+    if (line.starts_with(PREFIX)) {
+      line.remove_prefix(PREFIX.size());
+      while (line.ltrim_if(&isspace)) {
+        auto token = line.take_prefix_at(',');
+        if (swoc::IPRange r; r.load(token)) {
+          socks_stuff->ip_addrs.mark(r);
+        } else {
+          return swoc::Errata(ERRATA_ERROR, "Invalid IP address range \"{}\"", token);
+        }
+      }
+    }
+  }
+  return {};
+}
+
 int
 socks5BasicAuthHandler(int event, unsigned char *p, void (**h_ptr)(void))
 {
   // for more info on Socks5 see RFC 1928
   int ret           = 0;
-  char *pass_phrase = netProcessor.socks_conf_stuff->user_name_n_passwd;
+  char *pass_phrase = netProcessor.socks_conf_stuff->user_name_n_passwd.data();
 
   switch (event) {
   case SOCKS_AUTH_OPEN:
@@ -672,8 +677,8 @@ socks5PasswdAuthHandler(int event, unsigned char *p, void (**h_ptr)(void))
 
   switch (event) {
   case SOCKS_AUTH_OPEN:
-    pass_phrase = netProcessor.socks_conf_stuff->user_name_n_passwd;
-    pass_len    = netProcessor.socks_conf_stuff->user_name_n_passwd_len;
+    pass_phrase = netProcessor.socks_conf_stuff->user_name_n_passwd.data();
+    pass_len    = netProcessor.socks_conf_stuff->user_name_n_passwd.length();
     ink_assert(pass_phrase);
 
     p[0] = 1; // version
diff --git a/iocore/net/UnixNetProcessor.cc b/iocore/net/UnixNetProcessor.cc
index 35fae59f0..8ee1b65e7 100644
--- a/iocore/net/UnixNetProcessor.cc
+++ b/iocore/net/UnixNetProcessor.cc
@@ -200,7 +200,7 @@ UnixNetProcessor::connect_re_internal(Continuation *cont, sockaddr const *target
                            * we need to connect using socks server even
                            * if this ip is in no_socks list.
                            */
-                          !socks_conf_stuff->ip_map.contains(target))
+                          !socks_conf_stuff->ip_addrs.contains(swoc::IPAddr(target)))
 #endif
   );
   SocksEntry *socksEntry = nullptr;
diff --git a/src/tscore/IpMapConf.cc b/src/tscore/IpMapConf.cc
deleted file mode 100644
index 51bcc5ea0..000000000
--- a/src/tscore/IpMapConf.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-/** @file
-
-  Loading @c IpMap from a configuration file.
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- */
-
-// Copied from IPRange.cc for backwards compatibility.
-
-#include "tscore/IpMap.h"
-#include "tscore/IpMapConf.h"
-#include "tscore/ink_memory.h"
-
-static size_t const ERR_STRING_LEN = 256;
-static size_t const MAX_LINE_SIZE  = 2048;
-
-// Returns 0 if successful, 1 if failed
-// line  Input text (source line).
-// n     Amount of data in @a line.
-// i     [in,out] Offset in line.
-// addr  [out] Destination for address.
-// err   Buffer for error string (must be ERR_STRING_LEN big).
-int
-read_addr(char *line, int n, int *i, sockaddr *addr, char *err)
-{
-  int k;
-  char dst[INET6_ADDRSTRLEN];
-  char *src        = line + *i;
-  bool bracketed_p = false;
-
-  // Allow enclosing brackets to be more consistent but
-  // don't bother passing it to @c ntop.
-  if ((*i < n) && ('[' == *src)) {
-    ++*i, ++src, bracketed_p = true;
-  }
-
-  for (k = 0; k < INET6_ADDRSTRLEN && *i < n && (isxdigit(*src) || '.' == *src || ':' == *src); ++k, ++*i, ++src) {
-    dst[k] = *src;
-  }
-
-  if (bracketed_p && (!(*i < n) || (']' != *src))) {
-    snprintf(err, ERR_STRING_LEN, "Unclosed brackets");
-    return EINVAL;
-  }
-
-  if (k == sizeof(dst)) {
-    snprintf(err, ERR_STRING_LEN, "IP address too long");
-    return EINVAL;
-  }
-
-  dst[k] = '\0';
-  if (0 != ats_ip_pton(dst, addr)) {
-    snprintf(err, ERR_STRING_LEN, "IP address '%s' improperly formatted", dst);
-    return EINVAL;
-  }
-  return 0;
-}
-
-char *
-Load_IpMap_From_File(IpMap *map, int fd, const char *key_str)
-{
-  char *zret = nullptr;
-  int fd2    = dup(fd); // dup to avoid closing the original file.
-  FILE *f    = nullptr;
-
-  if (fd2 >= 0) {
-    f = fdopen(fd2, "r");
-  }
-
-  if (f != nullptr) {
-    zret = Load_IpMap_From_File(map, f, key_str);
-    fclose(f);
-  } else {
-    zret = static_cast<char *>(ats_malloc(ERR_STRING_LEN));
-    snprintf(zret, ERR_STRING_LEN, "Unable to reopen file descriptor as stream %d:%s", errno, strerror(errno));
-  }
-  return zret;
-}
-
-// Skip space in line, returning true if more data is available
-// (not end of line).
-//
-// line    Source line.
-// n       Line length.
-// offset  Current offset
-static inline bool
-skip_space(char *line, int n, int &offset)
-{
-  while (offset < n && isspace(line[offset])) {
-    ++offset;
-  }
-  return offset < n;
-}
-
-// Returns 0 if successful, error string otherwise
-char *
-Load_IpMap_From_File(IpMap *map, FILE *f, const char *key_str)
-{
-  int i, n, line_no;
-  int key_len = strlen(key_str);
-  IpEndpoint laddr, raddr;
-  char line[MAX_LINE_SIZE];
-  char err_buff[ERR_STRING_LEN];
-
-  // First hardcode 127.0.0.1 into the table
-  map->mark(INADDR_LOOPBACK);
-
-  line_no = 0;
-  while (fgets(line, MAX_LINE_SIZE, f)) {
-    ++line_no;
-    n = strlen(line);
-    // Find first white space which terminates the line key.
-    for (i = 0; i < n && !isspace(line[i]); ++i) {
-      ;
-    }
-    if (i != key_len || 0 != strncmp(line, key_str, key_len)) {
-      continue;
-    }
-    // Now look for IP address
-    while (true) {
-      if (!skip_space(line, n, i)) {
-        break;
-      }
-
-      if (0 != read_addr(line, n, &i, &laddr.sa, err_buff)) {
-        char *error_str = static_cast<char *>(ats_malloc(ERR_STRING_LEN));
-        snprintf(error_str, ERR_STRING_LEN, "Invalid input configuration (%s) at line %d offset %d - '%s'", err_buff, line_no, i,
-                 line);
-        return error_str;
-      }
-
-      if (!skip_space(line, n, i) || line[i] == ',') {
-        // You have read an IP address. Enter it in the table
-        map->mark(&laddr);
-        if (i == n) {
-          break;
-        } else {
-          ++i;
-        }
-      } else if (line[i] == '-') {
-        // What you have just read is the start of the range,
-        // Now, read the end of the IP range
-        ++i;
-        if (!skip_space(line, n, i)) {
-          char *error_str = static_cast<char *>(ats_malloc(ERR_STRING_LEN));
-          snprintf(error_str, ERR_STRING_LEN, "Invalid input (unterminated range) at line %d offset %d - '%s'", line_no, i, line);
-          return error_str;
-        } else if (0 != read_addr(line, n, &i, &raddr.sa, err_buff)) {
-          char *error_str = static_cast<char *>(ats_malloc(ERR_STRING_LEN));
-          snprintf(error_str, ERR_STRING_LEN, "Invalid input (%s) at line %d offset %d - '%s'", err_buff, line_no, i, line);
-          return error_str;
-        }
-        map->mark(&laddr.sa, &raddr.sa);
-        if (!skip_space(line, n, i)) {
-          break;
-        }
-        if (line[i] != ',') {
-          char *error_str = static_cast<char *>(ats_malloc(ERR_STRING_LEN));
-          snprintf(error_str, ERR_STRING_LEN, "Invalid input (expecting comma) at line %d offset %d - '%s'", line_no, i, line);
-          return error_str;
-        }
-        ++i;
-      } else {
-        char *error_str = static_cast<char *>(ats_malloc(ERR_STRING_LEN));
-        snprintf(error_str, ERR_STRING_LEN, "Invalid input (expecting dash or comma) at line %d offset %d", line_no, i);
-        return error_str;
-      }
-    }
-  }
-  return nullptr;
-}
diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am
index 941a3625d..4cd1fa6d2 100644
--- a/src/tscore/Makefile.am
+++ b/src/tscore/Makefile.am
@@ -105,7 +105,6 @@ libtscore_la_SOURCES = \
 	ink_time.cc \
 	ink_uuid.cc \
 	IpMap.cc \
-	IpMapConf.cc \
 	JeMiAllocator.cc \
 	Layout.cc \
 	llqueue.cc \