xref: /OK3568_Linux_fs/yocto/poky/scripts/oe-git-proxy (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun# oe-git-proxy is a simple tool to be via GIT_PROXY_COMMAND. It uses socat
4*4882a593Smuzhiyun# to make SOCKS5 or HTTPS proxy connections.
5*4882a593Smuzhiyun# It uses ALL_PROXY or all_proxy or http_proxy to determine the proxy server,
6*4882a593Smuzhiyun# protocol, and port.
7*4882a593Smuzhiyun# It uses NO_PROXY to skip using the proxy for a comma delimited list of
8*4882a593Smuzhiyun# hosts, host globs (*.example.com), IPs, or CIDR masks (192.168.1.0/24). It
9*4882a593Smuzhiyun# is known to work with both bash and dash shells.
10*4882a593Smuzhiyun#
11*4882a593Smuzhiyun# Example ALL_PROXY values:
12*4882a593Smuzhiyun# ALL_PROXY=socks://socks.example.com:1080
13*4882a593Smuzhiyun# ALL_PROXY=https://proxy.example.com:8080
14*4882a593Smuzhiyun#
15*4882a593Smuzhiyun# Copyright (c) 2013, Intel Corporation.
16*4882a593Smuzhiyun#
17*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
18*4882a593Smuzhiyun#
19*4882a593Smuzhiyun# AUTHORS
20*4882a593Smuzhiyun# Darren Hart <dvhart@linux.intel.com>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun# disable pathname expansion, NO_PROXY fields could start with "*" or be it
23*4882a593Smuzhiyunset -f
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunif [ $# -lt 2 -o "$1" = '--help' -o "$1" = '-h' ] ; then
26*4882a593Smuzhiyun    echo 'oe-git-proxy: error: the following arguments are required: host port'
27*4882a593Smuzhiyun    echo 'Usage: oe-git-proxy host port'
28*4882a593Smuzhiyun    echo ''
29*4882a593Smuzhiyun    echo 'OpenEmbedded git-proxy - a simple tool to be used via GIT_PROXY_COMMAND.'
30*4882a593Smuzhiyun    echo 'It uses socat to make SOCKS or HTTPS proxy connections.'
31*4882a593Smuzhiyun    echo 'It uses ALL_PROXY to determine the proxy server, protocol, and port.'
32*4882a593Smuzhiyun    echo 'It uses NO_PROXY to skip using the proxy for a comma delimited list'
33*4882a593Smuzhiyun    echo 'of hosts, host globs (*.example.com), IPs, or CIDR masks (192.168.1.0/24).'
34*4882a593Smuzhiyun    echo 'It is known to work with both bash and dash shells.runs native tools'
35*4882a593Smuzhiyun    echo ''
36*4882a593Smuzhiyun    echo 'arguments:'
37*4882a593Smuzhiyun    echo '  host                proxy host to use'
38*4882a593Smuzhiyun    echo '  port                proxy port to use'
39*4882a593Smuzhiyun    echo ''
40*4882a593Smuzhiyun    echo 'options:'
41*4882a593Smuzhiyun    echo '  -h, --help          show this help message and exit'
42*4882a593Smuzhiyun    echo ''
43*4882a593Smuzhiyun    exit 2
44*4882a593Smuzhiyunfi
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun# Locate the netcat binary
47*4882a593Smuzhiyunif [ -z "$SOCAT" ]; then
48*4882a593Smuzhiyun	SOCAT=$(which socat 2>/dev/null)
49*4882a593Smuzhiyun	if [ $? -ne 0 ]; then
50*4882a593Smuzhiyun		echo "ERROR: socat binary not in PATH" 1>&2
51*4882a593Smuzhiyun		exit 1
52*4882a593Smuzhiyun	fi
53*4882a593Smuzhiyunfi
54*4882a593SmuzhiyunMETHOD=""
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun# Test for a valid IPV4 quad with optional bitmask
57*4882a593Smuzhiyunvalid_ipv4() {
58*4882a593Smuzhiyun	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]))?$"
59*4882a593Smuzhiyun	return $?
60*4882a593Smuzhiyun}
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun# Convert an IPV4 address into a 32bit integer
63*4882a593Smuzhiyunipv4_val() {
64*4882a593Smuzhiyun	IP="$1"
65*4882a593Smuzhiyun	SHIFT=24
66*4882a593Smuzhiyun	VAL=0
67*4882a593Smuzhiyun	for B in $( echo "$IP" | tr '.' ' ' ); do
68*4882a593Smuzhiyun		VAL=$(($VAL+$(($B<<$SHIFT))))
69*4882a593Smuzhiyun		SHIFT=$(($SHIFT-8))
70*4882a593Smuzhiyun	done
71*4882a593Smuzhiyun	echo "$VAL"
72*4882a593Smuzhiyun}
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun# Determine if two IPs are equivalent, or if the CIDR contains the IP
75*4882a593Smuzhiyunmatch_ipv4() {
76*4882a593Smuzhiyun	CIDR=$1
77*4882a593Smuzhiyun	IP=$2
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun	if [ -z "${IP%%$CIDR}" ]; then
80*4882a593Smuzhiyun		return 0
81*4882a593Smuzhiyun	fi
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun	# Determine the mask bitlength
84*4882a593Smuzhiyun	BITS=${CIDR##*/}
85*4882a593Smuzhiyun	[ "$BITS" != "$CIDR" ] || BITS=32
86*4882a593Smuzhiyun	if [ -z "$BITS" ]; then
87*4882a593Smuzhiyun		return 1
88*4882a593Smuzhiyun	fi
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun	IPVAL=$(ipv4_val $IP)
91*4882a593Smuzhiyun	IP2VAL=$(ipv4_val ${CIDR%%/*})
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun	# OR in the unmasked bits
94*4882a593Smuzhiyun	for i in $(seq 0 $((32-$BITS))); do
95*4882a593Smuzhiyun		IP2VAL=$(($IP2VAL|$((1<<$i))))
96*4882a593Smuzhiyun		IPVAL=$(($IPVAL|$((1<<$i))))
97*4882a593Smuzhiyun	done
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun	if [ $IPVAL -eq $IP2VAL ]; then
100*4882a593Smuzhiyun		return 0
101*4882a593Smuzhiyun	fi
102*4882a593Smuzhiyun	return 1
103*4882a593Smuzhiyun}
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun# Test to see if GLOB matches HOST
106*4882a593Smuzhiyunmatch_host() {
107*4882a593Smuzhiyun	HOST=$1
108*4882a593Smuzhiyun	GLOB=$2
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun	if [ -z "${HOST%%*$GLOB}" ]; then
111*4882a593Smuzhiyun		return 0
112*4882a593Smuzhiyun	fi
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun	# Match by netmask
115*4882a593Smuzhiyun	if valid_ipv4 $GLOB; then
116*4882a593Smuzhiyun		for HOST_IP in $(getent ahostsv4 $HOST | grep ' STREAM ' | cut -d ' ' -f 1) ; do
117*4882a593Smuzhiyun			if valid_ipv4 $HOST_IP; then
118*4882a593Smuzhiyun				match_ipv4 $GLOB $HOST_IP
119*4882a593Smuzhiyun				if [ $? -eq 0 ]; then
120*4882a593Smuzhiyun					return 0
121*4882a593Smuzhiyun				fi
122*4882a593Smuzhiyun			fi
123*4882a593Smuzhiyun		done
124*4882a593Smuzhiyun	fi
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun	return 1
127*4882a593Smuzhiyun}
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun# If no proxy is set or needed, just connect directly
130*4882a593SmuzhiyunMETHOD="TCP:$1:$2"
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun[ -z "${ALL_PROXY}" ] && ALL_PROXY=$all_proxy
133*4882a593Smuzhiyun[ -z "${ALL_PROXY}" ] && ALL_PROXY=$http_proxy
134*4882a593Smuzhiyun
135*4882a593Smuzhiyunif [ -z "$ALL_PROXY" ]; then
136*4882a593Smuzhiyun	exec $SOCAT STDIO $METHOD
137*4882a593Smuzhiyunfi
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun# Connect directly to hosts in NO_PROXY
140*4882a593Smuzhiyunfor H in $( echo "$NO_PROXY" | tr ',' ' ' ); do
141*4882a593Smuzhiyun	if match_host $1 $H; then
142*4882a593Smuzhiyun		exec $SOCAT STDIO $METHOD
143*4882a593Smuzhiyun	fi
144*4882a593Smuzhiyundone
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun# Proxy is necessary, determine protocol, server, and port
147*4882a593Smuzhiyun# extract protocol
148*4882a593SmuzhiyunPROTO=${ALL_PROXY%://*}
149*4882a593Smuzhiyun# strip protocol:// from string
150*4882a593SmuzhiyunALL_PROXY=${ALL_PROXY#*://}
151*4882a593Smuzhiyun# extract host & port parts:
152*4882a593Smuzhiyun#   1) drop username/password
153*4882a593SmuzhiyunPROXY=${ALL_PROXY##*@}
154*4882a593Smuzhiyun#   2) remove optional trailing /?
155*4882a593SmuzhiyunPROXY=${PROXY%%/*}
156*4882a593Smuzhiyun#   3) extract optional port
157*4882a593SmuzhiyunPORT=${PROXY##*:}
158*4882a593Smuzhiyunif [ "$PORT" = "$PROXY" ]; then
159*4882a593Smuzhiyun	PORT=""
160*4882a593Smuzhiyunfi
161*4882a593Smuzhiyun#   4) remove port
162*4882a593SmuzhiyunPROXY=${PROXY%%:*}
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun# extract username & password
165*4882a593SmuzhiyunPROXYAUTH="${ALL_PROXY%@*}"
166*4882a593Smuzhiyun[ "$PROXYAUTH" = "$ALL_PROXY" ] && PROXYAUTH=
167*4882a593Smuzhiyun[ -n "${PROXYAUTH}" ] && PROXYAUTH=",proxyauth=${PROXYAUTH}"
168*4882a593Smuzhiyun
169*4882a593Smuzhiyunif [ "$PROTO" = "socks" ] || [ "$PROTO" = "socks4a" ]; then
170*4882a593Smuzhiyun	if [ -z "$PORT" ]; then
171*4882a593Smuzhiyun		PORT="1080"
172*4882a593Smuzhiyun	fi
173*4882a593Smuzhiyun	METHOD="SOCKS4A:$PROXY:$1:$2,socksport=$PORT"
174*4882a593Smuzhiyunelif [ "$PROTO" = "socks4" ]; then
175*4882a593Smuzhiyun	if [ -z "$PORT" ]; then
176*4882a593Smuzhiyun		PORT="1080"
177*4882a593Smuzhiyun	fi
178*4882a593Smuzhiyun	METHOD="SOCKS4:$PROXY:$1:$2,socksport=$PORT"
179*4882a593Smuzhiyunelse
180*4882a593Smuzhiyun	# Assume PROXY (http, https, etc)
181*4882a593Smuzhiyun	if [ -z "$PORT" ]; then
182*4882a593Smuzhiyun		PORT="8080"
183*4882a593Smuzhiyun	fi
184*4882a593Smuzhiyun	METHOD="PROXY:$PROXY:$1:$2,proxyport=${PORT}${PROXYAUTH}"
185*4882a593Smuzhiyunfi
186*4882a593Smuzhiyun
187*4882a593Smuzhiyunexec $SOCAT STDIO "$METHOD"
188