commit d6429d45e5513e8d3ff0cc65ed8a976a79569c04 Author: Rax Date: Tue Dec 23 19:07:02 2025 -0700 First push diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e18ab6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +easy-rsa/keys/*.ovpn +easy-rsa/keys/certs_by_serial/ +easy-rsa/keys/*.pem +easy-rsa/keys/*.crt +easy-rsa/keys/*.cnf +easy-rsa/keys/extensions.temp +easy-rsa/keys/index.* +easy-rsa/keys/serial +easy-rsa/keys/serial.old +easy-rsa/keys/ta.key +easy-rsa/keys/private/ +easy-rsa/keys/issued/ +easy-rsa/keys/renewed/ +easy-rsa/keys/reqs/ +easy-rsa/keys/revoked/ +easy-rsa/keys/crl.jail/etc/openvpn/crl.pem +easy-rsa/x509-types/ + + diff --git a/easy-rsa/easyrsa b/easy-rsa/easyrsa new file mode 100755 index 0000000..5df2c23 --- /dev/null +++ b/easy-rsa/easyrsa @@ -0,0 +1,1714 @@ +#!/bin/sh + +# Easy-RSA 3 -- A Shell-based CA Utility +# +# Copyright (C) 2018 by the Open-Source OpenVPN development community. +# A full list of contributors can be found in the ChangeLog. +# +# This code released under version 2 of the GNU GPL; see COPYING and the +# Licensing/ directory of this project for full licensing details. + +# Help/usage output to stdout +usage() { + # command help: + print " +Easy-RSA 3 usage and overview + +USAGE: easyrsa [options] COMMAND [command-options] + +A list of commands is shown below. To get detailed usage and help for a +command, run: + ./easyrsa help COMMAND + +For a listing of options that can be supplied before the command, use: + ./easyrsa help options + +Here is the list of commands available with a short syntax reminder. Use the +'help' command above to get full usage details. + + init-pki + build-ca [ cmd-opts ] + gen-dh + gen-req [ cmd-opts ] + sign-req + build-client-full [ cmd-opts ] + build-server-full [ cmd-opts ] + revoke [cmd-opts] + renew [cmd-opts] + build-serverClient-full [ cmd-opts ] + gen-crl + update-db + show-req [ cmd-opts ] + show-cert [ cmd-opts ] + show-ca [ cmd-opts ] + import-req + export-p7 [ cmd-opts ] + export-p12 [ cmd-opts ] + set-rsa-pass [ cmd-opts ] + set-ec-pass [ cmd-opts ] +" + + # collect/show dir status: + err_source="Not defined: vars autodetect failed and no value provided" + work_dir="${EASYRSA:-$err_source}" + pki_dir="${EASYRSA_PKI:-$err_source}" + print "\ +DIRECTORY STATUS (commands would take effect on these locations) + EASYRSA: $work_dir + PKI: $pki_dir +" +} # => usage() + +# Detailed command help +# When called with no args, calls usage(), otherwise shows help for a command +cmd_help() { + text="" + opts="" + case "$1" in + init-pki|clean-all) text=" + init-pki [ cmd-opts ] + Removes & re-initializes the PKI dir for a clean PKI" ;; + build-ca) text=" + build-ca [ cmd-opts ] + Creates a new CA" + opts=" + nopass - do not encrypt the CA key (default is encrypted) + subca - create a sub-CA keypair and request (default is a root CA)" ;; + gen-dh) text=" + gen-dh + Generates DH (Diffie-Hellman) parameters" ;; + gen-req) text=" + gen-req [ cmd-opts ] + Generate a standalone keypair and request (CSR) + + This request is suitable for sending to a remote CA for signing." + opts=" + nopass - do not encrypt the private key (default is encrypted)" ;; + sign|sign-req) text=" + sign-req + Sign a certificate request of the defined type. must be a known + type such as 'client', 'server', 'serverClient', or 'ca' (or a user-added type.) + + This request file must exist in the reqs/ dir and have a .req file + extension. See import-req below for importing reqs from other sources." ;; + build|build-client-full|build-server-full|build-serverClient-full) text=" + build-client-full [ cmd-opts ] + build-server-full [ cmd-opts ] + build-serverClient-full [ cmd-opts ] + Generate a keypair and sign locally for a client and/or server + + This mode uses the as the X509 CN." + opts=" + nopass - do not encrypt the private key (default is encrypted)" ;; + revoke) text=" + revoke [reason] + Revoke a certificate specified by the filename_base, with an optional + revocation reason that is one of: + unspecified + keyCompromise + CACompromise + affiliationChanged + superseded + cessationOfOperation + certificateHold";; + renew) text=" + renew [ cmd-opts ] + Renew a certificate specified by the filename_base" + opts=" + nopass - do not encrypt the private key (default is encrypted)" ;; + gen-crl) text=" + gen-crl + Generate a CRL" ;; + update-db) text=" + update-db + Update the index.txt database + + This command will use the system time to update the status of issued + certificates." ;; + show-req|show-cert) text=" + show-req [ cmd-opts ] + show-cert [ cmd-opts ] + Shows details of the req or cert referenced by filename_base + + Human-readable output is shown, including any requested cert options when + showing a request." + opts=" + full - show full req/cert info, including pubkey/sig data" ;; + show-ca) text=" + show-ca [ cmd-opts ] + Shows details of the CA cert + + Human-readable output is shown." + opts=" + full - show full cert info, including pubkey/sig data" ;; + import-req) text=" + import-req + Import a certificate request from a file + + This will copy the specified file into the reqs/ dir in + preparation for signing. + The is the filename base to create. + + Example usage: + import-req /some/where/bob_request.req bob" ;; + export-p12) text=" + export-p12 [ cmd-opts ] + Export a PKCS#12 file with the keypair specified by " + opts=" + noca - do not include the ca.crt file in the PKCS12 output + nokey - do not include the private key in the PKCS12 output" ;; + export-p7) text=" + export-p7 [ cmd-opts ] + Export a PKCS#7 file with the pubkey specified by " + opts=" + noca - do not include the ca.crt file in the PKCS7 output" ;; + set-rsa-pass|set-ec-pass) text=" + set-rsa-pass [ cmd-opts ] + set-ec-pass [ cmd-opts ] + Set a new passphrase on an RSA or EC key for the listed ." + opts=" + nopass - use no password and leave the key unencrypted + file - (advanced) treat the file as a raw path, not a short-name" ;; + altname|subjectaltname|san) text=" + --subject-alt-name=SAN_FORMAT_STRING + This global option adds a subjectAltName to the request or issued + certificate. It MUST be in a valid format accepted by openssl or + req/cert generation will fail. Note that including multiple such names + requires them to be comma-separated; further invocations of this + option will REPLACE the value. + + Examples of the SAN_FORMAT_STRING shown below: + DNS:alternate.example.net + DNS:primary.example.net,DNS:alternate.example.net + IP:203.0.113.29 + email:alternate@example.net" ;; + options) + opt_usage ;; + "") + usage ;; + *) text=" + Unknown command: '$1' (try without commands for a list of commands)" ;; + esac + + # display the help text + print "$text" + [ -n "$opts" ] && print " + cmd-opts is an optional set of command options from this list: +$opts" +} # => cmd_help() + +# Options usage +opt_usage() { + print " +Easy-RSA Global Option Flags + +The following options may be provided before the command. Options specified +at runtime override env-vars and any 'vars' file in use. Unless noted, +non-empty values to options are mandatory. + +General options: + +--batch : set automatic (no-prompts when possible) mode +--pki-dir=DIR : declares the PKI directory +--vars=FILE : define a specific 'vars' file to use for Easy-RSA config + +Certificate & Request options: (these impact cert/req field values) + +--days=# : sets the signing validity to the specified number of days +--digest=ALG : digest to use in the requests & certificates +--dn-mode=MODE : DN mode to use (cn_only or org) +--keysize=# : size in bits of keypair to generate +--req-cn=NAME : default CN to use +--subca-len=# : path length of signed sub-CA certs; must be >= 0 if used +--subject-alt-name : Add a subjectAltName. For more info and syntax, see: + ./easyrsa help altname +--use-algo=ALG : crypto alg to use: choose rsa (default) or ec +--curve=NAME : for elliptic curve, sets the named curve to use +--copy-ext : Copy included request X509 extensions (namely subjAltName + +Organizational DN options: (only used with the 'org' DN mode) + (values may be blank for org DN options) + +--req-c=CC : country code (2-letters) +--req-st=NAME : State/Province +--req-city=NAME : City/Locality +--req-org=NAME : Organization +--req-email=NAME : Email addresses +--req-ou=NAME : Organizational Unit + +Deprecated features: + +--ns-cert=YESNO : yes or no to including deprecated NS extensions +--ns-comment=COMMENT : NS comment to include (value may be blank) +" +} # => opt_usage() + +# Wrapper around printf - clobber print since it's not POSIX anyway +# shellcheck disable=SC1117 +print() { printf "%s\n" "$*"; } + +# Exit fatally with a message to stderr +# present even with EASYRSA_BATCH as these are fatal problems +die() { + print " +Easy-RSA error: + +$1" 1>&2 + clean_temp; + prog_exit "${2:-1}" +} # => die() + +# non-fatal warning output +warn() { + [ ! "$EASYRSA_BATCH" ] && \ + print " +$1" 1>&2 +} # => warn() + +# informational notices to stdout +notice() { + [ ! "$EASYRSA_BATCH" ] && \ + print " +$1" +} # => notice() + +# yes/no case-insensitive match (operates on stdin pipe) +# Returns 0 when input contains yes, 1 for no, 2 for no match +# If both strings are present, returns 1; first matching line returns. +awk_yesno() { + #shellcheck disable=SC2016 + awkscript=' +BEGIN {IGNORECASE=1; r=2} +{ if(match($0,"no")) {r=1; exit} + if(match($0,"yes")) {r=0; exit} +} END {exit r}' + awk "$awkscript" +} # => awk_yesno() + +# intent confirmation helper func +# returns without prompting in EASYRSA_BATCH +confirm() { + [ "$EASYRSA_BATCH" ] && return + prompt="$1" + value="$2" + msg="$3" + input="" + print " +$msg + +Type the word '$value' to continue, or any other input to abort." + printf %s " $prompt" + #shellcheck disable=SC2162 + read input + [ "$input" = "$value" ] && return + notice "Aborting without confirmation." + exit 9 +} # => confirm() + +# remove temp files +clean_temp() { + for f in "$EASYRSA_TEMP_CONF" "$EASYRSA_TEMP_EXT" \ + "$EASYRSA_TEMP_FILE_2" "$EASYRSA_TEMP_FILE_3" "$EASYRSA_TEMP_FILE_4" + do [ -f "$f" ] && rm "$f" 2>/dev/null + done +} # => clean_temp() + +prog_exit() { + ESTAT=0 + [ -n "$1" ] && ESTAT=$1 + (stty echo 2>/dev/null) || set -o echo + echo "" # just to get a clean line + exit "$ESTAT" +} # => prog_exit() + +# Make LibreSSL safe config file from OpenSSL config file +make_ssl_config() { +sed \ + -e "s\`ENV::EASYRSA\`EASYRSA\`g" \ + -e "s\`\$dir\`$EASYRSA_PKI\`g" \ + -e "s\`\$EASYRSA_PKI\`$EASYRSA_PKI\`g" \ + -e "s\`\$EASYRSA_CERT_EXPIRE\`$EASYRSA_CERT_EXPIRE\`g" \ + -e "s\`\$EASYRSA_CRL_DAYS\`$EASYRSA_CRL_DAYS\`g" \ + -e "s\`\$EASYRSA_DIGEST\`$EASYRSA_DIGEST\`g" \ + -e "s\`\$EASYRSA_KEY_SIZE\`$EASYRSA_KEY_SIZE\`g" \ + -e "s\`\$EASYRSA_DIGEST\`$EASYRSA_DIGEST\`g" \ + -e "s\`\$EASYRSA_DN\`$EASYRSA_DN\`g" \ + -e "s\`\$EASYRSA_REQ_COUNTRY\`$EASYRSA_REQ_COUNTRY\`g" \ + -e "s\`\$EASYRSA_REQ_PROVINCE\`$EASYRSA_REQ_PROVINCE\`g" \ + -e "s\`\$EASYRSA_REQ_CITY\`$EASYRSA_REQ_CITY\`g" \ + -e "s\`\$EASYRSA_REQ_ORG\`$EASYRSA_REQ_ORG\`g" \ + -e "s\`\$EASYRSA_REQ_OU\`$EASYRSA_REQ_OU\`g" \ + -e "s\`\$EASYRSA_REQ_CN\`$EASYRSA_REQ_CN\`g" \ + -e "s\`\$EASYRSA_REQ_EMAIL\`$EASYRSA_REQ_EMAIL\`g" \ + "$EASYRSA_SSL_CONF" > "$EASYRSA_SAFE_CONF" || die "\ +Failed to update $EASYRSA_SAFE_CONF" +} # => make_ssl_config() + +vars_source_check() { + # Check for defined EASYRSA_PKI + [ -n "$EASYRSA_PKI" ] || die "\ +EASYRSA_PKI env-var undefined" +} # => vars_source_check() + +# Verify supplied curve exists and generate curve file if needed +verify_curve() { + if ! "$EASYRSA_OPENSSL" ecparam -name "$EASYRSA_CURVE" > /dev/null; then + die "\ +Curve $EASYRSA_CURVE not found. Run openssl ecparam -list_curves to show a +list of supported curves." + fi + + # Check that the ecparams dir exists + [ -d "$EASYRSA_EC_DIR" ] || mkdir "$EASYRSA_EC_DIR" || die "\ +Failed creating ecparams dir (permissions?) at: +$EASYRSA_EC_DIR" + + # Check that the required ecparams file exists + out="$EASYRSA_EC_DIR/${EASYRSA_CURVE}.pem" + [ -f "$out" ] && return 0 + "$EASYRSA_OPENSSL" ecparam -name "$EASYRSA_CURVE" -out "$out" || die "\ +Failed to generate ecparam file (permissions?) when writing to: +$out" + + # Explicitly return success for caller + return 0 +} + +verify_ssl_lib () { + # make safessl-easyrsa.cnf + make_ssl_config + + # Verify EASYRSA_OPENSSL command gives expected output + if [ -z "$EASYRSA_SSL_OK" ]; then + val="$("$EASYRSA_OPENSSL" version)" + case "${val%% *}" in + OpenSSL|LibreSSL) + notice "\ +Using SSL: $EASYRSA_OPENSSL $("$EASYRSA_OPENSSL" version)" ;; + *) die "\ +Missing or invalid OpenSSL +Expected to find openssl command at: $EASYRSA_OPENSSL" ;; + esac + fi + EASYRSA_SSL_OK=1 + + # Verify EASYRSA_SSL_CONF file exists + [ -f "$EASYRSA_SSL_CONF" ] || die "\ +The OpenSSL config file cannot be found. +Expected location: $EASYRSA_SSL_CONF" +} # => verify_ssl_lib () + +# Basic sanity-check of PKI init and complain if missing +verify_pki_init() { + help_note="Run easyrsa without commands for usage and command help." + + # check that the pki dir exists + vars_source_check + [ -d "$EASYRSA_PKI" ] || die "\ +EASYRSA_PKI does not exist (perhaps you need to run init-pki)? +Expected to find the EASYRSA_PKI at: $EASYRSA_PKI +$help_note" + + # verify expected dirs present: + for i in private reqs; do + [ -d "$EASYRSA_PKI/$i" ] || die "\ +Missing expected directory: $i (perhaps you need to run init-pki?) +$help_note" + done + + # verify ssl lib + verify_ssl_lib +} # => verify_pki_init() + +# Verify core CA files present +verify_ca_init() { + help_note="Run without commands for usage and command help." + + # First check the PKI has been initialized + verify_pki_init + + # verify expected files present: + for i in serial index.txt ca.crt private/ca.key; do + if [ ! -f "$EASYRSA_PKI/$i" ]; then + [ "$1" = "test" ] && return 1 + die "\ +Missing expected CA file: $i (perhaps you need to run build-ca?) +$help_note" + fi + done + + # When operating in 'test' mode, return success. + # test callers don't care about CA-specific dir structure + [ "$1" = "test" ] && return 0 + + # verify expected CA-specific dirs: + for i in issued certs_by_serial \ + revoked/certs_by_serial revoked/private_by_serial revoked/reqs_by_serial \ + renewed/certs_by_serial renewed/private_by_serial renewed/reqs_by_serial ; + do + [ -d "$EASYRSA_PKI/$i" ] || die "\ +Missing expected CA dir: $i (perhaps you need to run build-ca?) +$help_note" + done + + # explicitly return success for callers + return 0 + +} # => verify_ca_init() + +# init-pki backend: +init_pki() { + + # If EASYRSA_PKI exists, confirm before we rm -rf (skiped with EASYRSA_BATCH) + if [ -e "$EASYRSA_PKI" ]; then + confirm "Confirm removal: " "yes" " +WARNING!!! + +You are about to remove the EASYRSA_PKI at: $EASYRSA_PKI +and initialize a fresh PKI here." + # now remove it: + rm -rf "$EASYRSA_PKI" || die "Removal of PKI dir failed. Check/correct errors above" + fi + + # new dirs: + for i in private reqs; do + mkdir -p "$EASYRSA_PKI/$i" || die "Failed to create PKI file structure (permissions?)" + done + + if [ ! -f "$EASYRSA_SSL_CONF" ] && [ -f "$EASYRSA/openssl-easyrsa.cnf" ]; + then + cp "$EASYRSA/openssl-easyrsa.cnf" "$EASYRSA_SSL_CONF" + fi + + notice "\ +init-pki complete; you may now create a CA or requests. +Your newly created PKI dir is: $EASYRSA_PKI +" + return 0 +} # => init_pki() + +hide_read_pass() +{ + (stty -echo 2>/dev/null) || set +o echo + read -r "$@" + (stty echo 2>/dev/null) || set -o echo +} # => hide_read_pass() + +# build-ca backend: +build_ca() { + opts="" + sub_ca="" + nopass="" + crypto="-aes256" + crypto_opts="" + while [ -n "$1" ]; do + case "$1" in + subca) sub_ca=1 ;; + nopass) nopass=1 ;; + *) warn "Ignoring unknown command option: '$1'" ;; + esac + shift + done + + verify_pki_init + [ "$EASYRSA_ALGO" = "ec" ] && verify_curve + + # setup for the simpler sub-CA situation and overwrite with root-CA if needed: + out_file="$EASYRSA_PKI/reqs/ca.req" + out_key="$EASYRSA_PKI/private/ca.key" + if [ ! $sub_ca ]; then + out_file="$EASYRSA_PKI/ca.crt" + opts="$opts -x509 -days $EASYRSA_CA_EXPIRE " + fi + + # Test for existing CA, and complain if already present + if verify_ca_init test; then + die "\ +Unable to create a CA as you already seem to have one set up. +If you intended to start a new CA, run init-pki first." + fi + # If a private key exists here, a sub-ca was created but not signed. + # Notify the user and require a signed ca.crt or a init-pki: + [ -f "$out_key" ] && \ + die "\ +A CA private key exists but no ca.crt is found in your PKI dir of: +$EASYRSA_PKI +Refusing to create a new CA keypair as this operation would overwrite your +current CA keypair. If you intended to start a new CA, run init-pki first." + + # create necessary files and dirs: + err_file="Unable to create necessary PKI files (permissions?)" + for i in issued certs_by_serial \ + revoked/certs_by_serial revoked/private_by_serial revoked/reqs_by_serial \ + renewed/certs_by_serial renewed/private_by_serial renewed/reqs_by_serial; + do + mkdir -p "$EASYRSA_PKI/$i" || die "$err_file" + done + printf "" > "$EASYRSA_PKI/index.txt" || die "$err_file" + print "01" > "$EASYRSA_PKI/serial" || die "$err_file" + + # Default CN only when not in global EASYRSA_BATCH mode: + # shellcheck disable=SC2015 + [ "$EASYRSA_BATCH" ] && opts="$opts -batch" || export EASYRSA_REQ_CN="Easy-RSA CA" + + out_key_tmp="$(mktemp "$out_key.XXXXXXXXXX")"; EASYRSA_TEMP_FILE_2="$out_key_tmp" + out_file_tmp="$(mktemp "$out_file.XXXXXXXXXX")"; EASYRSA_TEMP_FILE_3="$out_file_tmp" + # Get password from user if necessary + if [ ! $nopass ]; then + out_key_pass_tmp="$(mktemp)"; EASYRSA_TEMP_FILE_4="$out_key_pass_tmp" + echo + printf "Enter New CA Key Passphrase: " + hide_read_pass kpass + echo + printf "Re-Enter New CA Key Passphrase: " + hide_read_pass kpass2 + echo + # shellcheck disable=2154 + if [ "$kpass" = "$kpass2" ]; + then + printf "%s" "$kpass" > "$out_key_pass_tmp" + else + die "Passphrases do not match." + fi + fi + + # create the CA key using AES256 + [ ! $nopass ] && crypto_opts="$crypto -passout file:$out_key_pass_tmp" + if [ "$EASYRSA_ALGO" = "rsa" ]; then + #shellcheck disable=SC2086 + "$EASYRSA_OPENSSL" genrsa -out "$out_key_tmp" $crypto_opts "$EASYRSA_ALGO_PARAMS" + elif [ "$EASYRSA_ALGO" = "ec" ]; then + #shellcheck disable=SC2086 + "$EASYRSA_OPENSSL" ecparam -in "$EASYRSA_ALGO_PARAMS" -genkey | \ + "$EASYRSA_OPENSSL" ec -out "$out_key_tmp" $crypto_opts + fi + + # make safessl-easyrsa.cnf + make_ssl_config + + # create the CA keypair: + [ ! $nopass ] && crypto_opts="-passin file:$out_key_pass_tmp" + #shellcheck disable=SC2086 + "$EASYRSA_OPENSSL" req -utf8 -new -key "$out_key_tmp" \ + -config "$EASYRSA_SAFE_CONF" -keyout "$out_key_tmp" -out "$out_file_tmp" $crypto_opts $opts || \ + die "Failed to build the CA" + + mv "$out_key_tmp" "$out_key"; EASYRSA_TEMP_FILE_2= + mv "$out_file_tmp" "$out_file"; EASYRSA_TEMP_FILE_3= + [ -f "$out_key_pass_tmp" ] && rm "$out_key_pass_tmp" && EASYRSA_TEMP_FILE_4= + + # Success messages + if [ $sub_ca ]; then + notice "\ +NOTE: Your sub-CA request is at $out_file +and now must be sent to your parent CA for signing. Place your resulting cert +at $EASYRSA_PKI/ca.crt prior to signing operations. +" + else notice "\ +CA creation complete and you may now import and sign cert requests. +Your new CA certificate file for publishing is at: +$out_file +" + fi + return 0 +} # => build_ca() + +# gen-dh backend: +gen_dh() { + verify_pki_init + + out_file="$EASYRSA_PKI/dh.pem" + "$EASYRSA_OPENSSL" dhparam -out "$out_file" "$EASYRSA_KEY_SIZE" || \ + die "Failed to build DH params" + notice "\ +DH parameters of size $EASYRSA_KEY_SIZE created at $out_file +" + return 0 +} # => gen_dh() + +# gen-req backend: +gen_req() { + # pull filename base and use as default interactive CommonName: + [ -n "$1" ] || die "\ +Error: gen-req must have a file base as the first argument. +Run easyrsa without commands for usage and commands." + key_out="$EASYRSA_PKI/private/$1.key" + req_out="$EASYRSA_PKI/reqs/$1.req" + [ ! "$EASYRSA_BATCH" ] && EASYRSA_REQ_CN="$1" + shift + + # function opts support + opts= + while [ -n "$1" ]; do + case "$1" in + nopass) opts="$opts -nodes" ;; + # batch flag supports internal callers needing silent operation + batch) EASYRSA_BATCH=1 ;; + *) warn "Ignoring unknown command option: '$1'" ;; + esac + shift + done + + verify_pki_init + [ "$EASYRSA_ALGO" = "ec" ] && verify_curve + + # don't wipe out an existing private key without confirmation + [ -f "$key_out" ] && confirm "Confirm key overwrite: " "yes" "\ + +WARNING!!! + +An existing private key was found at $key_out +Continuing with key generation will replace this key." + + # When EASYRSA_EXTRA_EXTS is defined, append it to openssl's [req] section: + if [ -n "$EASYRSA_EXTRA_EXTS" ]; then + # Setup & insert the extra ext data keyed by a magic line + extra_exts=" +req_extensions = req_extra +[ req_extra ] +$EASYRSA_EXTRA_EXTS" + #shellcheck disable=SC2016 + awkscript=' +{if ( match($0, "^#%EXTRA_EXTS%") ) + { while ( getline<"/dev/stdin" ) {print} next } + {print} +}' + print "$extra_exts" | \ + awk "$awkscript" "$EASYRSA_SSL_CONF" \ + > "$EASYRSA_TEMP_CONF" \ + || die "Copying SSL config to temp file failed" + # Use this new SSL config for the rest of this function + EASYRSA_SSL_CONF="$EASYRSA_TEMP_CONF" + fi + + # make safessl-easyrsa.cnf + make_ssl_config + + key_out_tmp="$(mktemp "$key_out.XXXXXXXXXX")"; EASYRSA_TEMP_FILE_2="$key_out_tmp" + req_out_tmp="$(mktemp "$req_out.XXXXXXXXXX")"; EASYRSA_TEMP_FILE_3="$req_out_tmp" + # generate request + [ $EASYRSA_BATCH ] && opts="$opts -batch" + # shellcheck disable=2086,2148 + "$EASYRSA_OPENSSL" req -utf8 -new -newkey "$EASYRSA_ALGO":"$EASYRSA_ALGO_PARAMS" \ + -config "$EASYRSA_SAFE_CONF" -keyout "$key_out_tmp" -out "$req_out_tmp" $opts \ + || die "Failed to generate request" + mv "$key_out_tmp" "$key_out"; EASYRSA_TEMP_FILE_2= + mv "$req_out_tmp" "$req_out"; EASYRSA_TEMP_FILE_3= + notice "\ +Keypair and certificate request completed. Your files are: +req: $req_out +key: $key_out +" + return 0 +} # => gen_req() + +# common signing backend +sign_req() { + crt_type="$1" + opts="" + req_in="$EASYRSA_PKI/reqs/$2.req" + crt_out="$EASYRSA_PKI/issued/$2.crt" + + # Randomize Serial number + i="" + serial="" + check_serial="" + for i in 1 2 3 4 5; do + "$EASYRSA_OPENSSL" rand -hex -out "$EASYRSA_PKI/serial" 16 + serial="$(cat "$EASYRSA_PKI/serial")" + check_serial="$("$EASYRSA_OPENSSL" ca -config "$EASYRSA_SSL_CONF" -status "$serial" 2>&1)" + case "$check_serial" in + *"not present in db"*) break ;; + *) continue ;; + esac + done + + # Support batch by internal caller: + [ "$3" = "batch" ] && EASYRSA_BATCH=1 + + verify_ca_init + + # Check argument sanity: + [ -n "$2" ] || die "\ +Incorrect number of arguments provided to sign-req: +expected 2, got $# (see command help for usage)" + + # Cert type must exist under the EASYRSA_EXT_DIR + [ -r "$EASYRSA_EXT_DIR/$crt_type" ] || die "\ +Unknown cert type '$crt_type'" + + # Request file must exist + [ -f "$req_in" ] || die "\ +No request found for the input: '$2' +Expected to find the request at: $req_in" + + # Confirm input is a cert req + verify_file req "$req_in" || die "\ +The certificate request file is not in a valid X509 request format. +Offending file: $req_in" + + # Display the request subject in an easy-to-read format + # Confirm the user wishes to sign this request + confirm "Confirm request details: " "yes" " +You are about to sign the following certificate. +Please check over the details shown below for accuracy. Note that this request +has not been cryptographically verified. Please be sure it came from a trusted +source or that you have verified the request checksum with the sender. + +Request subject, to be signed as a $crt_type certificate for $EASYRSA_CERT_EXPIRE days: + +$(display_dn req "$req_in") +" # => confirm end + + # Generate the extensions file for this cert: + { + # Append first any COMMON file (if present) then the cert-type extensions + cat "$EASYRSA_EXT_DIR/COMMON" + cat "$EASYRSA_EXT_DIR/$crt_type" + # copy req extensions + [ "$EASYRSA_CP_EXT" ] && print "copy_extensions = copy" + + # Support a dynamic CA path length when present: + [ "$crt_type" = "ca" ] && [ -n "$EASYRSA_SUBCA_LEN" ] && \ + print "basicConstraints = CA:TRUE, pathlen:$EASYRSA_SUBCA_LEN" + + # Deprecated Netscape extension support, if enabled + if print "$EASYRSA_NS_SUPPORT" | awk_yesno; then + [ -n "$EASYRSA_NS_COMMENT" ] && \ + print "nsComment = \"$EASYRSA_NS_COMMENT\"" + case "$crt_type" in + serverClient) print "nsCertType = serverClient" ;; + server) print "nsCertType = server" ;; + client) print "nsCertType = client" ;; + ca) print "nsCertType = sslCA" ;; + esac + fi + + # If type is server and no subjectAltName was requested, + # add one to the extensions file + if [ "$crt_type" = 'server' ]; + then + echo "$EASYRSA_EXTRA_EXTS" | + grep -q subjectAltName || + default_server_san "$req_in" + fi + + # Add any advanced extensions supplied by env-var: + [ -n "$EASYRSA_EXTRA_EXTS" ] && print "$EASYRSA_EXTRA_EXTS" + + : # needed to keep die from inherting the above test + } > "$EASYRSA_TEMP_EXT" || die "\ +Failed to create temp extension file (bad permissions?) at: +$EASYRSA_TEMP_EXT" + + # make safessl-easyrsa.cnf + make_ssl_config + + # sign request + # shellcheck disable=SC2086 + crt_out_tmp="$(mktemp "$crt_out.XXXXXXXXXX")"; EASYRSA_TEMP_FILE_2="$crt_out_tmp" + "$EASYRSA_OPENSSL" ca -utf8 -in "$req_in" -out "$crt_out_tmp" -config "$EASYRSA_SAFE_CONF" \ + -extfile "$EASYRSA_TEMP_EXT" -days "$EASYRSA_CERT_EXPIRE" -batch $opts \ + || die "signing failed (openssl output above may have more detail)" + mv "$crt_out_tmp" "$crt_out"; EASYRSA_TEMP_FILE_2= + notice "\ +Certificate created at: $crt_out +" + return 0 +} # => sign_req() + +# common build backend +# used to generate+sign in 1 step +build_full() { + verify_ca_init + + # pull filename base: + [ -n "$2" ] || die "\ +Error: didn't find a file base name as the first argument. +Run easyrsa without commands for usage and commands." + crt_type="$1" name="$2" + req_out="$EASYRSA_PKI/reqs/$2.req" + key_out="$EASYRSA_PKI/private/$2.key" + crt_out="$EASYRSA_PKI/issued/$2.crt" + shift 2 + + # function opts support + req_opts= + while [ -n "$1" ]; do + case "$1" in + nopass) req_opts="$req_opts nopass" ;; + *) warn "Ignoring unknown command option: '$1'" ;; + esac + shift + done + + # abort on existing req/key/crt files + err_exists="\ +file already exists. Aborting build to avoid overwriting this file. +If you wish to continue, please use a different name or remove the file. +Matching file found at: " + [ -f "$req_out" ] && die "Request $err_exists $req_out" + [ -f "$key_out" ] && die "Key $err_exists $key_out" + [ -f "$crt_out" ] && die "Certificate $err_exists $crt_out" + + # create request + EASYRSA_REQ_CN="$name" + #shellcheck disable=SC2086 + gen_req "$name" batch $req_opts + + # Sign it + sign_req "$crt_type" "$name" batch + +} # => build_full() + +# revoke backend +revoke() { + verify_ca_init + + # pull filename base: + [ -n "$1" ] || die "\ +Error: didn't find a file base name as the first argument. +Run easyrsa without commands for usage and command help." + crt_in="$EASYRSA_PKI/issued/$1.crt" + + opts="" + if [ "$2" ]; then + opts="$opts -crl_reason $2" + fi + + verify_file x509 "$crt_in" || die "\ +Unable to revoke as the input file is not a valid certificate. Unexpected +input in file: $crt_in" + + # confirm operation by displaying DN: + confirm "Continue with revocation: " "yes" " +Please confirm you wish to revoke the certificate with the following subject: + +$(display_dn x509 "$crt_in") +" # => confirm end + + # referenced cert must exist: + [ -f "$crt_in" ] || die "\ +Unable to revoke as no certificate was found. Certificate was expected +at: $crt_in" + + # make safessl-easyrsa.cnf + make_ssl_config + + # shellcheck disable=SC2086 + "$EASYRSA_OPENSSL" ca -utf8 -revoke "$crt_in" -config "$EASYRSA_SAFE_CONF" $opts || die "\ +Failed to revoke certificate: revocation command failed." + + # move revoked files so we can reissue certificates with the same name + move_revoked "$1" + + notice "\ +IMPORTANT!!! + +Revocation was successful. You must run gen-crl and upload a CRL to your +infrastructure in order to prevent the revoked cert from being accepted. +" # => notice end + return 0 +} #= revoke() + +# move-revoked +# moves revoked certificates to an alternative folder +# allows reissuing certificates with the same name +move_revoked() { + verify_ca_init + + [ -n "$1" ] || die "\ +Error: didn't find a file base name as the first argument. +Run easyrsa without commands for usage and command help." + + crt_in="$EASYRSA_PKI/issued/$1.crt" + key_in="$EASYRSA_PKI/private/$1.key" + req_in="$EASYRSA_PKI/reqs/$1.req" + + verify_file x509 "$crt_in" || die "\ +Unable to move revoked input file. The file is not a valid certificate. Unexpected +input in file: $crt_in" + + verify_file req "$req_in" || die "\ +Unable to move request. The file is not a valid request. Unexpected +input in file: $req_in" + + # get the serial number of the certificate -> serial=XXXX + cert_serial="$("$EASYRSA_OPENSSL" x509 -in "$crt_in" -noout -serial)" + # remove the serial= part -> we only need the XXXX part + cert_serial=${cert_serial##*=} + + crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem" + crt_by_serial_revoked="$EASYRSA_PKI/revoked/certs_by_serial/$cert_serial.crt" + key_by_serial_revoked="$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.key" + req_by_serial_revoked="$EASYRSA_PKI/revoked/reqs_by_serial/$cert_serial.req" + + + # move crt, key and req file to revoked folders + mv "$crt_in" "$crt_by_serial_revoked" + mv "$req_in" "$req_by_serial_revoked" + + # only move the key if we have it + if [ -e "$key_in" ] + then + mv "$key_in" "$key_by_serial_revoked" + fi + + # move the rest of the files (p12, p7, ...) + # shellcheck disable=SC2231 + for file in $EASYRSA_PKI/private/$1\.??? + do + # get file extension + file_ext="${file##*.}" + + [ -f "$file" ] && mv "$file" "$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.$file_ext" + done + + # remove the dublicate certificate in the certs_by_serial folder + rm "$crt_by_serial" + + return 0 + +} #= move_revoked() + +# renew backend +renew() { + verify_ca_init + + # pull filename base: + [ -n "$1" ] || die "\ +Error: didn't find a file base name as the first argument. +Run easyrsa without commands for usage and command help." + crt_in="$EASYRSA_PKI/issued/$1.crt" + + opts="" + if [ "$2" ]; then + opts="$2" + fi + + verify_file x509 "$crt_in" || die "\ +Unable to renew as the input file is not a valid certificate. Unexpected +input in file: $crt_in" + + # confirm operation by displaying DN: + confirm "Continue with renew: " "yes" " +Please confirm you wish to renew the certificate with the following subject: + +$(display_dn x509 "$crt_in") +" # => confirm end + + # referenced cert must exist: + [ -f "$crt_in" ] || die "\ +Unable to renew as no certificate was found. Certificate was expected +at: $crt_in" + + # make safessl-easyrsa.cnf + make_ssl_config + + # Check if old cert is expired or expires within 30 days + expire_date=$( + "$EASYRSA_OPENSSL" x509 -in "$crt_in" -noout -enddate | + sed 's/^notAfter=//' + ) + case $(uname) in + "Darwin"|*"BSD") + expire_date=$(date -j -f '%b %d %T %Y %Z' "$expire_date" +%s) + allow_renew_date=$(date -j -v"+${EASYRSA_CERT_RENEW}d" +%s) + ;; + *) + # This works on Windows, too, since uname doesn't exist and this is catch-all + expire_date=$(date -d "$expire_date" +%s) + allow_renew_date=$(date -d "+${EASYRSA_CERT_RENEW}day" +%s) + ;; + esac + + [ "$expire_date" -lt "$allow_renew_date" ] || die "\ +Certificate expires in more than $EASYRSA_CERT_RENEW days. +Renewal not allowed." + + # Extract certificate usage from old cert + cert_ext_key_usage=$( + "$EASYRSA_OPENSSL" x509 -in "$crt_in" -noout -text | + sed -n "/X509v3 Extended Key Usage:/{n;s/^ *//g;p;}" + ) + case $cert_ext_key_usage in + "TLS Web Client Authentication") + cert_type=client + ;; + "TLS Web Server Authentication") + cert_type=server + ;; + "TLS Web Server Authentication, TLS Web Client Authentication") + cert_type=serverClient + ;; + esac + + # Use SAN from --subject-alt-name if set else use SAN from old cert + echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName || \ + { + san=$( + "$EASYRSA_OPENSSL" x509 -in "$crt_in" -noout -text | + sed -n "/X509v3 Subject Alternative Name:/{n;s/ //g;p;}" + ) + [ -n "$san" ] && export EASYRSA_EXTRA_EXTS="\ +$EASYRSA_EXTRA_EXTS +subjectAltName = $san" + } + + # move renewed files so we can reissue certificate with the same name + # FIXME: Modify revoke() to also work on the renewed certs subdir + move_renewed "$1" + + # renew certificate + # shellcheck disable=SC2086 + build_full $cert_type $1 $opts || die "\ +Failed to renew certificate: renew command failed." + + notice "\ +IMPORTANT!!! + +Renew was successful. +You may want to revoke the old certificate once the new one has been deployed. +" # => notice end + return 0 +} #= renew() + +# move-renewed +# moves renewed certificates to an alternative folder +# allows reissuing certificates with the same name +move_renewed() { + verify_ca_init + + [ -n "$1" ] || die "\ +Error: didn't find a file base name as the first argument. +Run easyrsa without commands for usage and command help." + + crt_in="$EASYRSA_PKI/issued/$1.crt" + key_in="$EASYRSA_PKI/private/$1.key" + req_in="$EASYRSA_PKI/reqs/$1.req" + + verify_file x509 "$crt_in" || die "\ +Unable to move renewed input file. The file is not a valid certificate. Unexpected +input in file: $crt_in" + + verify_file req "$req_in" || die "\ +Unable to move request. The file is not a valid request. Unexpected +input in file: $req_in" + + # get the serial number of the certificate -> serial=XXXX + cert_serial="$("$EASYRSA_OPENSSL" x509 -in "$crt_in" -noout -serial)" + # remove the serial= part -> we only need the XXXX part + cert_serial=${cert_serial##*=} + + crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem" + crt_by_serial_renewed="$EASYRSA_PKI/renewed/certs_by_serial/$cert_serial.crt" + key_by_serial_renewed="$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.key" + req_by_serial_renewed="$EASYRSA_PKI/renewed/reqs_by_serial/$cert_serial.req" + + + # move crt, key and req file to renewed folders + mv "$crt_in" "$crt_by_serial_renewed" + mv "$req_in" "$req_by_serial_renewed" + + # only move the key if we have it + if [ -e "$key_in" ] + then + mv "$key_in" "$key_by_serial_renewed" + fi + + # move the rest of the files (p12, p7, ...) + # shellcheck disable=SC2231 + for file in $EASYRSA_PKI/private/$1\.??? + do + # get file extension + file_ext="${file##*.}" + + [ -f "$file" ] && mv "$file" "$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.$file_ext" + done + + # remove the duplicate certificate in the certs_by_serial folder + rm "$crt_by_serial" + + return 0 + +} #= move_renewed() + +# gen-crl backend +gen_crl() { + verify_ca_init + + # make safessl-easyrsa.cnf + make_ssl_config + + out_file="$EASYRSA_PKI/crl.pem" + out_file_tmp="$(mktemp "$out_file.XXXXXXXXXX")"; EASYRSA_TEMP_FILE_2="$out_file_tmp" + "$EASYRSA_OPENSSL" ca -utf8 -gencrl -out "$out_file_tmp" -config "$EASYRSA_SAFE_CONF" || die "\ +CRL Generation failed. +" + mv "$out_file_tmp" "$out_file"; EASYRSA_TEMP_FILE_2= + + notice "\ +An updated CRL has been created. +CRL file: $out_file +" + return 0 +} # => gen_crl() + +# import-req backend +import_req() { + verify_pki_init + + # pull passed paths + in_req="$1" short_name="$2" + out_req="$EASYRSA_PKI/reqs/$2.req" + + [ -n "$short_name" ] || die "\ +Unable to import: incorrect command syntax. +Run easyrsa without commands for usage and command help." + + verify_file req "$in_req" || die "\ +The input file does not appear to be a certificate request. Aborting import. +Offending file: $in_req" + + # destination must not exist + [ -f "$out_req" ] && die "\ +Unable to import the request as the destination file already exists. +Please choose a different name for your imported request file. +Existing file at: $out_req" + + # now import it + cp "$in_req" "$out_req" + + notice "\ +The request has been successfully imported with a short name of: $short_name +You may now use this name to perform signing operations on this request. +" + return 0 +} # => import_req() + +# export pkcs#12 or pkcs#7 +export_pkcs() { + pkcs_type="$1" + shift + + [ -n "$1" ] || die "\ +Unable to export p12: incorrect command syntax. +Run easyrsa without commands for usage and command help." + + short_name="$1" + crt_in="$EASYRSA_PKI/issued/$1.crt" + key_in="$EASYRSA_PKI/private/$1.key" + crt_ca="$EASYRSA_PKI/ca.crt" + shift + + verify_pki_init + + # opts support + want_ca=1 + want_key=1 + while [ -n "$1" ]; do + case "$1" in + noca) want_ca="" ;; + nokey) want_key="" ;; + *) warn "Ignoring unknown command option: '$1'" ;; + esac + shift + done + + pkcs_opts= + if [ $want_ca ]; then + verify_file x509 "$crt_ca" || die "\ +Unable to include CA cert in the $pkcs_type output (missing file, or use noca option.) +Missing file expected at: $crt_ca" + pkcs_opts="$pkcs_opts -certfile $crt_ca" + fi + + # input files must exist + verify_file x509 "$crt_in" || die "\ +Unable to export $pkcs_type for short name '$short_name' without the certificate. +Missing cert expected at: $crt_in" + + case "$pkcs_type" in + p12) + pkcs_out="$EASYRSA_PKI/private/$short_name.p12" + + if [ $want_key ]; then + [ -f "$key_in" ] || die "\ +Unable to export p12 for short name '$short_name' without the key +(if you want a p12 without the private key, use nokey option.) +Missing key expected at: $key_in" + else + pkcs_opts="$pkcs_opts -nokeys" + fi + + # export the p12: + # shellcheck disable=SC2086 + "$EASYRSA_OPENSSL" pkcs12 -in "$crt_in" -inkey "$key_in" -export \ + -out "$pkcs_out" $pkcs_opts || die "\ +Export of p12 failed: see above for related openssl errors." + ;; + p7) + pkcs_out="$EASYRSA_PKI/issued/$short_name.p7b" + + # export the p7: + # shellcheck disable=SC2086 + "$EASYRSA_OPENSSL" crl2pkcs7 -nocrl -certfile "$crt_in" \ + -out "$pkcs_out" $pkcs_opts || die "\ +Export of p7 failed: see above for related openssl errors." + ;; +esac + + notice "\ +Successful export of $pkcs_type file. Your exported file is at the following +location: $pkcs_out +" + return 0 +} # => export_pkcs() + +# set-pass backend +set_pass() { + verify_pki_init + + # key type, supplied internally from frontend command call (rsa/ec) + key_type="$1" + + # values supplied by the user: + raw_file="$2" + file="$EASYRSA_PKI/private/$raw_file.key" + [ -n "$raw_file" ] || die "\ +Missing argument to 'set-$key_type-pass' command: no name/file supplied. +See help output for usage details." + + # parse command options + shift 2 + crypto="-aes256" + while [ -n "$1" ]; do + case "$1" in + nopass) crypto="" ;; + file) file="$raw_file" ;; + *) warn "Ignoring unknown command option: '$1'" ;; + esac + shift + done + + [ -f "$file" ] || die "\ +Missing private key: expected to find the private key component at: +$file" + + notice "\ +If the key is currently encrypted you must supply the decryption passphrase. +${crypto:+You will then enter a new PEM passphrase for this key.$NL}" + + EASYRSA_TEMP_FILE_2="$file.temp" + + "$EASYRSA_OPENSSL" "$key_type" -in "$file" -out "$EASYRSA_TEMP_FILE_2" $crypto || die "\ +Failed to change the private key passphrase. See above for possible openssl +error messages." + + mv "$EASYRSA_TEMP_FILE_2" "$file" || die "\ +Failed to change the private key passphrase. See above for error messages." + + notice "Key passphrase successfully changed" + +} # => set_pass() + +# update-db backend +update_db() { + verify_ca_init + + "$EASYRSA_OPENSSL" ca -utf8 -updatedb -config "$EASYRSA_SSL_CONF" || die "\ +Failed to perform update-db: see above for related openssl errors." + return 0 +} # => update_db() + +# display cert DN info on a req/X509, passed by full pathname +display_dn() { + format="$1" path="$2" + print "$("$EASYRSA_OPENSSL" "$format" -in "$path" -noout -subject -nameopt multiline)" +} # => display_dn() + +# generate default SAN from req/X509, passed by full pathname +default_server_san() { + path="$1" + cn=$( + "$EASYRSA_OPENSSL" req -in "$path" -noout -subject -nameopt sep_multiline | + awk -F'=' '/^ *CN=/{print $2}' + ) + echo "$cn" | grep -E -q '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' + #shellcheck disable=SC2181 + if [ $? -eq 0 ]; then + print "subjectAltName = IP:$cn" + else + print "subjectAltName = DNS:$cn" + fi +} # => default_server_san() + +# verify a file seems to be a valid req/X509 +verify_file() { + format="$1" + path="$2" + "$EASYRSA_OPENSSL" "$format" -in "$path" -noout 2>/dev/null || return 1 + return 0 +} # => verify_file() + +# show-* command backend +# Prints req/cert details in a readable format +show() { + type="$1" + name="$2" + in_file="" + format="" + [ -n "$name" ] || die "\ +Missing expected filename_base argument. +Run easyrsa without commands for usage help." + shift 2 + + # opts support + opts="-${type}opt no_pubkey,no_sigdump" + while [ -n "$1" ]; do + case "$1" in + full) + opts="" + ;; + *) + warn "Ignoring unknown command option: '$1'" + ;; + esac + shift + done + + # Determine cert/req type + if [ "$type" = "cert" ]; then + verify_ca_init + in_file="$EASYRSA_PKI/issued/${name}.crt" + format="x509" + else + verify_pki_init + in_file="$EASYRSA_PKI/reqs/${name}.req" + format="req" + fi + + # Verify file exists and is of the correct type + [ -f "$in_file" ] || die "\ +No such $type file with a basename of '$name' is present. +Expected to find this file at: +$in_file" + verify_file $format "$in_file" || die "\ +This file is not a valid $type file: +$in_file" + + notice "\ +Showing $type details for '$name'. +This file is stored at: +$in_file +" + "$EASYRSA_OPENSSL" $format -in "$in_file" -noout -text\ + -nameopt multiline $opts || die "\ +OpenSSL failure to process the input" +} # => show() + +# show-ca command backend +# Prints CA cert details in a readable format +show_ca() { + # opts support + opts="-certopt no_pubkey,no_sigdump" + while [ -n "$1" ]; do + case "$1" in + full) opts= ;; + *) warn "Ignoring unknown command option: '$1'" ;; + esac + shift + done + + verify_ca_init + in_file="$EASYRSA_PKI/ca.crt" + format="x509" + + # Verify file exists and is of the correct type + [ -f "$in_file" ] || die "\ +No such $type file with a basename of '$name' is present. +Expected to find this file at: +$in_file" + verify_file $format "$in_file" || die "\ +This file is not a valid $type file: +$in_file" + + notice "\ +Showing $type details for 'ca'. +This file is stored at: +$in_file +" + "$EASYRSA_OPENSSL" $format -in "$in_file" -noout -text\ + -nameopt multiline $opts || die "\ +OpenSSL failure to process the input" +} # => show_ca() + +# vars setup +# Here sourcing of 'vars' if present occurs. If not present, defaults are used +# to support running without a sourced config format +vars_setup() { + # Try to locate a 'vars' file in order of location preference. + # If one is found, source it + vars= + + # set up program path + prog_vars="${0%/*}/vars" + # set up PKI path + pki_vars="${EASYRSA_PKI:-$PWD/pki}/vars" + + # command-line path: + if [ -f "$EASYRSA_VARS_FILE" ]; then + vars="$EASYRSA_VARS_FILE" + # PKI location, if present: + elif [ -f "$pki_vars" ]; then + vars="$pki_vars" + # EASYRSA, if defined: + elif [ -n "$EASYRSA" ] && [ -f "$EASYRSA/vars" ]; then + vars="$EASYRSA/vars" + # program location: + elif [ -f "$prog_vars" ]; then + vars="$prog_vars" + fi + + # If a vars file was located, source it + # If $EASYRSA_NO_VARS is defined (not blank) this is skipped + if [ -z "$EASYRSA_NO_VARS" ] && [ -n "$vars" ]; then + #shellcheck disable=SC2034 + EASYRSA_CALLER=1 + # shellcheck disable=SC1090 + . "$vars" + notice "\ +Note: using Easy-RSA configuration from: $vars" + fi + + # Set defaults, preferring existing env-vars if present + set_var EASYRSA "${0%/*}" + set_var EASYRSA_OPENSSL openssl + set_var EASYRSA_PKI "$PWD/pki" + set_var EASYRSA_DN cn_only + set_var EASYRSA_REQ_COUNTRY "US" + set_var EASYRSA_REQ_PROVINCE "California" + set_var EASYRSA_REQ_CITY "San Francisco" + set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" + set_var EASYRSA_REQ_EMAIL me@example.net + set_var EASYRSA_REQ_OU "My Organizational Unit" + set_var EASYRSA_ALGO rsa + set_var EASYRSA_KEY_SIZE 2048 + set_var EASYRSA_CURVE secp384r1 + set_var EASYRSA_EC_DIR "$EASYRSA_PKI/ecparams" + set_var EASYRSA_CA_EXPIRE 3650 + set_var EASYRSA_CERT_EXPIRE 1080 # new default of 36 months + set_var EASYRSA_CERT_RENEW 30 + set_var EASYRSA_CRL_DAYS 180 + set_var EASYRSA_NS_SUPPORT no + set_var EASYRSA_NS_COMMENT "Easy-RSA (v3.0.6) Generated Certificate" + set_var EASYRSA_TEMP_CONF "$EASYRSA_PKI/openssl-easyrsa.temp" + set_var EASYRSA_TEMP_EXT "$EASYRSA_PKI/extensions.temp" + set_var EASYRSA_TEMP_FILE_2 "" + set_var EASYRSA_TEMP_FILE_3 "" + set_var EASYRSA_REQ_CN ChangeMe + set_var EASYRSA_DIGEST sha256 + + set_var EASYRSA_SSL_CONF "$EASYRSA_PKI/openssl-easyrsa.cnf" + set_var EASYRSA_SAFE_CONF "$EASYRSA_PKI/safessl-easyrsa.cnf" + + # Same as above for the x509-types extensions dir + if [ -d "$EASYRSA_PKI/x509-types" ]; then + set_var EASYRSA_EXT_DIR "$EASYRSA_PKI/x509-types" + else + #TODO: This should be removed. Not really suitable for packaging. + set_var EASYRSA_EXT_DIR "$EASYRSA/x509-types" + fi + + # EASYRSA_ALGO_PARAMS must be set depending on selected algo + if [ "ec" = "$EASYRSA_ALGO" ]; then + EASYRSA_ALGO_PARAMS="$EASYRSA_EC_DIR/${EASYRSA_CURVE}.pem" + elif [ "rsa" = "$EASYRSA_ALGO" ]; then + EASYRSA_ALGO_PARAMS="${EASYRSA_KEY_SIZE}" + else + die "Alg '$EASYRSA_ALGO' is invalid: must be 'rsa' or 'ec'" + fi + + # Setting OPENSSL_CONF prevents bogus warnings (especially useful on win32) + export OPENSSL_CONF="$EASYRSA_SAFE_CONF" +} # vars_setup() + +# variable assignment by indirection when undefined; merely exports +# the variable when it is already defined (even if currently null) +# Sets $1 as the value contained in $2 and exports (may be blank) +set_var() { + var=$1 + shift + value="$*" + eval "export $var=\"\${$var-$value}\"" +} #=> set_var() + +######################################## +# Invocation entry point: + +NL=' +' + +# Be secure with a restrictive umask +[ -z "$EASYRSA_NO_UMASK" ] && umask 077 + +# Parse options +while :; do + # Separate option from value: + opt="${1%%=*}" + val="${1#*=}" + empty_ok="" # Empty values are not allowed unless excepted + + case "$opt" in + --days) + export EASYRSA_CERT_EXPIRE="$val" + export EASYRSA_CA_EXPIRE="$val" + export EASYRSA_CRL_DAYS="$val" + ;; + --pki-dir) + export EASYRSA_PKI="$val" ;; + --use-algo) + export EASYRSA_ALGO="$val" ;; + --keysize) + export EASYRSA_KEY_SIZE="$val" ;; + --curve) + export EASYRSA_CURVE="$val" ;; + --dn-mode) + export EASYRSA_DN="$val" ;; + --req-cn) + export EASYRSA_REQ_CN="$val" ;; + --digest) + export EASYRSA_DIGEST="$val" ;; + --req-c) + empty_ok=1 + export EASYRSA_REQ_COUNTRY="$val" ;; + --req-st) + empty_ok=1 + export EASYRSA_REQ_PROVINCE="$val" ;; + --req-city) + empty_ok=1 + export EASYRSA_REQ_CITY="$val" ;; + --req-org) + empty_ok=1 + export EASYRSA_REQ_ORG="$val" ;; + --req-email) + empty_ok=1 + export EASYRSA_REQ_EMAIL="$val" ;; + --req-ou) + empty_ok=1 + export EASYRSA_REQ_OU="$val" ;; + --ns-cert) + export EASYRSA_NS_SUPPORT="$val" ;; + --ns-comment) + empty_ok=1 + export EASYRSA_NS_COMMENT="$val" ;; + --batch) + empty_ok=1 + export EASYRSA_BATCH=1 ;; + --subca-len) + export EASYRSA_SUBCA_LEN="$val" ;; + --vars) + export EASYRSA_VARS_FILE="$val" ;; + --copy-ext) + empty_ok=1 + export EASYRSA_CP_EXT=1 ;; + --subject-alt-name) + export EASYRSA_EXTRA_EXTS="\ +$EASYRSA_EXTRA_EXTS +subjectAltName = $val" ;; + *) + break ;; + esac + + # fatal error when no value was provided + if [ ! $empty_ok ] && { [ "$val" = "$1" ] || [ -z "$val" ]; }; then + die "Missing value to option: $opt" + fi + + shift +done + +# Intelligent env-var detection and auto-loading: +vars_setup + +# Register clean_temp and prog_exit on SIGHUP, SIGINT, SIGQUIT, and SIGABRT +trap "clean_temp; prog_exit 1" 1 +trap "clean_temp; prog_exit 2" 2 +trap "clean_temp; prog_exit 3" 3 +trap "clean_temp; prog_exit 6" 6 +trap "clean_temp; prog_exit 15" 15 + +# determine how we were called, then hand off to the function responsible +cmd="$1" +[ -n "$1" ] && shift # scrape off command +case "$cmd" in + init-pki|clean-all) + init_pki "$@" + ;; + build-ca) + build_ca "$@" + ;; + gen-dh) + gen_dh + ;; + gen-req) + gen_req "$@" + ;; + sign|sign-req) + sign_req "$@" + ;; + build-client-full) + build_full client "$@" + ;; + build-server-full) + build_full server "$@" + ;; + build-serverClient-full) + build_full serverClient "$@" + ;; + gen-crl) + gen_crl + ;; + revoke) + revoke "$@" + ;; + renew) + renew "$@" + ;; + import-req) + import_req "$@" + ;; + export-p12) + export_pkcs p12 "$@" + ;; + export-p7) + export_pkcs p7 "$@" + ;; + set-rsa-pass) + set_pass rsa "$@" + ;; + set-ec-pass) + set_pass ec "$@" + ;; + update-db) + update_db + ;; + show-req) + show req "$@" + ;; + show-cert) + show cert "$@" + ;; + show-ca) + show_ca "$@" + ;; + ""|help|-h|--help|--usage) + cmd_help "$1" + exit 0 + ;; + *) + die "Unknown command '$cmd'. Run without commands for usage help." + ;; +esac + +# vim: ft=sh nu ai sw=8 ts=8 noet diff --git a/easy-rsa/keys/.rnd b/easy-rsa/keys/.rnd new file mode 100644 index 0000000..a6ff166 Binary files /dev/null and b/easy-rsa/keys/.rnd differ diff --git a/easy-rsa/keys/crl.jail/etc/openvpn/scripts b/easy-rsa/keys/crl.jail/etc/openvpn/scripts new file mode 120000 index 0000000..6027452 --- /dev/null +++ b/easy-rsa/keys/crl.jail/etc/openvpn/scripts @@ -0,0 +1 @@ +/etc/openvpn/scripts/ \ No newline at end of file diff --git a/easy-rsa/openssl-easyrsa.cnf b/easy-rsa/openssl-easyrsa.cnf new file mode 100644 index 0000000..c3bf849 --- /dev/null +++ b/easy-rsa/openssl-easyrsa.cnf @@ -0,0 +1,141 @@ +# For use with Easy-RSA 3.1 and OpenSSL or LibreSSL + +RANDFILE = $ENV::EASYRSA_PKI/.rnd + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = $ENV::EASYRSA_PKI # Where everything is kept +certs = $dir # Where the issued certs are kept +crl_dir = $dir # Where the issued crl are kept +database = $dir/index.txt # database index file. +new_certs_dir = $dir/certs_by_serial # default place for new certs. + +certificate = $dir/ca.crt # The CA certificate +serial = $dir/serial # The current serial number +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/ca.key # The private key +RANDFILE = $dir/.rand # private random number file + +x509_extensions = basic_exts # The extentions to add to the cert + +# This allows a V2 CRL. Ancient browsers don't like it, but anything Easy-RSA +# is designed for will. In return, we get the Issuer attached to CRLs. +crl_extensions = crl_ext + +default_days = $ENV::EASYRSA_CERT_EXPIRE # how long to certify for +# TurnKey default_crl_days: 3 years - see https://github.com/turnkeylinux/tracker/issues/1291 +default_crl_days= 1095 # how long before next CRL expiry +default_md = $ENV::EASYRSA_DIGEST # use public key default MD +preserve = no # keep passed DN ordering + +# This allows to renew certificates which have not been revoked +unique_subject = no + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_anything + +# For the 'anything' policy, which defines allowed DN fields +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +name = optional +emailAddress = optional + +#################################################################### +# Easy-RSA request handling +# We key off $DN_MODE to determine how to format the DN +[ req ] +default_bits = $ENV::EASYRSA_KEY_SIZE +default_keyfile = privkey.pem +default_md = $ENV::EASYRSA_DIGEST +distinguished_name = $ENV::EASYRSA_DN +x509_extensions = easyrsa_ca # The extentions to add to the self signed cert + +# A placeholder to handle the $EXTRA_EXTS feature: +#%EXTRA_EXTS% # Do NOT remove or change this line as $EXTRA_EXTS support requires it + +#################################################################### +# Easy-RSA DN (Subject) handling + +# Easy-RSA DN for cn_only support: +[ cn_only ] +commonName = Common Name (eg: your user, host, or server name) +commonName_max = 64 +commonName_default = $ENV::EASYRSA_REQ_CN + +# Easy-RSA DN for org support: +[ org ] +countryName = Country Name (2 letter code) +countryName_default = $ENV::EASYRSA_REQ_COUNTRY +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = $ENV::EASYRSA_REQ_PROVINCE + +localityName = Locality Name (eg, city) +localityName_default = $ENV::EASYRSA_REQ_CITY + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = $ENV::EASYRSA_REQ_ORG + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = $ENV::EASYRSA_REQ_OU + +commonName = Common Name (eg: your user, host, or server name) +commonName_max = 64 +commonName_default = $ENV::EASYRSA_REQ_CN + +emailAddress = Email Address +emailAddress_default = $ENV::EASYRSA_REQ_EMAIL +emailAddress_max = 64 + +#################################################################### +# Easy-RSA cert extension handling + +# This section is effectively unused as the main script sets extensions +# dynamically. This core section is left to support the odd usecase where +# a user calls openssl directly. +[ basic_exts ] +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always + +# The Easy-RSA CA extensions +[ easyrsa_ca ] + +# PKIX recommendations: + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always + +# This could be marked critical, but it's nice to support reading by any +# broken clients who attempt to do so. +basicConstraints = CA:true + +# Limit key usage to CA tasks. If you really want to use the generated pair as +# a self-signed cert, comment this out. +keyUsage = cRLSign, keyCertSign + +# nsCertType omitted by default. Let's try to let the deprecated stuff die. +# nsCertType = sslCA + +# CRL extensions. +[ crl_ext ] + +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + diff --git a/easy-rsa/vars b/easy-rsa/vars new file mode 100644 index 0000000..4f437db --- /dev/null +++ b/easy-rsa/vars @@ -0,0 +1,17 @@ +set_var EASY_RSA "/etc/openvpn/easy-rsa/easyrsa" +set_var OPENSSL "/usr/bin/openssl" +set_var EASYRSA_PKI "/etc/openvpn/easy-rsa/keys" + +set_var EASYRSA_KEY_SIZE 2048 +set_var EASYRSA_REQ_ORG "TurnKey Linux" +set_var EASYRSA_REQ_EMAIL "admin@astragroup.info" +set_var EASYRSA_REQ_OU "OpenVPN" +set_var EASYRSA_REQ_COUNTRY "US" +set_var EASYRSA_REQ_PROVINCE "UT" +set_var EASYRSA_REQ_CITY "Salt Lake" +set_var EASYRSA_REQ_CN "AGOVPN" +set_var EASYRSA_DIGEST "sha256" +set_var EASYRSA_NS_SUPPORT "yes" +set_var EASYRSA_ALGO "rsa" +set_var EASYRSA_CRL_DAYS 730 + diff --git a/easy-rsa/vars.example b/easy-rsa/vars.example new file mode 100644 index 0000000..f03ea6e --- /dev/null +++ b/easy-rsa/vars.example @@ -0,0 +1,210 @@ +# Easy-RSA 3 parameter settings + +# NOTE: If you installed Easy-RSA from your distro's package manager, don't edit +# this file in place -- instead, you should copy the entire easy-rsa directory +# to another location so future upgrades don't wipe out your changes. + +# HOW TO USE THIS FILE +# +# vars.example contains built-in examples to Easy-RSA settings. You MUST name +# this file 'vars' if you want it to be used as a configuration file. If you do +# not, it WILL NOT be automatically read when you call easyrsa commands. +# +# It is not necessary to use this config file unless you wish to change +# operational defaults. These defaults should be fine for many uses without the +# need to copy and edit the 'vars' file. +# +# All of the editable settings are shown commented and start with the command +# 'set_var' -- this means any set_var command that is uncommented has been +# modified by the user. If you're happy with a default, there is no need to +# define the value to its default. + +# NOTES FOR WINDOWS USERS +# +# Paths for Windows *MUST* use forward slashes, or optionally double-esscaped +# backslashes (single forward slashes are recommended.) This means your path to +# the openssl binary might look like this: +# "C:/Program Files/OpenSSL-Win32/bin/openssl.exe" + +# A little housekeeping: DON'T EDIT THIS SECTION +# +# Easy-RSA 3.x doesn't source into the environment directly. +# Complain if a user tries to do this: +if [ -z "$EASYRSA_CALLER" ]; then + echo "You appear to be sourcing an Easy-RSA 'vars' file." >&2 + echo "This is no longer necessary and is disallowed. See the section called" >&2 + echo "'How to use this file' near the top comments for more details." >&2 + return 1 +fi + +# DO YOUR EDITS BELOW THIS POINT + +# This variable is used as the base location of configuration files needed by +# easyrsa. More specific variables for specific files (e.g., EASYRSA_SSL_CONF) +# may override this default. +# +# The default value of this variable is the location of the easyrsa script +# itself, which is also where the configuration files are located in the +# easy-rsa tree. + +#set_var EASYRSA "${0%/*}" + +# If your OpenSSL command is not in the system PATH, you will need to define the +# path to it here. Normally this means a full path to the executable, otherwise +# you could have left it undefined here and the shown default would be used. +# +# Windows users, remember to use paths with forward-slashes (or escaped +# back-slashes.) Windows users should declare the full path to the openssl +# binary here if it is not in their system PATH. + +#set_var EASYRSA_OPENSSL "openssl" +# +# This sample is in Windows syntax -- edit it for your path if not using PATH: +#set_var EASYRSA_OPENSSL "C:/Program Files/OpenSSL-Win32/bin/openssl.exe" + +# Edit this variable to point to your soon-to-be-created key directory. By +# default, this will be "$PWD/pki" (i.e. the "pki" subdirectory of the +# directory you are currently in). +# +# WARNING: init-pki will do a rm -rf on this directory so make sure you define +# it correctly! (Interactive mode will prompt before acting.) + +#set_var EASYRSA_PKI "$PWD/pki" + +# Define X509 DN mode. +# This is used to adjust what elements are included in the Subject field as the DN +# (this is the "Distinguished Name.") +# Note that in cn_only mode the Organizational fields further below aren't used. +# +# Choices are: +# cn_only - use just a CN value +# org - use the "traditional" Country/Province/City/Org/OU/email/CN format + +#set_var EASYRSA_DN "cn_only" + +# Organizational fields (used with 'org' mode and ignored in 'cn_only' mode.) +# These are the default values for fields which will be placed in the +# certificate. Don't leave any of these fields blank, although interactively +# you may omit any specific field by typing the "." symbol (not valid for +# email.) + +#set_var EASYRSA_REQ_COUNTRY "US" +#set_var EASYRSA_REQ_PROVINCE "California" +#set_var EASYRSA_REQ_CITY "San Francisco" +#set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" +#set_var EASYRSA_REQ_EMAIL "me@example.net" +#set_var EASYRSA_REQ_OU "My Organizational Unit" + +# Choose a size in bits for your keypairs. The recommended value is 2048. Using +# 2048-bit keys is considered more than sufficient for many years into the +# future. Larger keysizes will slow down TLS negotiation and make key/DH param +# generation take much longer. Values up to 4096 should be accepted by most +# software. Only used when the crypto alg is rsa (see below.) + +#set_var EASYRSA_KEY_SIZE 2048 + +# The default crypto mode is rsa; ec can enable elliptic curve support. +# Note that not all software supports ECC, so use care when enabling it. +# Choices for crypto alg are: (each in lower-case) +# * rsa +# * ec + +#set_var EASYRSA_ALGO rsa + +# Define the named curve, used in ec mode only: + +#set_var EASYRSA_CURVE secp384r1 + +# In how many days should the root CA key expire? + +#set_var EASYRSA_CA_EXPIRE 3650 + +# In how many days should certificates expire? + +#set_var EASYRSA_CERT_EXPIRE 1080 + +# How many days until the next CRL publish date? Note that the CRL can still be +# parsed after this timeframe passes. It is only used for an expected next +# publication date. + +# How many days before its expiration date a certificate is allowed to be +# renewed? +#set_var EASYRSA_CERT_RENEW 30 + +#set_var EASYRSA_CRL_DAYS 180 + +# Support deprecated "Netscape" extensions? (choices "yes" or "no".) The default +# is "no" to discourage use of deprecated extensions. If you require this +# feature to use with --ns-cert-type, set this to "yes" here. This support +# should be replaced with the more modern --remote-cert-tls feature. If you do +# not use --ns-cert-type in your configs, it is safe (and recommended) to leave +# this defined to "no". When set to "yes", server-signed certs get the +# nsCertType=server attribute, and also get any NS_COMMENT defined below in the +# nsComment field. + +#set_var EASYRSA_NS_SUPPORT "no" + +# When NS_SUPPORT is set to "yes", this field is added as the nsComment field. +# Set this blank to omit it. With NS_SUPPORT set to "no" this field is ignored. + +#set_var EASYRSA_NS_COMMENT "Easy-RSA Generated Certificate" + +# A temp file used to stage cert extensions during signing. The default should +# be fine for most users; however, some users might want an alternative under a +# RAM-based FS, such as /dev/shm or /tmp on some systems. + +#set_var EASYRSA_TEMP_FILE "$EASYRSA_PKI/extensions.temp" + +# !! +# NOTE: ADVANCED OPTIONS BELOW THIS POINT +# PLAY WITH THEM AT YOUR OWN RISK +# !! + +# Broken shell command aliases: If you have a largely broken shell that is +# missing any of these POSIX-required commands used by Easy-RSA, you will need +# to define an alias to the proper path for the command. The symptom will be +# some form of a 'command not found' error from your shell. This means your +# shell is BROKEN, but you can hack around it here if you really need. These +# shown values are not defaults: it is up to you to know what you're doing if +# you touch these. +# +#alias awk="/alt/bin/awk" +#alias cat="/alt/bin/cat" + +# X509 extensions directory: +# If you want to customize the X509 extensions used, set the directory to look +# for extensions here. Each cert type you sign must have a matching filename, +# and an optional file named 'COMMON' is included first when present. Note that +# when undefined here, default behaviour is to look in $EASYRSA_PKI first, then +# fallback to $EASYRSA for the 'x509-types' dir. You may override this +# detection with an explicit dir here. +# +#set_var EASYRSA_EXT_DIR "$EASYRSA/x509-types" + +# OpenSSL config file: +# If you need to use a specific openssl config file, you can reference it here. +# Normally this file is auto-detected from a file named openssl-easyrsa.cnf from the +# EASYRSA_PKI or EASYRSA dir (in that order.) NOTE that this file is Easy-RSA +# specific and you cannot just use a standard config file, so this is an +# advanced feature. + +#set_var EASYRSA_SSL_CONF "$EASYRSA/openssl-easyrsa.cnf" + +# Default CN: +# This is best left alone. Interactively you will set this manually, and BATCH +# callers are expected to set this themselves. + +#set_var EASYRSA_REQ_CN "ChangeMe" + +# Cryptographic digest to use. +# Do not change this default unless you understand the security implications. +# Valid choices include: md5, sha1, sha256, sha224, sha384, sha512 + +#set_var EASYRSA_DIGEST "sha256" + +# Batch mode. Leave this disabled unless you intend to call Easy-RSA explicitly +# in batch mode without any user input, confirmation on dangerous operations, +# or most output. Setting this to any non-blank string enables batch mode. + +#set_var EASYRSA_BATCH "" + diff --git a/scripts/connect.sh b/scripts/connect.sh new file mode 100755 index 0000000..6726f71 --- /dev/null +++ b/scripts/connect.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# connect script + +/usr/bin/echo "client $common_name connected at $(/usr/bin/date +%m-%d-%y_%H:%M:%S)" >> /var/log/openvpn/states.log diff --git a/scripts/disconnect.sh b/scripts/disconnect.sh new file mode 100755 index 0000000..9d28295 --- /dev/null +++ b/scripts/disconnect.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# disconnect script + +echo "client $common_name disconnected at $(date +%m-%d-%y_%H:%M:%S)" >> /var/log/openvpn/states.log + diff --git a/server.ccd b/server.ccd new file mode 120000 index 0000000..6df400d --- /dev/null +++ b/server.ccd @@ -0,0 +1 @@ +/etc/openvpn/easy-rsa/keys/crl.jail/etc/openvpn/server.ccd \ No newline at end of file diff --git a/server.conf b/server.conf new file mode 100644 index 0000000..57500f0 --- /dev/null +++ b/server.conf @@ -0,0 +1,43 @@ +# PUBLIC_ADDRESS: priv.astragroup.info (used by openvpn-addclient) + +port 1194 +proto udp +dev tun + +cipher AES-256-CBC +auth SHA256 + +keepalive 10 120 + +persist-key +persist-tun +user nobody +group nogroup + +script-security 3 +#client-connect "/usr/bin/bash /etc/openvpn/scripts/connect.sh" +#client-disconnect "/etc/openvpn/scripts/disconnect.sh" + +chroot /etc/openvpn/easy-rsa/keys/crl.jail + +crl-verify /etc/openvpn/crl.pem + +ca /etc/openvpn/easy-rsa/keys/ca.crt +dh /etc/openvpn/easy-rsa/keys/dh.pem +tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0 +key /etc/openvpn/easy-rsa/keys/private/server.key +cert /etc/openvpn/easy-rsa/keys/issued/server.crt + +ifconfig-pool-persist /var/lib/openvpn/server.ipp +client-config-dir /etc/openvpn/server.ccd +status /var/log/openvpn/server.status 1 +log /var/log/openvpn/server.log +verb 2 + +# virtual subnet unique for openvpn to draw client addresses from +# the server will be configured with x.x.x.1 +# important: must not be used on your network +server 10.86.203.0 255.255.255.0 +# configure clients to route all their traffic through the vpn +push "redirect-gateway def1 bypass-dhcp" +push "explicit-exit-notify 1" diff --git a/update-resolv-conf b/update-resolv-conf new file mode 100755 index 0000000..61b15d9 --- /dev/null +++ b/update-resolv-conf @@ -0,0 +1,63 @@ +#!/bin/bash +# +# Parses DHCP options from openvpn to update resolv.conf +# To use set as 'up' and 'down' script in your openvpn *.conf: +# up /etc/openvpn/update-resolv-conf +# down /etc/openvpn/update-resolv-conf +# +# Used snippets of resolvconf script by Thomas Hood and Chris Hanson. +# Licensed under the GNU GPL. See /usr/share/common-licenses/GPL. +# +# Example envs set from openvpn: +# +# foreign_option_1='dhcp-option DNS 193.43.27.132' +# foreign_option_2='dhcp-option DNS 193.43.27.133' +# foreign_option_3='dhcp-option DOMAIN be.bnc.ch' +# + +if [ ! -x /sbin/resolvconf ] ; then + logger "[OpenVPN:update-resolve-conf] missing binary /sbin/resolvconf"; + exit 0; +fi + +[ "$script_type" ] || exit 0 +[ "$dev" ] || exit 0 + +split_into_parts() +{ + part1="$1" + part2="$2" + part3="$3" +} + +case "$script_type" in + up) + NMSRVRS="" + SRCHS="" + foreign_options=$(printf '%s\n' ${!foreign_option_*} | sort -t _ -k 3 -g) + for optionvarname in ${foreign_options} ; do + option="${!optionvarname}" + echo "$option" + split_into_parts $option + if [ "$part1" = "dhcp-option" ] ; then + if [ "$part2" = "DNS" ] ; then + NMSRVRS="${NMSRVRS:+$NMSRVRS }$part3" + elif [ "$part2" = "DOMAIN" ] ; then + SRCHS="${SRCHS:+$SRCHS }$part3" + fi + fi + done + R="" + [ "$SRCHS" ] && R="search $SRCHS +" + for NS in $NMSRVRS ; do + R="${R}nameserver $NS +" + done + echo -n "$R" | /sbin/resolvconf -a "${dev}.openvpn" + ;; + down) + /sbin/resolvconf -d "${dev}.openvpn" + ;; +esac +