-
Notifications
You must be signed in to change notification settings - Fork 13
/
index.cgi
125 lines (114 loc) · 2.82 KB
/
index.cgi
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
#!/bin/bash
set -e
d() {
date -u '+%Y/%m/%d %H:%M:%S GMT'
}
badRequest() {
echo "HTTP/1.1 400 Bad Request"
echo "Content-Type: text/plain"
echo
echo "$*"
echo "$*" | sed "s;^;[$(d)] ERROR - ;" >&2
exit 1
}
notFound() {
echo "HTTP/1.1 404 Not Found"
echo "Content-Type: text/plain"
echo
echo "404 Not Found"
exit 1
}
info() {
echo "[$(d)] $*" >&2
}
#1 token
checktoken() {
IFS=":" read -r algo hash <<<"$TOKEN"
[ -z "$hash" ] && echo "Hash algorithm wasn't provided" && return 1
case "$algo" in
md5|sha1|sha256|sha512) check=$(echo -n "$1" | openssl dgst -$algo -r | cut -d' ' -f1) ;;
*) echo "Unsupported algorithm: $algo" && return 1 ;;
esac
[ "$check" != "$hash" ] && echo "Invalid token" && return 1
return 0
}
### sign() exec as a subprocess - do not write HTTP headers
#1 Output
sign() {
local paramOutput=$1
unset dn cn ip ns o days
# No decode, no space from QUERY_STRING
for param in ${QUERY_STRING//&/ }; do
varname="${param%%=*}"
varvalue="${param#*=}"
case "$varname" in
dn) dn=$varvalue ;;
cn) cn=$varvalue ;;
ip) ip=$varvalue ;;
ns) ns=$varvalue ;;
o) o=$varvalue ;;
days) days=$varvalue ;;
token) token=$varvalue ;;
esac
done
[ -n "$TOKEN" ] && ! checktoken "$token" && return 1
[ -n "$cn" -a -n "$dn" ] && echo "Pick either cn or dn" && return 1
[ -z "$dn" -a -n "$cn" ] && dn="/CN=$cn"
for vo in ${o//,/ }; do
dn+="/O=$vo"
done
export RANDFILE=.rnd
exec 100<ca.cnf && \
flock 100 && \
openssl ca \
-batch \
-config ca.cnf \
$([ -n "$dn" ] && echo "-subj $dn" || :) \
-notext \
$([ -n "$days" ] && echo "-days $days" || :) \
-in <(cat -) \
-out "$paramOutput" \
-extfile <(
echo "basicConstraints = CA:FALSE"
echo "keyUsage = nonRepudiation, digitalSignature, keyEncipherment"
echo "extendedKeyUsage = clientAuth$([ -n "$ip$ns" ] && echo ", serverAuth")"
if [ -n "$ip" ] || [ -n "$ns" ]; then
echo "subjectAltName = @alt_names"
echo "[ alt_names ]"
i=1
for alt_ip in ${ip//,/ }; do
echo "IP.${i} = $alt_ip"
((i++))
done
i=1
for alt_ns in ${ns//,/ }; do
echo "DNS.${i} = $alt_ns"
((i++))
done
fi
)
}
# breakdown /<ca_method>[/<ca_id>]
IFS="/" read -r ca_method ca_id <<<"${PATH_INFO#/}"
ca_id="${ca_id:-$CA_DEFAULT}"
grep -Eq ",${ca_id}," <<<",${CA_LIST}," || notFound
cd "$CA_DIR/$ca_id" 2>/dev/null || notFound
case "$ca_method" in
sign)
CRT=/tmp/crt-$$.pem
trap "rm -f $CRT" EXIT
err=$(sign "$CRT" 2>&1) || badRequest "$err"
info "New cert: $(openssl x509 -noout -subject -in $CRT)"
out=$CRT
;;
ca)
out=ca.pem
;;
*)
notFound
;;
esac
echo "HTTP/1.1 200 OK"
echo "Content-Type: text/plain"
echo
cat "$out"