Utoljára aktív 2 years ago

evert's Avatar evert gist felülvizsgálása 2 years ago. Revízióhoz ugrás

1 file changed, 616 insertions

ca.sh(fájl létrehozva)

@@ -0,0 +1,616 @@
1 + #!/bin/bash
2 +
3 + # Source: https://jamielinux.com/docs/openssl-certificate-authority/index.html
4 +
5 + if [ -z "$1" ]; then
6 + echo "=x=> Path for your CA root is required!"
7 + exit 1
8 + fi
9 +
10 + CA_ROOT=$(realpath "$1")
11 +
12 + # Intermediate directory
13 + INTERMEDIATE_ROOT="$CA_ROOT/intermediate"
14 +
15 + # Static config blanks
16 +
17 + read -r -d '' OPENSSL_CA_CFG << EOM
18 + # OpenSSL root CA configuration file.
19 + # Auto-generated.
20 +
21 + [ ca ]
22 + # \`man ca\`
23 + default_ca = CA_default
24 +
25 + [ CA_default ]
26 + # Directory and file locations.
27 + dir = $CA_ROOT
28 + certs = \$dir/certs
29 + crl_dir = \$dir/crl
30 + new_certs_dir = \$dir/newcerts
31 + database = \$dir/index.txt
32 + serial = \$dir/serial
33 + RANDFILE = \$dir/private/.rand
34 +
35 + # The root key and root certificate.
36 + private_key = \$dir/private/ca.key.pem
37 + certificate = \$dir/certs/ca.cert.pem
38 +
39 + # For certificate revocation lists.
40 + crlnumber = \$dir/crlnumber
41 + crl = \$dir/crl/ca.crl.pem
42 + crl_extensions = crl_ext
43 + default_crl_days = 30
44 +
45 + # SHA-1 is deprecated, so use SHA-2 instead.
46 + default_md = sha256
47 +
48 + name_opt = ca_default
49 + cert_opt = ca_default
50 + default_days = 375
51 + preserve = no
52 + policy = policy_strict
53 +
54 + [ policy_strict ]
55 + # The root CA should only sign intermediate certificates that match.
56 + # See the POLICY FORMAT section of \`man ca\`.
57 + countryName = match
58 + stateOrProvinceName = match
59 + organizationName = match
60 + organizationalUnitName = optional
61 + commonName = supplied
62 + emailAddress = optional
63 +
64 + [ policy_loose ]
65 + # Allow the intermediate CA to sign a more diverse range of certificates.
66 + # See the POLICY FORMAT section of the \`ca\` man page.
67 + countryName = optional
68 + stateOrProvinceName = optional
69 + localityName = optional
70 + organizationName = optional
71 + organizationalUnitName = optional
72 + commonName = supplied
73 + emailAddress = optional
74 +
75 + [ req ]
76 + # Options for the \`req\` tool (\`man req\`).
77 + default_bits = 4096
78 + distinguished_name = req_distinguished_name
79 + string_mask = utf8only
80 +
81 + # SHA-1 is deprecated, so use SHA-2 instead.
82 + default_md = sha256
83 +
84 + # Extension to add when the -x509 option is used.
85 + x509_extensions = v3_ca
86 +
87 + [ req_distinguished_name ]
88 + # See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
89 + countryName = Country Name (2 letter code)
90 + stateOrProvinceName = State or Province Name
91 + localityName = Locality Name
92 + 0.organizationName = Organization Name
93 + organizationalUnitName = Organizational Unit Name
94 + commonName = Common Name
95 + emailAddress = Email Address
96 +
97 + [ v3_ca ]
98 + # Extensions for a typical CA (\`man x509v3_config\`).
99 + subjectKeyIdentifier = hash
100 + authorityKeyIdentifier = keyid:always,issuer
101 + basicConstraints = critical, CA:true
102 + keyUsage = critical, digitalSignature, cRLSign, keyCertSign
103 +
104 + [ v3_intermediate_ca ]
105 + # Extensions for a typical intermediate CA (\`man x509v3_config\`).
106 + subjectKeyIdentifier = hash
107 + authorityKeyIdentifier = keyid:always,issuer
108 + basicConstraints = critical, CA:true, pathlen:0
109 + keyUsage = critical, digitalSignature, cRLSign, keyCertSign
110 +
111 + [ usr_cert ]
112 + # Extensions for client certificates (\`man x509v3_config\`).
113 + basicConstraints = CA:FALSE
114 + nsCertType = client, email
115 + nsComment = "OpenSSL Generated Client Certificate"
116 + subjectKeyIdentifier = hash
117 + authorityKeyIdentifier = keyid,issuer
118 + keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
119 + extendedKeyUsage = clientAuth, emailProtection
120 +
121 + [ server_cert ]
122 + # Extensions for server certificates (\`man x509v3_config\`).
123 + basicConstraints = CA:FALSE
124 + nsCertType = server
125 + nsComment = "OpenSSL Generated Server Certificate"
126 + subjectKeyIdentifier = hash
127 + authorityKeyIdentifier = keyid,issuer:always
128 + keyUsage = critical, digitalSignature, keyEncipherment
129 + extendedKeyUsage = serverAuth
130 +
131 + [ crl_ext ]
132 + # Extension for CRLs (\`man x509v3_config\`).
133 + authorityKeyIdentifier=keyid:always
134 +
135 + [ ocsp ]
136 + # Extension for OCSP signing certificates (\`man ocsp\`).
137 + basicConstraints = CA:FALSE
138 + subjectKeyIdentifier = hash
139 + authorityKeyIdentifier = keyid,issuer
140 + keyUsage = critical, digitalSignature
141 + extendedKeyUsage = critical, OCSPSigning
142 +
143 + EOM
144 +
145 + read -r -d '' OPENSSL_INTERMEDIATE_CFG << EOM
146 + # OpenSSL intermediate CA configuration file.
147 + # Auto-generated.
148 +
149 + [ ca ]
150 + # \`man ca\`
151 + default_ca = CA_default
152 +
153 + [ CA_default ]
154 + # Directory and file locations.
155 + dir = $INTERMEDIATE_ROOT
156 + certs = \$dir/certs
157 + crl_dir = \$dir/crl
158 + new_certs_dir = \$dir/newcerts
159 + database = \$dir/index.txt
160 + serial = \$dir/serial
161 + RANDFILE = \$dir/private/.rand
162 +
163 + # The root key and root certificate.
164 + private_key = \$dir/private/intermediate.key.pem
165 + certificate = \$dir/certs/intermediate.cert.pem
166 +
167 + # For certificate revocation lists.
168 + crlnumber = \$dir/crlnumber
169 + crl = \$dir/crl/intermediate.crl.pem
170 + crl_extensions = crl_ext
171 + default_crl_days = 30
172 +
173 + # SHA-1 is deprecated, so use SHA-2 instead.
174 + default_md = sha256
175 +
176 + name_opt = ca_default
177 + cert_opt = ca_default
178 + default_days = 375
179 + preserve = no
180 + policy = policy_loose
181 +
182 + # Allow copying extensions from CSRs
183 + copy_extensions = copy
184 +
185 + [ policy_strict ]
186 + # The root CA should only sign intermediate certificates that match.
187 + # See the POLICY FORMAT section of \`man ca\`.
188 + countryName = match
189 + stateOrProvinceName = match
190 + organizationName = match
191 + organizationalUnitName = optional
192 + commonName = supplied
193 + emailAddress = optional
194 +
195 + [ policy_loose ]
196 + # Allow the intermediate CA to sign a more diverse range of certificates.
197 + # See the POLICY FORMAT section of the \`ca\` man page.
198 + countryName = optional
199 + stateOrProvinceName = optional
200 + localityName = optional
201 + organizationName = optional
202 + organizationalUnitName = optional
203 + commonName = supplied
204 + emailAddress = optional
205 +
206 + [ req ]
207 + # Options for the \`req\` tool (\`man req\`).
208 + default_bits = 4096
209 + distinguished_name = req_distinguished_name
210 + string_mask = utf8only
211 +
212 + # SHA-1 is deprecated, so use SHA-2 instead.
213 + default_md = sha256
214 +
215 + # Extension to add when the -x509 option is used.
216 + x509_extensions = v3_intermediate_ca
217 +
218 + [ req_distinguished_name ]
219 + # See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
220 + countryName = Country Name (2 letter code)
221 + stateOrProvinceName = State or Province Name
222 + localityName = Locality Name
223 + 0.organizationName = Organization Name
224 + organizationalUnitName = Organizational Unit Name
225 + commonName = Common Name
226 + emailAddress = Email Address
227 +
228 + [ v3_ca ]
229 + # Extensions for a typical CA (\`man x509v3_config\`).
230 + subjectKeyIdentifier = hash
231 + authorityKeyIdentifier = keyid:always,issuer
232 + basicConstraints = critical, CA:true
233 + keyUsage = critical, digitalSignature, cRLSign, keyCertSign
234 +
235 + [ v3_intermediate_ca ]
236 + # Extensions for a typical intermediate CA (\`man x509v3_config\`).
237 + subjectKeyIdentifier = hash
238 + authorityKeyIdentifier = keyid:always,issuer
239 + basicConstraints = critical, CA:true, pathlen:0
240 + keyUsage = critical, digitalSignature, cRLSign, keyCertSign
241 +
242 + [ usr_cert ]
243 + # Extensions for client certificates (\`man x509v3_config\`).
244 + basicConstraints = CA:FALSE
245 + nsCertType = client, email
246 + nsComment = "OpenSSL Generated Client Certificate"
247 + subjectKeyIdentifier = hash
248 + authorityKeyIdentifier = keyid,issuer
249 + keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
250 + extendedKeyUsage = clientAuth, emailProtection
251 +
252 + [ server_cert ]
253 + # Extensions for server certificates (\`man x509v3_config\`).
254 + basicConstraints = CA:FALSE
255 + nsCertType = server
256 + nsComment = "OpenSSL Generated Server Certificate"
257 + subjectKeyIdentifier = hash
258 + authorityKeyIdentifier = keyid,issuer:always
259 + keyUsage = critical, digitalSignature, keyEncipherment
260 + extendedKeyUsage = serverAuth
261 +
262 + [ crl_ext ]
263 + # Extension for CRLs (\`man x509v3_config\`).
264 + authorityKeyIdentifier=keyid:always
265 +
266 + [ ocsp ]
267 + # Extension for OCSP signing certificates (\`man ocsp\`).
268 + basicConstraints = CA:FALSE
269 + subjectKeyIdentifier = hash
270 + authorityKeyIdentifier = keyid,issuer
271 + keyUsage = critical, digitalSignature
272 + extendedKeyUsage = critical, OCSPSigning
273 +
274 + EOM
275 +
276 + deployFiles () {
277 + echo "Deploying a Certificate Authority to $CA_ROOT"
278 + echo ''
279 +
280 + if [ ! -d "$CA_ROOT" ]; then
281 + # Create directory
282 + mkdir -p "$CA_ROOT"
283 +
284 + # Create sub-directories
285 + mkdir -p "$CA_ROOT/private" "$CA_ROOT/csr" "$CA_ROOT/certs" "$CA_ROOT/newcerts"
286 + touch "$CA_ROOT/index.txt"
287 + echo 1000 > "$CA_ROOT/serial"
288 +
289 + chmod 700 "$CA_ROOT/private"
290 + echo "$OPENSSL_CA_CFG" > "$CA_ROOT/openssl.cfg"
291 + fi
292 +
293 + if [ ! -d "$INTERMEDIATE_ROOT" ]; then
294 + mkdir -p "$INTERMEDIATE_ROOT/private" "$INTERMEDIATE_ROOT/csr" "$INTERMEDIATE_ROOT/certs" "$INTERMEDIATE_ROOT/newcerts"
295 + touch "$INTERMEDIATE_ROOT/index.txt"
296 + echo 1000 > "$INTERMEDIATE_ROOT/serial"
297 +
298 + chmod 700 "$INTERMEDIATE_ROOT/private"
299 + echo "$OPENSSL_INTERMEDIATE_CFG" > "$INTERMEDIATE_ROOT/openssl.cfg"
300 + fi
301 + }
302 +
303 + generateRootPair () {
304 + ############################
305 + # GENERATING ROOT KEY PAIR #
306 + ############################
307 +
308 + echo '==> Starting the generation of the root key pair.'
309 + echo '==> Please fill in the appropriate information asked.'
310 + echo ''
311 +
312 + # Set CWD
313 + cd "$CA_ROOT"
314 +
315 + # CA Root Private Key
316 + if [ ! -e "$CA_ROOT/private/ca.key.pem" ]; then
317 + echo '=> Generating CA key.. Please enter a strong passphrase.'
318 + echo ''
319 + openssl genrsa -aes256 -out private/ca.key.pem 4096
320 + else
321 + echo '=> Root CA key exists, skipping..'
322 + fi
323 +
324 + if [ ! -e "$CA_ROOT/private/ca.key.pem" ]; then
325 + echo '=x=> Root CA key was not generated!'
326 + return 1
327 + fi
328 + chmod 400 private/ca.key.pem
329 +
330 + # CA Root Certificate
331 + if [ ! -e "$CA_ROOT/certs/ca.cert.pem" ]; then
332 + echo '=> Generating CA certificate..'
333 + echo ''
334 + openssl req -config "$CA_ROOT/openssl.cfg" \
335 + -key private/ca.key.pem \
336 + -new -x509 -days 7300 -sha256 -extensions v3_ca \
337 + -out certs/ca.cert.pem
338 + else
339 + echo '=> Root certificate exists, skipping..'
340 + fi
341 +
342 + if [ ! -e "$CA_ROOT/certs/ca.cert.pem" ]; then
343 + echo '=x=> Root certificate was not generated!'
344 + return 1
345 + fi
346 + chmod 444 certs/ca.cert.pem
347 +
348 + # Print info
349 + openssl x509 -noout -text -in certs/ca.cert.pem
350 +
351 + echo '==> Root key pair generated.'
352 + echo ''
353 + }
354 +
355 + generateIntermediate () {
356 + if [ ! -e "$CA_ROOT/certs/ca.cert.pem" ]; then
357 + echo '=x=> Could not generate intermediate certificate.'
358 + echo '=x=> CA certificate is missing!'
359 + return 1
360 + fi
361 +
362 + ####################################
363 + # GENERATING INTERMEDIATE KEY PAIR #
364 + ####################################
365 +
366 + cd "$CA_ROOT"
367 +
368 + echo '==> Starting the generation of the intermediate key pair.'
369 + echo '==> This is used to sign server and user certificates.'
370 + echo '==> Please fill in the appropriate information asked.'
371 + echo ''
372 +
373 + if [ ! -e "$CA_ROOT/intermediate/private/intermediate.key.pem" ]; then
374 + # Key
375 + echo '=> Generating intermediate key.. Please enter a strong passphrase.'
376 + echo ''
377 + openssl genrsa -aes256 \
378 + -out intermediate/private/intermediate.key.pem 4096
379 + else
380 + echo '=> Intermediate certificate key exists, skipping..'
381 + fi
382 +
383 + if [ ! -e "$CA_ROOT/intermediate/private/intermediate.key.pem" ]; then
384 + echo '=x=> Intermediate certificate key was not generated!'
385 + return 1
386 + fi
387 +
388 + chmod 400 intermediate/private/intermediate.key.pem
389 +
390 + if [ -e "$CA_ROOT/intermediate/csr/intermediate.csr.pem" ]; then
391 + rm -f intermediate/csr/intermediate.csr.pem
392 + rm -f intermediate/certs/intermediate.cert.pem
393 + fi
394 +
395 + # Certificate Signing Request (CSR)
396 + echo '=> Generating intermediate CSR..'
397 + echo ''
398 + openssl req -config "$INTERMEDIATE_ROOT/openssl.cfg" -new -sha256 \
399 + -key intermediate/private/intermediate.key.pem \
400 + -out intermediate/csr/intermediate.csr.pem
401 +
402 + if [ ! -e "$CA_ROOT/intermediate/csr/intermediate.csr.pem" ]; then
403 + echo '=x=> Intermediate signing request was not generated!'
404 + return 1
405 + fi
406 +
407 + echo '=> Singing the intermediate certificate. Please answer yes in order to continue.'
408 + echo ''
409 + openssl ca -config "$CA_ROOT/openssl.cfg" -extensions v3_intermediate_ca \
410 + -days 3650 -notext -md sha256 \
411 + -in intermediate/csr/intermediate.csr.pem \
412 + -out intermediate/certs/intermediate.cert.pem
413 +
414 + if [ ! -e "$CA_ROOT/intermediate/certs/intermediate.cert.pem" ]; then
415 + echo '=x=> Intermediate certificate was not signed!'
416 + return 1
417 + fi
418 +
419 + chmod 444 intermediate/certs/intermediate.cert.pem
420 +
421 + # Print info
422 + openssl x509 -noout -text \
423 + -in intermediate/certs/intermediate.cert.pem
424 +
425 + openssl verify -CAfile certs/ca.cert.pem \
426 + intermediate/certs/intermediate.cert.pem
427 +
428 + # Generate Certificate Chain
429 + cat intermediate/certs/intermediate.cert.pem \
430 + certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
431 +
432 + chmod 444 intermediate/certs/ca-chain.cert.pem
433 +
434 + echo '==> Intermediate key pair generated.'
435 + echo "==> Your CA (Certificate Authority) is \"$INTERMEDIATE_ROOT/certs/ca-chain.cert.pem\""
436 + }
437 +
438 + createCertificate() {
439 + if [ ! -e "$CA_ROOT" ]; then
440 + echo "=x=> Certificate root was not found."
441 + return 1
442 + elif [ ! -e "$INTERMEDIATE_ROOT/openssl.cfg" ]; then
443 + echo "=x=> Intermediate certificate configuration was not found."
444 + return 1
445 + fi
446 +
447 + if [ -z "$1" ]; then
448 + echo "=x=> Please provide a name for this certificate."
449 + return 1
450 + fi
451 +
452 + if [ -z "$2" ] || [ "$2" != "server_cert" ] && [ "$2" != "usr_cert" ]; then
453 + echo "=x=> Type must be one of server_cert or usr_cert. If you're unsure about this, use 'usr_cert'."
454 + return 1
455 + fi
456 +
457 + cd "$CA_ROOT"
458 +
459 + # Custom configuration file
460 + local CSRCFG="$INTERMEDIATE_ROOT/openssl.cfg"
461 + if [ -n $3 ]; then
462 + CSRCFG="$3"
463 + fi
464 +
465 + # Generate the key if it does not exist
466 + if [ ! -e "$INTERMEDIATE_ROOT/private/$1.key.pem" ]; then
467 + echo "==> Generating key for \"$1\""
468 + echo ''
469 +
470 + openssl genrsa -out "$INTERMEDIATE_ROOT/private/$1.key.pem" 4096
471 + chmod 400 "$INTERMEDIATE_ROOT/private/$1.key.pem"
472 +
473 + if [ ! -e "$INTERMEDIATE_ROOT/private/$1.key.pem" ]; then
474 + echo "=x=> Key was not created!"
475 + return 1
476 + fi
477 + fi
478 +
479 + echo "==> Generating CSR for \"$1\""
480 + echo ''
481 +
482 + openssl req -config "$CSRCFG" \
483 + -key "$INTERMEDIATE_ROOT/private/$1.key.pem" \
484 + -new -sha256 -out "$INTERMEDIATE_ROOT/csr/$1.csr.pem"
485 +
486 + if [ ! -e "$INTERMEDIATE_ROOT/csr/$1.csr.pem" ]; then
487 + echo "=x=> CSR was not created!"
488 + return 1
489 + fi
490 +
491 + echo "==> Generating certificate for \"$1\""
492 + echo ''
493 +
494 + openssl ca -config "$INTERMEDIATE_ROOT/openssl.cfg" \
495 + -extensions "$2" -days 375 -notext -md sha256 \
496 + -in "$INTERMEDIATE_ROOT/csr/$1.csr.pem" \
497 + -out "$INTERMEDIATE_ROOT/certs/$1.cert.pem"
498 +
499 + if [ ! -e "$INTERMEDIATE_ROOT/certs/$1.cert.pem" ]; then
500 + echo "=x=> Certificate was not created!"
501 + return 1
502 + fi
503 +
504 + chmod 444 "$INTERMEDIATE_ROOT/certs/$1.cert.pem"
505 +
506 + echo "==> Done."
507 + echo "==> Key: $INTERMEDIATE_ROOT/private/$1.key.pem"
508 + echo "==> Cert: $INTERMEDIATE_ROOT/certs/$1.cert.pem"
509 + }
510 +
511 + revokeCertificate() {
512 + if [ ! -e "$CA_ROOT" ]; then
513 + echo "=x=> Certificate root was not found."
514 + return 1
515 + elif [ ! -e "$INTERMEDIATE_ROOT/openssl.cfg" ]; then
516 + echo "=x=> Intermediate certificate configuration was not found."
517 + return 1
518 + fi
519 +
520 + if [ -z "$1" ]; then
521 + echo "=x=> Please provide a name for a certificate to revoke."
522 + return 1
523 + fi
524 +
525 + cd "$CA_ROOT"
526 +
527 + echo "==> Revoking certificate"
528 +
529 + openssl ca -config "$INTERMEDIATE_ROOT/openssl.cfg" \
530 + -revoke "$INTERMEDIATE_ROOT/certs/$1.cert.pem"
531 +
532 + echo "==> Done."
533 + }
534 +
535 + printInfo () {
536 + if [ ! -e "$CA_ROOT" ]; then
537 + echo "=x=> Certificate root was not found."
538 + return 1
539 + elif [ ! -e "$INTERMEDIATE_ROOT/openssl.cfg" ]; then
540 + echo "=x=> Intermediate certificate configuration was not found."
541 + return 1
542 + fi
543 +
544 + if [ -n "$1" ]; then
545 + openssl x509 -noout -text -in "$CA_ROOT/intermediate/certs/$1.cert.pem"
546 + return 0
547 + fi
548 +
549 + echo "=> Root certificate"
550 + openssl x509 -noout -text -in "$CA_ROOT/certs/ca.cert.pem"
551 +
552 + echo "=> Intermediate certificate"
553 + openssl x509 -noout -text \
554 + -in "$CA_ROOT/intermediate/certs/intermediate.cert.pem"
555 +
556 + openssl verify -CAfile "$CA_ROOT/certs/ca.cert.pem" \
557 + "$CA_ROOT/intermediate/certs/intermediate.cert.pem"
558 +
559 + echo ""
560 + echo "==> Paths"
561 + echo "Root: $CA_ROOT"
562 + echo "Intermediate: $CA_ROOT/intermediate"
563 + echo ""
564 +
565 + echo "Root Key: $CA_ROOT/private/ca.key.pem"
566 + echo "Root Cert: $CA_ROOT/certs/ca.cert.pem"
567 +
568 + echo "CA Key: $CA_ROOT/intermediate/private/intermediate.key.pem"
569 + echo "Chain: $CA_ROOT/intermediate/certs/ca-chain.cert.pem"
570 + echo ""
571 + }
572 +
573 + printHelp () {
574 + echo "Usage: ./ca <CA Path> info | wizard | root | intm | revoke [<name>] | new [<name>] [ server_cert | usr_cert ] [ openssl.cfg ]"
575 + echo -e " info\t- Print information about your CA"
576 + echo -e " wizard\t- Create a new CA"
577 + echo -e " root\t- Generate root certificate. For use when wizard fails."
578 + echo -e " intm\t- Generate intermediate certificate. For use when wizard fails."
579 + echo -e " new \t- Create a new certificate signed with your CA. Can also be used for renewal."
580 + echo -e " revoke\t- Revoke a certificate by name"
581 + }
582 +
583 + set -e
584 + case "$2" in
585 + "info")
586 + printInfo $3
587 + ;;
588 + "wizard" | "generate" | "newca")
589 + echo "==> Proceeding with full generation for path $1"
590 + deployFiles
591 + generateRootPair
592 + generateIntermediate
593 + printInfo
594 + ;;
595 + "files")
596 + deployFiles
597 + ;;
598 + "rootpair" | "root")
599 + generateRootPair
600 + ;;
601 + "intermediate" | "intm")
602 + generateIntermediate
603 + ;;
604 + "certificate" | "cert" | "new" | "renew")
605 + createCertificate $3 $4 $5
606 + ;;
607 + "revoke")
608 + revokeCertificate $3
609 + ;;
610 + "help")
611 + printHelp
612 + ;;
613 + *)
614 + echo "Usage: ./ca <CA Path> info | wizard | root | intm | revoke [<name>] | new [<name>] [ server_cert | usr_cert ] [ openssl.cfg ]"
615 + ;;
616 + esac
Újabb Régebbi