aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/oe-git-proxy
blob: d2e9f925b79b96e20d10e9b568a01cfef76a4cf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/bin/bash

# oe-git-proxy is a simple tool to be via GIT_PROXY_COMMAND. It uses socat
# to make SOCKS5 or HTTPS proxy connections. It uses ALL_PROXY to determine the
# proxy server, protocol, and port. It uses NO_PROXY to skip using the proxy for
# a comma delimited list of hosts, host globs (*.example.com), IPs, or CIDR
# masks (192.168.1.0/24). It is known to work with both bash and dash shells.
#
# Example ALL_PROXY values:
# ALL_PROXY=socks://socks.example.com:1080
# ALL_PROXY=https://proxy.example.com:8080
#
# Copyright (c) 2013, Intel Corporation.
# All rights reserved.
#
# AUTHORS
# Darren Hart <dvhart@linux.intel.com>

# Locate the netcat binary
SOCAT=$(which socat 2>/dev/null)
if [ $? -ne 0 ]; then
	echo "ERROR: socat binary not in PATH" 1>&2
	exit 1
fi
METHOD=""

# Test for a valid IPV4 quad with optional bitmask
valid_ipv4() {
	echo $1 | egrep -q "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}(/(3[0-2]|[1-2]?[0-9]))?$"
	return $?
}

# Convert an IPV4 address into a 32bit integer
ipv4_val() {
	IP="$1"
	SHIFT=24
	VAL=0
	for B in ${IP//./ }; do
		VAL=$(($VAL+$(($B<<$SHIFT))))
		SHIFT=$(($SHIFT-8))
	done
	echo "$VAL"
}

# Determine if two IPs are equivalent, or if the CIDR contains the IP
match_ipv4() {
	CIDR=$1
	IP=$2

	if [ -z "${IP%%$CIDR}" ]; then
		return 0
	fi

	# Determine the mask bitlength
	BITS=${CIDR##*/}
	[ "$BITS" != "$CIDR" ] || BITS=32
	if [ -z "$BITS" ]; then
		return 1
	fi

	IPVAL=$(ipv4_val $IP)
	IP2VAL=$(ipv4_val ${CIDR%%/*})

	# OR in the unmasked bits
	for i in $(seq 0 $((32-$BITS))); do
		IP2VAL=$(($IP2VAL|$((1<<$i))))
		IPVAL=$(($IPVAL|$((1<<$i))))
	done

	if [ $IPVAL -eq $IP2VAL ]; then
		return 0
	fi
	return 1
}

# Test to see if GLOB matches HOST
match_host() {
	HOST=$1
	GLOB=$2

	if [ -z "${HOST%%$GLOB}" ]; then
		return 0
	fi

	# Match by netmask
	if valid_ipv4 $GLOB; then
		HOST_IP=$(gethostip -d $HOST)
		if valid_ipv4 $HOST_IP; then
			match_ipv4 $GLOB $HOST_IP
			if [ $? -eq 0 ]; then
				return 0
			fi
		fi
	fi

	return 1
}

# If no proxy is set or needed, just connect directly
METHOD="TCP:$1:$2"

if [ -z "$ALL_PROXY" ]; then
	exec $SOCAT STDIO $METHOD
fi

# Connect directly to hosts in NO_PROXY
for H in ${NO_PROXY//,/ }; do
	if match_host $1 $H; then
		exec $SOCAT STDIO $METHOD
	fi
done

# Proxy is necessary, determine protocol, server, and port
PROTO=$(echo $ALL_PROXY | sed -e 's/\([^:]*\):\/\/.*/\1/')
PROXY=$(echo $ALL_PROXY | sed -e 's/.*:\/\/\([^:]*\).*/\1/')
# For backwards compatibility, this allows the port number to be followed by /?
# in addition to the customary optional /
PORT=$(echo $ALL_PROXY | sed -e 's/.*:\([0-9]*\)\(\/?\?\)\?$/\1/')
if [ "$PORT" = "$ALL_PROXY" ]; then
	PORT=""
fi

if [ "$PROTO" = "socks" ] || [ "$PROTO" = "socks4a" ]; then
	if [ -z "$PORT" ]; then
		PORT="1080"
	fi
	METHOD="SOCKS4A:$PROXY:$1:$2,socksport=$PORT"
elif [ "$PROTO" = "socks4" ]; then
	if [ -z "$PORT" ]; then
		PORT="1080"
	fi
	METHOD="SOCKS4:$PROXY:$1:$2,socksport=$PORT"
else
	# Assume PROXY (http, https, etc)
	if [ -z "$PORT" ]; then
		PORT="8080"
	fi
	METHOD="PROXY:$PROXY:$1:$2,proxyport=$PORT"
fi

exec $SOCAT STDIO $METHOD