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