gnunet-gns-proxy-setup-ca: replace which(1) usage.
[oweals/gnunet.git] / src / gns / gnunet-gns-proxy-setup-ca.in
1 #!/bin/sh
2 #
3 # This shell script will generate an X509 certificate for
4 # your gnunet-gns-proxy and install it (for both GNUnet
5 # and your browser).
6 #
7 # TODO: Implement support for more browsers
8 # TODO: Debug and switch to the new version
9 # TODO  - The only remaining task is fixing the getopts
10 # TODO: Error checks
11 #
12 # The current version partially reuses and recycles
13 # code from build.sh by NetBSD (although not entirely
14 # used because it needs debugging):
15 #
16 # Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
17 # All rights reserved.
18 #
19 # This code is derived from software contributed to
20 # The NetBSD Foundation by Todd Vierling and Luke Mewburn.
21
22 # Redistribution and use in source and binary forms, with or
23 # without modification, are permitted provided that the following
24 # conditions are met:
25 # 1. Redistributions of source code must retain the above
26 #    copyright notice, this list of conditions and the following
27 #    disclaimer.
28 # 2. Redistributions in binary form must reproduce the above
29 #    copyright notice, this list of conditions and the following
30 #    disclaimer in the documentation and/or other materials
31 #    provided with the distribution.
32
33 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
34 # CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 # DISCLAIMED.
38 # IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR
39 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44 # LIABILITY, OR TORT
45 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
46 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
47 # OF SUCH DAMAGE.
48
49 progname=${0##*/}
50
51 setdefaults()
52 {
53     runcmd=
54     #TOP=$( (exec pwd -P 2>/dev/null) || (exec pwd 2>/dev/null) )
55 }
56
57 statusmsg()
58 {
59     ${runcmd} echo "    $@"
60 }
61
62 infomsg()
63 {
64     statusmsg "INFO: $@"
65 }
66
67 warningmsg()
68 {
69     statusmsg "WARNING: $@"
70 }
71
72 errormsg()
73 {
74     statusmsg "ERROR: $@"
75 }
76
77 linemsg()
78 {
79     statusmsg "========================================="
80 }
81
82 # Given a variable name in $1, modify the variable in place
83 # as follows:
84 # Convert possibly-relative path to absolute path by prepending
85 # ${TOP} if necessary.  Also delete trailing "/", if any.
86 resolvepath()
87 {
88     local var="$1"
89     local val
90     eval val=\"\${${var}}\"
91     case "${val}" in
92         /)
93         ;;
94         /*)
95             val="${val%/}"
96             ;;
97         *)
98             val="${TOP}/${val%/}"
99             ;;
100     esac
101     eval ${var}=\"\${val}\"
102 }
103
104 # usage()
105 # {
106 #     if [ -n "$*" ]; then
107 #         echo ""
108 #         echo "${progname}: $*"
109 #     fi
110 #     cat <<_usage_
111
112 # Usage: ${progname} [-fhv] [-c FILE] operation [...]
113
114 # Operations:
115 #    cert               Create the GNS certificate and only insert
116 #               it in GNS.
117 #    browser    Create the GNS certificate, insert it in
118 #               GNS and install it in webbrowsers found.
119 #    all                Create the GNS certificate, insert it in
120 #               GNS and install it in webbrowsers found.
121 #    help               Print this help message.
122
123 # Options:
124 #    -c FILE    Use the configuration file FILE.
125 #    -f         Perform expansions of the variables used in the config
126 #               value of gns-proxy. This will usually expand
127 #               $GNUNET_DATA_HOME to represent its path.
128 #    -h         Print this help message.
129 #    -v         Print the version.
130
131 # _usage_
132 #       exit 1
133 # }
134
135 usage()
136 {
137     if [ -n "$*" ]; then
138         echo ""
139         echo "${progname}: $*"
140     fi
141     cat <<_usage_
142
143 Usage: ${progname} [-hv] [-c FILE] [...]
144
145 Options:
146    -c FILE      Use the configuration file FILE.
147    -h           Print this help message.
148    -v           Print the version and exit.
149    -V           be verbose
150
151 _usage_
152         exit 1
153 }
154
155
156 # parseoptions()
157 # {
158 #     opts=':cfhv'
159 #     # For now use POSIX getopts. For the future, refer to
160 #     # the shell capabilities check build.sh has?
161 #     if type getopts >/dev/null 2>&1; then
162 #         # we are a posix shell, we can use the builtin getopts
163 #         getoptcmd='getopts ${opts} opt && opt=-${opt}'
164 #         optargcmd=':'
165 #         optremcmd='shift $((${OPTIND} -1))'
166 #     fi
167
168 #     # parse command line options.
169 #     while eval ${getoptcmd}; do
170 #         case ${opt} in
171
172 #             -c)
173 #                 eval ${optargcmd}; resolvepath OPTARG
174 #                 GNUNET_CONFIG_FILE="${OPTARG}"
175 #                 export GNUNET_CONFIG_FILE
176 #                 ;;
177 #             -f)
178 #                 GNUNET_PASS_FILENAME=1
179 #                 export GNUNET_PASS_FILENAME
180 #                 ;;
181 #             -v)
182 #                 print_version
183 #                 ;;
184 #             --)
185 #                 break
186 #                 ;;
187 #             -'?'|-h)
188 #                 usage
189 #                 ;;
190 #         esac
191 #     done
192
193 #     # operations
194 #     eval ${optremcmd}
195 #     while [ $# -gt 0 ]; do
196 #         op=$1; shift
197 #         operations="${operations} ${op}"
198 #         case "${op}" in
199 #             help)
200 #                 usage
201 #                 ;;
202 #             all|\
203 #             browser|\
204 #             cert)
205 #                 ;;
206 #             *)
207 #                 usage "Unknown operation \`${op}'"
208 #                 ;;
209 #         esac
210 #         op="$( echo "$op" | tr -s '.-' '__')"
211 #         eval do_${op}=true
212 #     done
213 # }
214     #[ -n "${operations}" ] || usage "Missing operation to perform."
215     # old code:
216     # while getopts "c:" opt; do
217     #     case $opt in
218     #         c)
219     #             options="$options -c $OPTARG"
220     #             ;;
221     #         \?)
222     #             echo "Invalid option: -$OPTARG" >&2
223     #             exit 1
224     #             ;;
225     #         :)
226     #             echo "Option -$OPTARG requires an argument." >&2
227     #             exit 1
228     #             ;;
229     #     esac
230     # done
231
232 generate_ca()
233 {
234     echo ""
235     infomsg "Generating CA"
236     TMPDIR=${TMPDIR:-/tmp}
237     if [ -e "$TMPDIR" ]; then
238         GNSCERT=`mktemp -t ${00##*/}.pem` || exit 1
239         GNSCAKY=`mktemp -t ${00##*/}.pem` || exit 1
240         GNSCANO=`mktemp -t ${00##*/}.pem` || exit 1
241     else
242         # This warning is mostly pointless.
243         warning "You need to export the TMPDIR variable"
244     fi
245     # else
246     #     # SETUP_TMPDIR="$HOME/gns_setup"
247     #     # if [ ! -e "$SETUP_TMPDIR" ]; then
248     #     #     mkdir -p $SETUP_TMPDIR
249     #     # fi
250     #     GNSCERT=`mktemp ${00##*/}.pem` || exit 1
251     #     GNSCAKY=`mktemp ${00##*/}.pem` || exit 1
252     #     GNSCANO=`mktemp ${00##*/}.pem` || exit 1
253     # fi
254
255     # # ------------- gnutls
256     #
257     # if ! which certutil > /dev/null
258     # then
259     #     warningmsg "The 'certutil' command was not found."
260     #     warningmsg "Not importing into browsers."
261     #     warningmsg "For 'certutil' install nss."
262     # else
263     #     # Generate CA key
264     #     # pkcs#8 password-protects key
265     #     certtool --pkcs8 --generate-privkey --sec-param high --outfile ca-key.pem
266     #     # self-sign the CA to create public certificate
267     #     certtool --generate-self-signed --load-privkey ca-key.pem --template ca.cfg --outfile ca.pem
268
269     # ------------- openssl
270
271     OPENSSLCFG=@pkgdatadir@/openssl.cnf
272     if test -z "`openssl version`" > /dev/null
273     then
274         warningmsg "'openssl' command not found. Please install it."
275         infomsg    "Cleaning up."
276         rm -f $GNSCAKY $GNSCANO $GNSCERT
277         exit 1
278     fi
279     if [ -n "${GNUNET_CONFIG}" ]; then
280         GNUNET_CONFIG="-c ${GNUNET_CONFIG_FILE}"
281     else
282         GNUNET_CONFIG=""
283     fi
284     if [ GNUNET_PASS_FILENAME ]; then
285         GNUNET_OPT_F=""
286     else
287         GNUNET_OPT_F=" -f "
288     fi
289     GNS_CA_CERT_PEM=`gnunet-config ${GNUNET_CONFIG} -s gns-proxy -o PROXY_CACERT ${GNUNET_OPT_F} -f ${options}`
290     mkdir -p `dirname $GNS_CA_CERT_PEM`
291
292     # Bad names etc.
293     if [ verbosity ]; then
294         VERBOSE_OUTPUT=""
295     else
296         VERBOSE_OUTPUT="2>/dev/null"
297     fi
298     openssl req -config $OPENSSLCFG -new -x509 -days 3650 -extensions v3_ca -keyout $GNSCAKY -out $GNSCERT -subj "/C=ZZ/L=World/O=GNU/OU=GNUnet/CN=GNS Proxy CA/emailAddress=bounce@gnunet.org" -passout pass:"GNU Name System" ${VERBOSE_OUTPUT}
299
300     statusmsg "Removing passphrase from key"
301     openssl rsa -passin pass:"GNU Name System" -in $GNSCAKY -out $GNSCANO ${VERBOSE_OUTPUT}
302
303     statusmsg "Making private key available to gnunet-gns-proxy"
304     cat $GNSCERT $GNSCANO > $GNS_CA_CERT_PEM
305 }
306
307 importbrowsers()
308 {
309     # Don't check with -H, -H defies any method to not
310     # print the output on screen! Let's hope that every
311     # certutil gets build with some kind of build flags
312     # which end up being printed here:
313     if test -z "`certutil --build-flags`" > /dev/null 2>&1
314     then
315         warningmsg "The 'certutil' command was not found."
316         warningmsg "Not importing into browsers."
317         warningmsg "For 'certutil' install nss."
318     else
319         statusmsg "Importing CA into browsers"
320         # TODO: Error handling?
321         for f in ~/.mozilla/firefox/*.*/
322         do
323             if [ -d $f ]; then
324                 statusmsg "Importing CA into Firefox at $f"
325                 # delete old certificate (if any)
326                 certutil -D -n "GNS Proxy CA" -d "$f" >/dev/null 2>/dev/null
327                 # add new certificate
328                 certutil -A -n "GNS Proxy CA" -t CT,, -d "$f" < $GNSCERT
329             fi
330         done
331         # TODO: Error handling?
332         if [ -d ~/.pki/nssdb/ ]; then
333             statusmsg "Importing CA into Chrome at ~/.pki/nssdb/"
334             # delete old certificate (if any)
335             certutil -D -n "GNS Proxy CA" -d ~/.pki/nssdb/ >/dev/null 2>/dev/null
336             # add new certificate
337             certutil -A -n "GNS Proxy CA" -t CT,, -d ~/.pki/nssdb/ < $GNSCERT
338         fi
339     fi
340 }
341
342 print_version()
343 {
344     GNUNET_ARM_VERSION=`gnunet-arm -v`
345     echo $GNUNET_ARM_VERSION
346 }
347
348 clean_up()
349 {
350     infomsg "Cleaning up."
351     rm -f $GNSCAKY $GNSCANO $GNSCERT
352     if [ -e $SETUP_TMPDIR ]; then
353         rm -rf $SETUP_TMPDIR
354     fi
355
356     linemsg
357     infomsg "You can now start gnunet-gns-proxy."
358     infomsg "Afterwards, configure your browser "
359     infomsg "to use a SOCKS proxy on port 7777. "
360     linemsg
361 }
362
363 main()
364 {
365     while getopts "vhVc:" opt; do
366         case $opt in
367             v)
368                 print_version
369                 exit 0
370                 ;;
371             h)
372                 usage
373                 ;;
374             V)
375                 verbosity=1
376                 ;;
377             c)
378                 options="$options -c $OPTARG"
379                 infomsg "Using configuration file $OPTARG"
380                 ;;
381             \?)
382                 echo "Invalid option: -$OPTARG" >&2
383                 usage
384                 ;;
385             :)
386                 echo "Option -$OPTARG requires an argument." >&2
387                 usage
388                 ;;
389         esac
390     done
391     setdefaults
392     generate_ca
393     importbrowsers
394     clean_up
395
396 # Needs debugging...
397 #    setdefaults
398 #    _args=$@
399 #    parseoptions "$@"
400 #    for op in ${operations}; do
401 #        case "${op}" in
402 #            cert)
403 #                ${runcmd} "${generate_ca}"
404 #                ${runcmd} "${clean_up}"
405 #                ;;
406 #            browser)
407 #                ${runcmd} "${generate_ca}"
408 #                ${runcmd} "${importbrowsers}"
409 #                ${runcmd} "${clean_up}"
410 #                ;;
411 #            all)
412 #                ${runcmd} "${generate_ca}"
413 #                ${runcmd} "${importbrowsers}"
414 #                ${runcmd} "${clean_up}"
415 #                ;;
416 #            *)
417 #                infomsg "Unknown operation \`${op}'"
418 #                ;;
419 #        esac
420 #    done
421 }
422
423 main "$@"