blob: 0078e95450266cd4471c076ed4b11d2f96a8df50 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#!/bin/bash
2
3# oe-git-proxy is a simple tool to be via GIT_PROXY_COMMAND. It uses socat
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05004# 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.
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
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# All rights reserved.
17#
18# AUTHORS
19# Darren Hart <dvhart@linux.intel.com>
20
21# Locate the netcat binary
22SOCAT=$(which socat 2>/dev/null)
23if [ $? -ne 0 ]; then
24 echo "ERROR: socat binary not in PATH" 1>&2
25 exit 1
26fi
27METHOD=""
28
29# Test for a valid IPV4 quad with optional bitmask
30valid_ipv4() {
31 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]))?$"
32 return $?
33}
34
35# Convert an IPV4 address into a 32bit integer
36ipv4_val() {
37 IP="$1"
38 SHIFT=24
39 VAL=0
40 for B in ${IP//./ }; do
41 VAL=$(($VAL+$(($B<<$SHIFT))))
42 SHIFT=$(($SHIFT-8))
43 done
44 echo "$VAL"
45}
46
47# Determine if two IPs are equivalent, or if the CIDR contains the IP
48match_ipv4() {
49 CIDR=$1
50 IP=$2
51
52 if [ -z "${IP%%$CIDR}" ]; then
53 return 0
54 fi
55
56 # Determine the mask bitlength
57 BITS=${CIDR##*/}
Patrick Williamsf1e5d692016-03-30 15:21:19 -050058 [ "$BITS" != "$CIDR" ] || BITS=32
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059 if [ -z "$BITS" ]; then
60 return 1
61 fi
62
63 IPVAL=$(ipv4_val $IP)
64 IP2VAL=$(ipv4_val ${CIDR%%/*})
65
66 # OR in the unmasked bits
67 for i in $(seq 0 $((32-$BITS))); do
68 IP2VAL=$(($IP2VAL|$((1<<$i))))
69 IPVAL=$(($IPVAL|$((1<<$i))))
70 done
71
72 if [ $IPVAL -eq $IP2VAL ]; then
73 return 0
74 fi
75 return 1
76}
77
78# Test to see if GLOB matches HOST
79match_host() {
80 HOST=$1
81 GLOB=$2
82
83 if [ -z "${HOST%%$GLOB}" ]; then
84 return 0
85 fi
86
87 # Match by netmask
88 if valid_ipv4 $GLOB; then
Patrick Williamsc0f7c042017-02-23 20:41:17 -060089 for HOST_IP in $(getent ahostsv4 $HOST | grep ' STREAM ' | cut -d ' ' -f 1) ; do
90 if valid_ipv4 $HOST_IP; then
91 match_ipv4 $GLOB $HOST_IP
92 if [ $? -eq 0 ]; then
93 return 0
94 fi
Patrick Williamsc124f4f2015-09-15 14:41:29 -050095 fi
Patrick Williamsc0f7c042017-02-23 20:41:17 -060096 done
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097 fi
98
99 return 1
100}
101
102# If no proxy is set or needed, just connect directly
103METHOD="TCP:$1:$2"
104
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500105[ -z "${ALL_PROXY}" ] && ALL_PROXY=$all_proxy
106[ -z "${ALL_PROXY}" ] && ALL_PROXY=$http_proxy
107
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500108if [ -z "$ALL_PROXY" ]; then
109 exec $SOCAT STDIO $METHOD
110fi
111
112# Connect directly to hosts in NO_PROXY
113for H in ${NO_PROXY//,/ }; do
114 if match_host $1 $H; then
115 exec $SOCAT STDIO $METHOD
116 fi
117done
118
119# Proxy is necessary, determine protocol, server, and port
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500120# extract protocol
121PROTO=${ALL_PROXY%://*}
122# strip protocol:// from string
123ALL_PROXY=${ALL_PROXY#*://}
124# extract host & port parts:
125# 1) drop username/password
126PROXY=${ALL_PROXY##*@}
127# 2) remove optional trailing /?
128PROXY=${PROXY%%/*}
129# 3) extract optional port
130PORT=${PROXY##*:}
131if [ "$PORT" = "$PROXY" ]; then
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500132 PORT=""
133fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500134# 4) remove port
135PROXY=${PROXY%%:*}
136
137# extract username & password
138PROXYAUTH="${ALL_PROXY%@*}"
139[ "$PROXYAUTH" = "$ALL_PROXY" ] && PROXYAUTH=
140[ -n "${PROXYAUTH}" ] && PROXYAUTH=",proxyauth=${PROXYAUTH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500142if [ "$PROTO" = "socks" ] || [ "$PROTO" = "socks4a" ]; then
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500143 if [ -z "$PORT" ]; then
144 PORT="1080"
145 fi
146 METHOD="SOCKS4A:$PROXY:$1:$2,socksport=$PORT"
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500147elif [ "$PROTO" = "socks4" ]; then
148 if [ -z "$PORT" ]; then
149 PORT="1080"
150 fi
151 METHOD="SOCKS4:$PROXY:$1:$2,socksport=$PORT"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152else
153 # Assume PROXY (http, https, etc)
154 if [ -z "$PORT" ]; then
155 PORT="8080"
156 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500157 METHOD="PROXY:$PROXY:$1:$2,proxyport=${PORT}${PROXYAUTH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500158fi
159
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500160exec $SOCAT STDIO "$METHOD"