Implement OpenFlow statistics in switches and in dpctl.
[sliver-openvswitch.git] / utilities / ofp-pki
1 #! /bin/sh -e
2
3 DIR=pki
4 command=
5 arg1=
6 arg2=
7 prev=
8 force=no
9 batch=no
10 log=ofp-pki.log
11 for option; do
12     # This option-parsing mechanism borrowed from a Autoconf-generated
13     # configure script under the following license:
14
15     # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
16     # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
17     # This configure script is free software; the Free Software Foundation
18     # gives unlimited permission to copy, distribute and modify it.
19
20     # If the previous option needs an argument, assign it.
21     if test -n "$prev"; then
22         eval $prev=\$option
23         prev=
24         continue
25     fi
26     case $option in
27         *=*) optarg=`expr "X$option" : '[^=]*=\(.*\)'` ;;
28         *) optarg=yes ;;
29     esac
30
31     case $dashdash$option in
32         --)
33             dashdash=yes ;;
34         -h|--help)
35             cat <<EOF
36 ofp-pki, for managing a simple OpenFlow public key infrastructure 
37 usage: $0 [OPTION...] COMMAND [ARG...]
38 where the valid commands and their arguments are:
39   new-pki              Create a new PKI
40   req NAME             Create new private key and certificate request
41                        named NAME-privkey.pem and NAME-req.pem, resp.
42                        TYPE is a certificate type: 'switch' or 'controller'
43   sign NAME TYPE       Sign switch certificate request NAME-req.pem,
44                        producing certificate NAME-cert.pem
45                        TYPE is a certificate type: 'switch' or 'controller'
46   req+sign NAME TYPE   Combine the above two steps, producing all three files.
47   verify NAME TYPE     Checks that NAME-cert.pem is a valid TYPE certificate
48                        TYPE is a certificate type: 'switch' or 'controller'
49 The valid OPTIONS are:
50   -d, --dir=DIR        Directory where the PKI is located (default: pki)
51   -f, --force          Continue even if file or directory already exists
52   -b, --batch          Skip fingerprint verification
53   -l, --log=FILE       Log openssl output to FILE (default: ofp-log.log)
54   -h, --help           Print this usage message.
55 EOF
56             exit 0
57             ;;
58         --d*=*)
59             DIR=$optarg
60             ;;
61         --d*|-d)
62             prev=DIR
63             ;;
64         --force|-f)
65             force=yes
66             ;;
67         --batch|-b)
68             batch=yes
69             ;;
70         -*)
71             echo "unrecognized option $option"
72             exit 1
73             ;;
74         *)
75             if test -z "$command"; then
76                 command=$option
77             elif test -z "$arg1"; then
78                 arg1=$option
79             elif test -z "$arg2"; then
80                 arg2=$option
81             else
82                 echo "only two arguments may be specified"
83                 exit 1
84             fi
85             ;;
86     esac
87     shift
88 done
89 if test -n "$prev"; then
90     option=--`echo $prev | sed 's/_/-/g'`
91     { echo "$as_me: error: missing argument to $option" >&2
92         { (exit 1); exit 1; }; }
93 fi
94 if test -z "$command"; then
95     echo "$0: missing command name; use --help for help"
96     exit 1
97 fi
98 exec 3>>$log
99
100 if test "$command" = "new-pki"; then
101     if test -e "$DIR" && test "$force" != "yes"; then
102         echo "$0: $DIR already exists"
103         exit 1
104     fi
105
106     if test ! -d "$DIR"; then
107         mkdir "$DIR"
108     fi
109     cd "$DIR"
110
111     if test ! -e dsaparam.pem; then
112         echo "Generating DSA parameters, please wait..."
113         openssl dsaparam -out dsaparam.pem 2048 1>&3 2>&3
114     fi
115
116     # Create the request configuration.
117     if test ! -e req.cnf; then
118         cat > req.cnf <<EOF
119 [ req ]
120 prompt = no
121 distinguished_name = req_distinguished_name
122
123 [ req_distinguished_name ]
124 C = US
125 ST = CA
126 L = Palo Alto
127 O = OpenFlow
128 OU = OpenFlow certifier
129 CN = OpenFlow certificate
130 EOF
131     fi
132
133     # Create the CAs.
134     for ca in controllerca switchca; do
135         echo "Creating $ca..."
136         oldpwd=$PWD
137         mkdir -p $ca
138         cd $ca
139
140         mkdir -p certs crl newcerts private
141         touch index.txt
142         test -e crlnumber || echo 01 > crlnumber
143         test -e serial || echo 01 > serial
144
145         # Put DSA parameters in directory.
146         if test ! -e dsaparam.pem; then
147             cp ../dsaparam.pem .
148         fi
149
150     # Write CA configuration file.
151         if test ! -e ca.cnf; then
152             cat > ca.cnf <<'EOF'
153 [ req ]
154 prompt = no
155 distinguished_name = req_distinguished_name
156
157 [ req_distinguished_name ]
158 C = US
159 ST = CA
160 L = Palo Alto
161 O = OpenFlow
162 OU = OpenFlow
163 CN = OpenFlow
164
165 [ ca ]
166 default_ca = the_ca
167
168 [ the_ca ]
169 dir            = .                     # top dir
170 database       = $dir/index.txt        # index file.
171 new_certs_dir  = $dir/newcerts         # new certs dir
172 certificate    = $dir/cacert.pem       # The CA cert
173 serial         = $dir/serial           # serial no file
174 private_key    = $dir/private/cakey.pem# CA private key
175 RANDFILE       = $dir/private/.rand    # random number file
176 default_days   = 365                   # how long to certify for
177 default_crl_days= 30                   # how long before next CRL
178 default_md     = md5                   # md to use
179 policy         = policy                # default policy
180 email_in_dn    = no                    # Don't add the email into cert DN
181 name_opt       = ca_default            # Subject name display option
182 cert_opt       = ca_default            # Certificate display option
183 copy_extensions = none                 # Don't copy extensions from request
184
185 # For the CA policy
186 [ policy ]
187 countryName             = optional
188 stateOrProvinceName     = optional
189 organizationName        = match
190 organizationalUnitName  = optional
191 commonName              = supplied
192 emailAddress            = optional
193 EOF
194         fi
195
196         # Create certificate authority.
197         openssl req -config ca.cnf -nodes \
198             -newkey dsa:dsaparam.pem -keyout private/cakey.pem -out careq.pem \
199             1>&3 2>&3
200         openssl ca -config ca.cnf -create_serial -out cacert.pem \
201             -days 1095 -batch -keyfile private/cakey.pem -selfsign \
202             -infiles careq.pem 1>&3 2>&3
203
204         cd "$oldpwd"
205     done
206     exit 0
207 fi
208
209 one_arg() {
210     if test -z "$arg1" || test -n "$arg2"; then
211         echo "$0: $command must have exactly one argument; use --help for help"
212         exit 1
213     fi
214 }
215
216 two_args() {
217     if test -z "$arg1" || test -z "$arg2"; then
218         echo "$0: $command must have exactly two arguments; use --help for help"
219         exit 1
220     fi
221 }
222
223 must_not_exist() {
224     if test -e "$1" && test "$force" != "yes"; then
225         echo "$0: $1 already exists and --force not supplied"
226         exit 1
227     fi
228 }
229
230 fingerprint() {
231     printf "$1-req.pem fingerprint is "
232     sha1sum "$1-req.pem" | awk '{print $1}'
233 }
234
235 check_type() {
236     if test "$1" != switch && test "$1" != controller; then
237         echo "$0: type argument must be 'switch' or 'controller'"
238         exit 1
239     fi
240 }
241
242 must_exist() {
243     if test ! -e "$1"; then
244         echo "$0: $1 does not exist"
245         exit 1
246     fi
247 }
248
249 DIR_must_exist() {
250     if test ! -e "$DIR"; then
251         echo "$0: $DIR does not exist (need to use --dir or new-pki?)"
252         exit 1
253     elif test ! -d "$DIR"; then
254         echo "$0: $DIR is not a directory"
255         exit 1
256     fi
257 }
258
259 make_request() {
260     must_not_exist "$arg1-privkey.pem"
261     must_not_exist "$arg1-req.pem"
262     DIR_must_exist
263     openssl req -config "$DIR/req.cnf" -text -nodes \
264         -newkey "dsa:$DIR/dsaparam.pem" -keyout "$1-privkey.pem" \
265         -out "$1-req.pem" 1>&3 2>&3
266 }
267
268 sign_request() {
269     must_exist "$1-req.pem"
270     must_not_exist "$1-cert.pem"
271     check_type "$2"
272     DIR_must_exist
273     (cd "$DIR/$2ca" && openssl ca -config ca.cnf -batch -in /dev/stdin) \
274         < "$1-req.pem" > "$1-cert.pem.tmp" 2>&3
275     mv "$1-cert.pem.tmp" "$1-cert.pem"
276 }
277
278 if test "$command" = req; then
279     one_arg
280     make_request "$arg1"
281     fingerprint "$arg1"
282 elif test "$command" = sign; then
283     two_args
284     fingerprint "$arg1"
285     if test $batch != yes; then
286         echo "Does fingerprint match? (yes/no)"
287         read answer
288         if test "$answer" != yes; then 
289             echo "Match failure, aborting"
290             exit 1
291         fi
292     fi
293     sign_request "$arg1" "$arg2"
294 elif test "$command" = req+sign; then
295     two_args
296     make_request "$arg1"
297     sign_request "$arg1" "$arg2"
298     fingerprint "$arg1"
299 elif test "$command" = verify; then
300     two_args
301     must_exist "$arg1-cert.pem"
302     check_type "$arg2"
303     DIR_must_exist
304     openssl verify -CAfile "$DIR/${arg2}ca/cacert.pem" "$arg1-cert.pem"
305 else
306     echo "$0: $command command unknown; use --help for help"
307     exit 1
308 fi