github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/redact_test.go (about)

     1  /*
     2   * Copyright (c) 2020, Psiphon Inc.
     3   * All rights reserved.
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package common
    21  
    22  import (
    23  	"os"
    24  	"strings"
    25  	"testing"
    26  )
    27  
    28  func TestRedactIPAddresses(t *testing.T) {
    29  
    30  	testCases := []struct {
    31  		description    string
    32  		input          string
    33  		expectedOutput string
    34  		escape         bool
    35  	}{
    36  		{
    37  			"IPv4 address",
    38  			"prefix 192.168.0.1 suffix",
    39  			"prefix [redacted] suffix",
    40  			false,
    41  		},
    42  		{
    43  			"IPv6 address",
    44  			"prefix 2001:0db8:0000:0000:0000:ff00:0042:8329 suffix",
    45  			"prefix [redacted] suffix",
    46  			false,
    47  		},
    48  		{
    49  			"Remove leading zeros IPv6 address",
    50  			"prefix 2001:db8:0:0:0:ff00:42:8329 suffix",
    51  			"prefix [redacted] suffix",
    52  			false,
    53  		},
    54  		{
    55  			"Omit consecutive zeros sections IPv6 address",
    56  			"prefix 2001:db8::ff00:42:8329 suffix",
    57  			"prefix [redacted] suffix",
    58  			false,
    59  		},
    60  		{
    61  			"IPv4 mapped/translated/embedded address",
    62  			"prefix 0::ffff:192.168.0.1, 0::ffff:0:192.168.0.1, 64:ff9b::192.168.0.1 suffix",
    63  			"prefix [redacted], [redacted], [redacted] suffix",
    64  			false,
    65  		},
    66  		{
    67  			"IPv4 address and port",
    68  			"read tcp 127.0.0.1:1025->127.0.0.1:8000: use of closed network connection",
    69  			"read tcp [redacted]->[redacted]: use of closed network connection",
    70  			false,
    71  		},
    72  		{
    73  			"IPv6 address and port",
    74  			"read tcp [2001:db8::ff00:42:8329]:1025->[2001:db8::ff00:42:8329]:8000: use of closed network connection",
    75  			"read tcp [redacted]->[redacted]: use of closed network connection",
    76  			false,
    77  		},
    78  		{
    79  			"Loopback IPv6 address and invalid port number",
    80  			"dial tcp [::1]:88888: network is unreachable",
    81  			"dial tcp [redacted]: network is unreachable",
    82  			false,
    83  		},
    84  		{
    85  			"Numbers and periods",
    86  			"prefix 192. 168. 0. 1 suffix",
    87  			"prefix 192. 168. 0. 1 suffix",
    88  			false,
    89  		},
    90  		{
    91  			"Hex string and colon",
    92  			"prefix 0123456789abcdef: suffix",
    93  			"prefix 0123456789abcdef: suffix",
    94  			false,
    95  		},
    96  		{
    97  			"Colons",
    98  			"prefix :: suffix",
    99  			"prefix :: suffix",
   100  			false,
   101  		},
   102  		{
   103  			"Notice",
   104  			`{"data":{"SSHClientVersion":"SSH-2.0-C","candidateNumber":0,"diagnosticID":"se0XVQ/4","dialPortNumber":"4000","establishedTunnelsCount":0,"isReplay":false,"networkLatencyMultiplier":2.8284780852763953,"networkType":"WIFI","protocol":"OSSH","region":"US","upstream_ossh_padding":7077},"noticeType":"ConnectedServer","timestamp":"2020-12-16T14:07:02.030Z"}`,
   105  			`{"data":{"SSHClientVersion":"SSH-2.0-C","candidateNumber":0,"diagnosticID":"se0XVQ/4","dialPortNumber":"4000","establishedTunnelsCount":0,"isReplay":false,"networkLatencyMultiplier":2.8284780852763953,"networkType":"WIFI","protocol":"OSSH","region":"US","upstream_ossh_padding":7077},"noticeType":"ConnectedServer","timestamp":"2020-12-16T14:07:02.030Z"}`,
   106  			false,
   107  		},
   108  		{
   109  			"escape IPv4 address and port",
   110  			"prefix 192.168.0.1:443 suffix",
   111  			"prefix 192\\.168\\.0\\.1\\:443 suffix",
   112  			true,
   113  		},
   114  		{
   115  			"escape IPv6 address and port",
   116  			"prefix [2001:db8::ff00:42:8329]:443 suffix",
   117  			"prefix [2001\\:db8\\:\\:ff00\\:42\\:8329]\\:443 suffix",
   118  			true,
   119  		},
   120  	}
   121  
   122  	for _, testCase := range testCases {
   123  		t.Run(testCase.description, func(t *testing.T) {
   124  			input := testCase.input
   125  			if testCase.escape {
   126  				input = EscapeRedactIPAddressString(input)
   127  			}
   128  			output := RedactIPAddressesString(input)
   129  			if output != testCase.expectedOutput {
   130  				t.Errorf("unexpected output: %s", output)
   131  			}
   132  		})
   133  	}
   134  }
   135  
   136  func TestRedactFilePaths(t *testing.T) {
   137  
   138  	testCases := []struct {
   139  		description    string
   140  		input          string
   141  		expectedOutput string
   142  		filePaths      []string
   143  	}{
   144  		{
   145  			"Absolute path",
   146  			"prefix /a suffix",
   147  			"prefix [redacted] suffix",
   148  			nil,
   149  		},
   150  		{
   151  			"Absolute path with directories",
   152  			"prefix /a/b/c/d suffix",
   153  			"prefix [redacted] suffix",
   154  			nil,
   155  		},
   156  		{
   157  			"Relative path 1",
   158  			"prefix ./a/b/c/d suffix",
   159  			"prefix [redacted] suffix",
   160  			nil,
   161  		},
   162  		{
   163  			"Relative path 2",
   164  			"prefix a/b/c/d suffix",
   165  			"prefix [redacted] suffix",
   166  			nil,
   167  		},
   168  		{
   169  			"Relative path 3",
   170  			"prefix ../a/b/c/d/../ suffix",
   171  			"prefix [redacted] suffix",
   172  			nil,
   173  		},
   174  		{
   175  			"File path with home directory tilde",
   176  			"prefix ~/a/b/c/d suffix",
   177  			"prefix [redacted] suffix",
   178  			nil,
   179  		},
   180  		{
   181  			"Multiple file paths",
   182  			"prefix /a/b c/d suffix",
   183  			"prefix [redacted] [redacted] suffix",
   184  			nil,
   185  		},
   186  		{
   187  			"File path with percent encoded spaces",
   188  			"prefix /a/b%20c/d suffix",
   189  			"prefix [redacted] suffix",
   190  			nil,
   191  		},
   192  		{
   193  			"Strip file paths unhandled case",
   194  			"prefix /a/file name with spaces /e/f/g/ suffix",
   195  			"prefix [redacted] name with spaces [redacted] suffix",
   196  			nil,
   197  		},
   198  		{
   199  			"Strip file paths catch unhandled case with provided path",
   200  			"prefix /a/file name with spaces /e/f/g/ suffix",
   201  			"prefix [redacted] [redacted] suffix",
   202  			[]string{"/a/file name with spaces"},
   203  		},
   204  	}
   205  
   206  	for _, testCase := range testCases {
   207  		t.Run(testCase.description, func(t *testing.T) {
   208  			// For convenience replace separators in input string and
   209  			// file paths with the OS-specific path separator here instead
   210  			// constructing the test input strings with os.PathSeparator.
   211  			input := strings.ReplaceAll(testCase.input, "/", string(os.PathSeparator))
   212  			var filePaths []string
   213  			for _, filePath := range testCase.filePaths {
   214  				filePaths = append(filePaths, strings.ReplaceAll(filePath, "/", string(os.PathSeparator)))
   215  			}
   216  			output := RedactFilePaths(input, filePaths...)
   217  			if output != testCase.expectedOutput {
   218  				t.Errorf("unexpected output: %s", output)
   219  			}
   220  		})
   221  	}
   222  }