certificate.sh 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. #!/bin/bash
  2. #------ Settings ------
  3. OPENSSL="openssl"
  4. CONFIG="./openssl.cnf"
  5. ROOTCADAYS="-days 3650" # 10 years
  6. CADAYS="-days 1825" # 5 years
  7. #CADAYS="-days 825" # 2 years
  8. DAYS="-days 397" # 1 year
  9. CONFIGOPTION="-config ${CONFIG}"
  10. REQ="${OPENSSL} req ${CONFIGOPTION}"
  11. CA="${OPENSSL} ca ${CONFIGOPTION}"
  12. VERIFY="${OPENSSL} verify"
  13. X509="${OPENSSL} x509"
  14. PKCS12="${OPENSSL} pkcs12"
  15. CERTFOLDER="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd -P )"
  16. CAFOLDER="./CA"
  17. CAKEY="./cakey.pem"
  18. CAREQ="./careq.pem"
  19. CACERT="./cacert.pem"
  20. PASSEXTENSION="keyfile"
  21. PASSFILE="./${PASSEXTENSION}"
  22. TYPEFILE="./type"
  23. CHAINFILE="./cachain.pem"
  24. CERTBOT="certbot"
  25. #CERTBOT="certbot --staging"
  26. CERTBOTACMEPATH="${CERTFOLDER}/../../certbot"
  27. C="NL"
  28. ST="Noord-Brabant"
  29. L="Veldhoven"
  30. O="Dierkse DataManagement"
  31. OU="Secure Digital Certificate Signing"
  32. #CN="CommonName"
  33. E="certification@dierkse.nl"
  34. #------ Functions ------
  35. execute() {
  36. COMMAND=$@
  37. eval ${COMMAND}
  38. RETURNVALUE=$?
  39. if [ "${RETURNVALUE}" -ne "0" ]; then
  40. exit ${RETURNVALUE}
  41. fi
  42. }
  43. writeRandomString() {
  44. SIZE=$1
  45. FILE=$2
  46. tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' < /dev/urandom | head -c ${SIZE} > "${FILE}"
  47. }
  48. validateType() {
  49. TYPE=$1
  50. VALIDTYPE=""
  51. if [[ "${TYPE}" == "ROOTCA" ||
  52. "${TYPE}" == "INTERMEDIATECA" ||
  53. "${TYPE}" == "VPNCA" ||
  54. "${TYPE}" == "WEBSERVER" ||
  55. "${TYPE}" == "LETSENCRYPT" ||
  56. "${TYPE}" == "WEBCLIENT" ||
  57. "${TYPE}" == "APPLICATIONCLIENT" ||
  58. "${TYPE}" == "EMAIL" ||
  59. "${TYPE}" == "VPN" ]]; then
  60. VALIDTYPE=${TYPE}
  61. fi
  62. }
  63. copyPem() {
  64. INFILE=$1
  65. OUTFILE=$2
  66. BOUND=$3
  67. FLAG=0
  68. if [ ! -f "${INFILE}" ]; then
  69. echo "Missing File ${INFILE}"
  70. exit -1
  71. fi
  72. if [[ -z "$BOUND" ]]; then
  73. echo "Missing Boundary"
  74. exit -1
  75. fi
  76. exec < "${INFILE}";
  77. while read LINE; do
  78. if [ ${FLAG} -eq 1 ]; then
  79. echo ${LINE}|grep "^-----END.*${BOUND}" 2>/dev/null 1>/dev/null
  80. if [ $? -eq 0 ] ; then
  81. echo ${LINE} >> "${OUTFILE}"
  82. break
  83. else
  84. echo ${LINE} >> "${OUTFILE}"
  85. fi
  86. fi
  87. echo ${LINE} | grep "^-----BEGIN.*${BOUND}" 2>/dev/null 1>/dev/null
  88. if [ $? -eq 0 ]; then
  89. echo ${LINE} > "${OUTFILE}"
  90. FLAG=1
  91. fi
  92. done
  93. }
  94. newCertificate() {
  95. KEYBITS=2048
  96. if [ ! -d ${CAFOLDER} ]; then
  97. echo "Missing CA Folder"
  98. exit -1
  99. fi
  100. if [[ "${TYPE}" == "WEBSERVER" ]]; then
  101. EXTENSIONS="server_cert -nodes"
  102. SAN=()
  103. if [ ! -z "${CN}" ]; then
  104. SAN+=("${CN}")
  105. SAN+=("*.${CN}")
  106. fi
  107. SAN+=("${EXTRASAN[@]}")
  108. IP=("${EXTRAIP[@]}")
  109. fi
  110. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  111. EXTENSIONS="server_cert -nodes"
  112. SAN=()
  113. if [ ! -z "${CN}" ]; then
  114. SAN+=("${CN}")
  115. SAN+=("remote.${CN}")
  116. fi
  117. SAN+=("${EXTRASAN[@]}")
  118. fi
  119. if [[ "${TYPE}" == "WEBCLIENT" ]]; then
  120. EXTENSIONS="client_cert -nodes"
  121. fi
  122. if [[ "${TYPE}" == "APPLICATIONCLIENT" ]]; then
  123. EXTENSIONS="application_cert -nodes"
  124. fi
  125. if [[ "${TYPE}" == "EMAIL" ]]; then
  126. EXTENSIONS="email_cert -nodes"
  127. fi
  128. if [[ "${TYPE}" == "VPN" ]]; then
  129. EXTENSIONS="vpn_cert -nodes"
  130. SAN=()
  131. if [ ! -z "${CN}" ]; then
  132. SAN+=("${CN}")
  133. fi
  134. fi
  135. if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
  136. KEYBITS=4096
  137. DAYS=${CADAYS}
  138. EXTENSIONS="intermediate_extensions"
  139. fi
  140. COMMAND="${REQ} -new -x509 -newkey rsa:${KEYBITS} -extensions ${EXTENSIONS} -keyout \"${FILENAME}.key\" -out \"${FILENAME}.crt\" ${DAYS}"
  141. if [ ! -z "${CN}" ]; then
  142. SUBJECT="/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${E}"
  143. COMMAND+=" -subj \"${SUBJECT}\""
  144. fi
  145. if [[ "${TYPE}" == "WEBSERVER" || "${TYPE}" == "LETSENCRYPT"|| "${TYPE}" == "VPN" || ${#SAN[@]} -ne "0" || ${#IP[@]} -ne "0" ]]; then
  146. if [[ ${#SAN[@]} -ne "0" || ${#IP[@]} -ne "0" ]]; then
  147. COMMAND+=" -addext \"subjectAltName="
  148. INDEX=0
  149. for S in "${SAN[@]}"
  150. do
  151. ((INDEX+=1))
  152. COMMAND+="DNS.${INDEX}: ${S},"
  153. done
  154. INDEX=0
  155. for I in "${IP[@]}"
  156. do
  157. ((INDEX+=1))
  158. COMMAND+="IP.${INDEX}: ${I},"
  159. done
  160. COMMAND=${COMMAND%?}
  161. COMMAND+="\""
  162. fi
  163. fi
  164. execute ${COMMAND}
  165. }
  166. newRequest() {
  167. KEYBITS=2048
  168. if [ ! -d ${CAFOLDER} ]; then
  169. echo "Missing CA Folder"
  170. exit -1
  171. fi
  172. if [[ "${TYPE}" == "WEBSERVER" ]]; then
  173. EXTENSIONS="server_cert -nodes"
  174. SAN=()
  175. if [ ! -z "${CN}" ]; then
  176. SAN+=("${CN}")
  177. SAN+=("*.${CN}")
  178. fi
  179. SAN+=("${EXTRASAN[@]}")
  180. IP=("${EXTRAIP[@]}")
  181. fi
  182. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  183. EXTENSIONS="server_cert -nodes"
  184. SAN=()
  185. if [ ! -z "${CN}" ]; then
  186. SAN+=("${CN}")
  187. SAN+=("remote.${CN}")
  188. fi
  189. SAN+=("${EXTRASAN[@]}")
  190. fi
  191. if [[ "${TYPE}" == "WEBCLIENT" ]]; then
  192. EXTENSIONS="client_cert -nodes"
  193. fi
  194. if [[ "${TYPE}" == "APPLICATIONCLIENT" ]]; then
  195. EXTENSIONS="application_cert -nodes"
  196. fi
  197. if [[ "${TYPE}" == "EMAIL" ]]; then
  198. EXTENSIONS="email_cert -nodes"
  199. fi
  200. if [[ "${TYPE}" == "VPN" ]]; then
  201. EXTENSIONS="vpn_cert -nodes"
  202. SAN=()
  203. if [ ! -z "${CN}" ]; then
  204. SAN+=("${CN}")
  205. fi
  206. fi
  207. if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
  208. KEYBITS=4096
  209. writeRandomString 128 "${FILENAME}.${PASSEXTENSION}"
  210. chmod 000 "${FILENAME}.${PASSEXTENSION}"
  211. EXTENSIONS="intermediate_extensions -passout file:\"${FILENAME}.${PASSEXTENSION}\""
  212. fi
  213. COMMAND="${REQ} -new -newkey rsa:${KEYBITS} -extensions ${EXTENSIONS} -keyout \"${FILENAME}.key\" -out \"${FILENAME}.csr\""
  214. if [ ! -z "${CN}" ]; then
  215. SUBJECT="/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${E}"
  216. COMMAND+=" -subj \"${SUBJECT}\""
  217. fi
  218. if [[ "${TYPE}" == "WEBSERVER" || "${TYPE}" == "LETSENCRYPT" || "${TYPE}" == "VPN" || ${#SAN[@]} -ne "0" || ${#IP[@]} -ne "0" ]]; then
  219. if [[ ${#SAN[@]} -ne "0" || ${#IP[@]} -ne "0" ]]; then
  220. COMMAND+=" -addext \"subjectAltName="
  221. INDEX=0
  222. for S in "${SAN[@]}"
  223. do
  224. ((INDEX+=1))
  225. COMMAND+="DNS.${INDEX}: ${S},"
  226. done
  227. INDEX=0
  228. for I in "${IP[@]}"
  229. do
  230. ((INDEX+=1))
  231. COMMAND+="IP.${INDEX}: ${I},"
  232. done
  233. COMMAND=${COMMAND%?}
  234. COMMAND+="\""
  235. fi
  236. fi
  237. execute ${COMMAND}
  238. }
  239. newCertificateAuthority() {
  240. if [[ "${TYPE}" == "ROOTCA" ]]; then
  241. KEYBITS=8192
  242. EXTENSIONS="CA_root"
  243. DAYS=${ROOTCADAYS}
  244. SUBTYPE="INTERMEDIATECA"
  245. fi
  246. if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
  247. KEYBITS=4096
  248. EXTENSIONS="CA_intermediate"
  249. DAYS=${CADAYS}
  250. fi
  251. if [[ "${TYPE}" == "VPNCA" ]]; then
  252. KEYBITS=4096
  253. EXTENSIONS="CA_root"
  254. DAYS=${ROOTCADAYS}
  255. SUBTYPE="VPN"
  256. fi
  257. if [ -z "${KEYBITS}" ]; then
  258. echo "Error: invalid certificate authority type" >&2
  259. exit -1
  260. fi
  261. if [ ! -f ${CAFOLDER}/serial ]; then
  262. mkdir -p ${CAFOLDER}
  263. mkdir -p ${CAFOLDER}/certs
  264. mkdir -p ${CAFOLDER}/crl
  265. mkdir -p ${CAFOLDER}/newcerts
  266. mkdir -p ${CAFOLDER}/private
  267. touch ${CAFOLDER}/index.txt
  268. echo 1000 > ${CAFOLDER}/crl/crlnumber
  269. openssl rand -writerand ${CAFOLDER}/private/.rand
  270. writeRandomString 128 ${CAFOLDER}/private/${PASSFILE}
  271. chmod 000 ${CAFOLDER}/private/${PASSFILE}
  272. if [ ! -z "${SUBTYPE}" ]; then
  273. echo "${SUBTYPE}" > ${CAFOLDER}/${TYPEFILE}
  274. fi
  275. fi
  276. if [ ! -f ${CAFOLDER}/private/${CAKEY} ]; then
  277. if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
  278. echo "CA certificate filename (or enter to create)"
  279. read NAME
  280. fi
  281. if [ "${NAME}" ]; then
  282. if [ -f "./${NAME}" ]; then
  283. NAME="./${NAME%.*}"
  284. else
  285. if [ -f "../${NAME}" ]; then
  286. NAME="../${NAME%.*}"
  287. else
  288. if [ -f "./${NAME}.crt" ]; then
  289. NAME="./${NAME}"
  290. else
  291. if [ -f "../${NAME}.crt" ]; then
  292. NAME="../${NAME}"
  293. else
  294. echo "Certificate not found"
  295. echo " ("./${NAME}")"
  296. echo " ("../${NAME}")"
  297. echo " ("./${NAME}.crt")"
  298. echo " ("../${NAME}.crt")"
  299. echo ""
  300. exit -1
  301. fi
  302. fi
  303. fi
  304. fi
  305. if [ -f "${NAME}.csr" ]; then
  306. copyPem "${NAME}.csr" ${CAFOLDER}/${CAREQ} CERTIFICATE
  307. else
  308. echo "CA Request missing (${NAME}.csr)"
  309. exit -1
  310. fi
  311. if [ -f "${NAME}.key" ]; then
  312. copyPem "${NAME}.key" ${CAFOLDER}/private/${CAKEY} PRIVATE
  313. else
  314. echo "CA Private Key missing (${NAME}.key)"
  315. exit -1
  316. fi
  317. if [ -f "${NAME}.${PASSEXTENSION}" ]; then
  318. cp "${NAME}.${PASSEXTENSION}" ${CAFOLDER}/private/${PASSFILE}
  319. chmod 000 ${CAFOLDER}/private/${PASSFILE}
  320. else
  321. echo "CA Private Key Keyfile missing (${NAME}.${PASSEXTENSION})"
  322. fi
  323. if [ -f "${NAME}.crt" ]; then
  324. copyPem "${NAME}.crt" ${CAFOLDER}/${CACERT} CERTIFICATE
  325. else
  326. echo "CA Certificate missing (${NAME}.crt)"
  327. exit -1
  328. fi
  329. if [ -f "${NAME}.pem" ]; then
  330. COMMAND="cp \"${NAME}.pem\" ${CAFOLDER}/${CHAINFILE}"
  331. execute ${COMMAND}
  332. else
  333. echo "CA Chain missing (${NAME}.pem)"
  334. exit -1
  335. fi
  336. if [ ! -f "${CAFOLDER}/serial" ]; then
  337. COMMAND="$X509 -in ${CAFOLDER}/${CACERT} -noout -next_serial -out ${CAFOLDER}/serial"
  338. execute ${COMMAND}
  339. fi
  340. else
  341. COMMAND="$REQ -new -newkey rsa:${KEYBITS} -passout file:${CAFOLDER}/private/${PASSFILE} -keyout ${CAFOLDER}/private/${CAKEY} -out ${CAFOLDER}/${CAREQ}"
  342. if [ ! -z "${CN}" ]; then
  343. SUBJECT="/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${E}"
  344. COMMAND+=" -subj \"${SUBJECT}\""
  345. fi
  346. execute ${COMMAND}
  347. COMMAND="$CA -create_serial -out ${CAFOLDER}/${CACERT} ${DAYS} -batch -keyfile ${CAFOLDER}/private/${CAKEY} -passin file:${CAFOLDER}/private/${PASSFILE} -selfsign -name ${EXTENSIONS} -infiles ${CAFOLDER}/${CAREQ}"
  348. execute ${COMMAND}
  349. copyPem ${CAFOLDER}/${CACERT} ${CAFOLDER}/${CACERT}.tmp CERTIFICATE
  350. COMMAND="mv ${CAFOLDER}/${CACERT}.tmp ${CAFOLDER}/${CACERT}"
  351. execute ${COMMAND}
  352. COMMAND="cp ${CAFOLDER}/${CACERT} ${CAFOLDER}/${CHAINFILE}"
  353. execute ${COMMAND}
  354. fi
  355. fi
  356. generateCrl
  357. }
  358. renewCertificate() {
  359. revokeCertificate
  360. signRequest
  361. }
  362. renewCertificateAuthorityCertificate() {
  363. # TODO
  364. if [ ! -d ${CAFOLDER} ]; then
  365. echo "Missing CA Folder"
  366. exit -1
  367. fi
  368. echo "Not implemented"
  369. exit -1
  370. }
  371. signCertificate() {
  372. if [ ! -d ${CAFOLDER} ]; then
  373. echo "Missing CA Folder"
  374. exit -1
  375. fi
  376. if [ ! -f "${FILENAME}.csr" ]; then
  377. echo "Missing Certificate Request"
  378. exit -1
  379. fi
  380. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  381. echo "Not implemented"
  382. exit -1
  383. fi
  384. COMMAND="${X509} -x509toreq -signkey \"${FILENAME}.key\" -in \"${FILENAME}.csr\" -out temporary.pem"
  385. execute ${COMMAND}
  386. COMMAND="${CA} -policy policy_anything -passin file:${CAFOLDER}/private/${PASSFILE} ${DAYS} -out \"${FILENAME}.crt\" -infiles temporary.pem"
  387. execute ${COMMAND}
  388. copyPem "${FILENAME}.crt" "${FILENAME}.crt.tmp" CERTIFICATE
  389. COMMAND="mv \"${FILENAME}.crt.tmp\" \"${FILENAME}.crt\""
  390. execute ${COMMAND}
  391. COMMAND="cat \"${FILENAME}.crt\" ${CAFOLDER}/${CHAINFILE} > \"${FILENAME}.pem\""
  392. execute ${COMMAND}
  393. }
  394. signRequest() {
  395. if [ ! -d ${CAFOLDER} ]; then
  396. echo "Missing CA Folder"
  397. exit -1
  398. fi
  399. if [ ! -f "${FILENAME}.csr" ]; then
  400. echo "Missing Certificate Request"
  401. exit -1
  402. fi
  403. if [[ "${TYPE}" == "WEBSERVER" ]]; then
  404. EXTENSIONS="server_cert"
  405. fi
  406. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  407. if [ -f "${FILENAME}.crt" ]; then
  408. echo "Certificate Exists (${FILENAME}.crt)"
  409. exit -1
  410. fi
  411. if [ -f "${FILENAME}.ca.pem" ]; then
  412. echo "Certificate Exists (${FILENAME}.ca.pem)"
  413. exit -1
  414. fi
  415. if [ -f "${FILENAME}.pem" ]; then
  416. echo "Certificate Exists (${FILENAME}.pem)"
  417. exit -1
  418. fi
  419. COMMAND="${CERTBOT} certonly -n --webroot -w ${CERTBOTACMEPATH} --csr \"${FILENAME}.csr\" --cert-path \"${FILENAME}.crt\" --chain-path \"${FILENAME}.ca.pem\" --fullchain-path \"${FILENAME}.pem\" --agree-tos --email ${E}"
  420. execute ${COMMAND}
  421. return
  422. fi
  423. if [[ "${TYPE}" == "WEBCLIENT" ]]; then
  424. EXTENSIONS="client_cert"
  425. fi
  426. if [[ "${TYPE}" == "APPLICATIONCLIENT" ]]; then
  427. EXTENSIONS="application_cert"
  428. fi
  429. if [[ "${TYPE}" == "EMAIL" ]]; then
  430. EXTENSIONS="email_cert"
  431. fi
  432. if [[ "${TYPE}" == "VPN" ]]; then
  433. EXTENSIONS="vpn_cert"
  434. fi
  435. if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
  436. DAYS=${CADAYS}
  437. EXTENSIONS="intermediate_extensions"
  438. fi
  439. COMMAND="${CA} -policy policy_match -passin file:${CAFOLDER}/private/${PASSFILE} -name CA_intermediate -extensions ${EXTENSIONS} ${DAYS} -out \"${FILENAME}.crt\" -infiles \"${FILENAME}.csr\""
  440. execute ${COMMAND}
  441. copyPem "${FILENAME}.crt" "${FILENAME}.crt.tmp" CERTIFICATE
  442. COMMAND="mv \"${FILENAME}.crt.tmp\" \"${FILENAME}.crt\""
  443. execute ${COMMAND}
  444. COMMAND="cat \"${FILENAME}.crt\" ${CAFOLDER}/${CHAINFILE} > \"${FILENAME}.pem\""
  445. execute ${COMMAND}
  446. }
  447. signCertificateAuthorityCertificate() {
  448. # TODO
  449. if [ ! -d ${CAFOLDER} ]; then
  450. echo "Missing CA Folder"
  451. exit -1
  452. fi
  453. # $CA -policy policy_anything -out newcert.pem -extensions v3_ca -infiles newreq.pem
  454. # RET=$?
  455. echo "Not implemented"
  456. exit -1
  457. }
  458. signRequestAnything() {
  459. # TODO
  460. if [ ! -d ${CAFOLDER} ]; then
  461. echo "Missing CA Folder"
  462. exit -1
  463. fi
  464. # $CA -policy policy_anything -infiles newreq.pem
  465. # RET=$?
  466. echo "Not implemented"
  467. exit -1
  468. }
  469. createCertificatePackage() {
  470. if [ ! -d ${CAFOLDER} ]; then
  471. echo "Missing CA Folder"
  472. exit -1
  473. fi
  474. if [ ! -f "${FILENAME}.crt" ]; then
  475. echo "Missing Certificate"
  476. exit -1
  477. fi
  478. if [ ! -f "${FILENAME}.key" ]; then
  479. echo "Missing Private Key"
  480. exit -1
  481. fi
  482. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  483. echo "Not implemented"
  484. exit -1
  485. fi
  486. CACERTCN=$(${X509} -noout -subject -nameopt multiline -in ${CAFOLDER}/${CACERT} | sed -n 's/ *commonName *= //p')
  487. COMMAND="${PKCS12} -in \"${FILENAME}.crt\" -inkey \"${FILENAME}.key\" -certfile ${CAFOLDER}/${CHAINFILE} -caname \"${CACERTCN}\" -out \"${FILENAME}.p12\" -export -name \"${FILENAME}\""
  488. execute ${COMMAND}
  489. }
  490. generateCrl() {
  491. if [ ! -d ${CAFOLDER} ]; then
  492. echo "Missing CA Folder"
  493. exit -1
  494. fi
  495. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  496. echo "Not implemented"
  497. exit -1
  498. fi
  499. COMMAND="${CA} -passin file:${CAFOLDER}/private/${PASSFILE} -gencrl -out ${CAFOLDER}/crl/crl.pem"
  500. execute ${COMMAND}
  501. COMMAND="cat ${CAFOLDER}/${CHAINFILE} ${CAFOLDER}/crl/crl.pem > ${CAFOLDER}/crl/crl_chain.pem"
  502. execute ${COMMAND}
  503. }
  504. revokeCertificate() {
  505. if [ ! -d ${CAFOLDER} ]; then
  506. echo "Missing CA Folder"
  507. exit -1
  508. fi
  509. if [ ! -f "${FILENAME}.crt" ]; then
  510. echo "Missing Certificate"
  511. exit -1
  512. fi
  513. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  514. #COMMAND="${CERTBOT} revoke -n --cert-path \"${FILENAME}.crt\""
  515. #execute ${COMMAND}
  516. COMMAND="mv \"${FILENAME}.crt\" \"${FILENAME}.crt.revoked\""
  517. execute ${COMMAND}
  518. COMMAND="rm -f \"${FILENAME}.pem\" \"${FILENAME}.ca.pem\""
  519. execute ${COMMAND}
  520. return
  521. fi
  522. COMMAND="${CA} -passin file:${CAFOLDER}/private/${PASSFILE} -revoke \"${FILENAME}.crt\""
  523. execute ${COMMAND}
  524. COMMAND="mv \"${FILENAME}.crt\" \"${FILENAME}.crt.revoked\""
  525. execute ${COMMAND}
  526. COMMAND="rm -f \"${FILENAME}.pem\""
  527. execute ${COMMAND}
  528. generateCrl
  529. }
  530. verifyCertificate() {
  531. if [ ! -d ${CAFOLDER} ]; then
  532. echo "Missing CA Folder"
  533. exit -1
  534. fi
  535. if [ ! -f "${FILENAME}.crt" ]; then
  536. echo "Missing Certificate"
  537. exit -1
  538. fi
  539. if [[ "${TYPE}" == "LETSENCRYPT" ]]; then
  540. COMMAND="${VERIFY} \"${FILENAME}.ca.pem\""
  541. execute ${COMMAND}
  542. COMMAND="${VERIFY} -CAfile \"${FILENAME}.ca.pem\" \"${FILENAME}.crt\""
  543. execute ${COMMAND}
  544. #"openssl ocsp -issuer \"${FILENAME}.ca.pem\" -cert \"${FILENAME}.crt\" -text -url http://stg-r3.o.lencr.org"
  545. return
  546. fi
  547. COMMAND="${VERIFY} ${CAFOLDER}/${CHAINFILE}"
  548. execute ${COMMAND}
  549. COMMAND="${VERIFY} -CAfile ${CAFOLDER}/${CHAINFILE} \"${FILENAME}.crt\""
  550. execute ${COMMAND}
  551. COMMAND="${VERIFY} -crl_check -CAfile ${CAFOLDER}/crl/crl_chain.pem \"${FILENAME}.crt\""
  552. execute ${COMMAND}
  553. }
  554. printHelp() {
  555. echo "" >&2
  556. echo "usage: $0 <OPERATION> -t <TYPE> [--san <SAN>] [--ip <IP>] [COMMON NAME]" >&2
  557. echo "" >&2
  558. echo " Certificate Types:" >&2
  559. echo " ROOTCA " >&2
  560. echo " INTERMEDIATECA " >&2
  561. echo " VPNCA " >&2
  562. echo " WEBSERVER " >&2
  563. echo " LETSENCRYPT " >&2
  564. echo " WEBCLIENT " >&2
  565. echo " APPLICATIONCLIENT " >&2
  566. echo " EMAIL " >&2
  567. echo " VPN " >&2
  568. echo "" >&2
  569. echo " Operations:" >&2
  570. echo " -c|--newcert Create a new certificate and private key" >&2
  571. echo " -n|--newreq Create a new certificate request and private key" >&2
  572. echo " --newca Create a new certificate authority" >&2
  573. echo " -r|--renewcert Renew an existing certificate (requires a certificate request)" >&2
  574. #echo " --renewca Renew the certificate authority certificate" >&2
  575. echo " --signcert Sign a certificate with the certificate authority" >&2
  576. echo " -s|--signreq Create and sign a new certificate with the certificate autority" >&2
  577. #echo " --signca Sign the certificate authority certificate" >&2
  578. #echo " --xsign Sign the certificate request with the certificate authority using the 'policy_anything' option" >&2
  579. echo " -p|--pkcs12 Create pkcs12 package containing the certificate and its private key" >&2
  580. echo " --revoke Revoke a certificate" >&2
  581. echo " --crl Generate CRL file" >&2
  582. echo " -v|--verify Verify a certificate" >&2
  583. echo " -h|--help Display this help message" >&2
  584. echo "" >&2
  585. }
  586. #------ Commandline parsing ------
  587. shopt -s nocasematch
  588. EXTRASAN=()
  589. EXTRAIP=()
  590. POSITIONAL=()
  591. while [[ $# -gt 0 ]]; do
  592. key="$1"
  593. case $key in
  594. -t|--type)
  595. validateType ${2}
  596. shift # past argument
  597. shift # past value
  598. ;;
  599. -c|--newcert)
  600. OPERATION="newCertificate"
  601. shift # past argument
  602. ;;
  603. -n|--newreq)
  604. OPERATION="newRequest"
  605. shift # past argument
  606. ;;
  607. --newca)
  608. OPERATION="newCertificateAuthority"
  609. shift # past argument
  610. ;;
  611. -r|--renewcert)
  612. OPERATION="renewCertificate"
  613. shift # past argument
  614. ;;
  615. #--renewca)
  616. # OPERATION="renewCertificateAuthorityCertificate"
  617. #
  618. # shift # past argument
  619. # ;;
  620. --signcert)
  621. OPERATION="signCertificate"
  622. shift # past argument
  623. ;;
  624. -s|--signreq)
  625. OPERATION="signRequest"
  626. shift # past argument
  627. ;;
  628. #--signca)
  629. # OPERATION="signCertificateAuthorityCertificate"
  630. #
  631. # shift # past argument
  632. # ;;
  633. #--xsign)
  634. # OPERATION="signRequestAnything"
  635. #
  636. # shift # past argument
  637. # ;;
  638. -p|--pkcs12)
  639. OPERATION="createCertificatePackage"
  640. shift # past argument
  641. ;;
  642. --revoke)
  643. OPERATION="revokeCertificate"
  644. shift # past argument
  645. ;;
  646. --crl)
  647. OPERATION="generateCrl"
  648. shift # past argument
  649. ;;
  650. -v|--verify)
  651. OPERATION="verifyCertificate"
  652. shift # past argument
  653. ;;
  654. --san)
  655. EXTRASAN+=("$2")
  656. shift # past argument
  657. shift # past value
  658. ;;
  659. --ip)
  660. EXTRAIP+=("$2")
  661. shift # past argument
  662. shift # past value
  663. ;;
  664. -h|--help)
  665. OPERATION="printHelp"
  666. shift # past argument
  667. ;;
  668. *)
  669. POSITIONAL+=("$1")
  670. shift # past argument
  671. ;;
  672. esac
  673. done
  674. FILENAME="newCertificate"
  675. if (( ${#POSITIONAL[@]} )); then
  676. CN=${POSITIONAL[0]}
  677. FILENAME=${CN}
  678. fi
  679. if [[ -z "${TYPE}" &&
  680. -f "${CAFOLDER}/${TYPEFILE}" ]]; then
  681. TYPE=$(<${CAFOLDER}/${TYPEFILE})
  682. validateType ${TYPE}
  683. fi
  684. if [[ -z "${TYPE}" &&
  685. "${OPERATION}" != "revokeCertificate" &&
  686. "${OPERATION}" != "generateCrl" &&
  687. "${OPERATION}" != "verifyCertificate" &&
  688. "${OPERATION}" != "createCertificatePackage" &&
  689. "${OPERATION}" != "printHelp" ]]; then
  690. echo "Error: missing certificate type" >&2
  691. printHelp
  692. exit -1
  693. fi
  694. if [[ ! -z "${TYPE}" &&
  695. -z "${VALIDTYPE}" &&
  696. "${OPERATION}" != "revokeCertificate" &&
  697. "${OPERATION}" != "generateCrl" &&
  698. "${OPERATION}" != "verifyCertificate" &&
  699. "${OPERATION}" != "createCertificatePackage" &&
  700. "${OPERATION}" != "printHelp" ]]; then
  701. echo "Error: invalid certificate type" >&2
  702. printHelp
  703. exit -1
  704. fi
  705. if [ -z "${OPERATION}" ]; then
  706. echo "Error: missing operation" >&2
  707. printHelp
  708. exit -1
  709. fi
  710. TYPE=${VALIDTYPE}
  711. eval ${OPERATION}
  712. exit 0