diff --git a/admin/api/certificate.go b/admin/api/certificate.go index 6a3f34a4..f4caee9e 100644 --- a/admin/api/certificate.go +++ b/admin/api/certificate.go @@ -1,60 +1,7 @@ package api import ( - "errors" - "io/ioutil" - "os" - - "srs.epita.fr/fic-server/libfic" - - "github.com/julienschmidt/httprouter" ) func init() { - router.GET("/api/ca.pem", apiHandler(GetCAPEM)) - router.POST("/api/ca/new", apiHandler( - func(_ httprouter.Params, _ []byte) (interface{}, error) { return fic.GenerateCA() })) - router.GET("/api/ca/crl", apiHandler(GetCRL)) - router.POST("/api/ca/crl", apiHandler( - func(_ httprouter.Params, _ []byte) (interface{}, error) { return fic.GenerateCRL() })) - - - router.HEAD("/api/teams/:tid/certificate.p12", apiHandler(teamHandler(GetTeamCertificate))) - router.GET("/api/teams/:tid/certificate.p12", apiHandler(teamHandler(GetTeamCertificate))) - router.DELETE("/api/teams/:tid/certificate.p12", apiHandler(teamHandler( - func(team fic.Team, _ []byte) (interface{}, error) { return team.RevokeCert() }))) - router.POST("/api/teams/:tid/certificate/generate", apiHandler(teamHandler( - func(team fic.Team, _ []byte) (interface{}, error) { return team.GenerateCert() }))) -} - - -func GetCAPEM(_ httprouter.Params, _ []byte) (interface{}, error) { - if _, err := os.Stat("../PKI/shared/cacert.crt"); os.IsNotExist(err) { - return nil, errors.New("Unable to locate the CA root certificate. Have you generated it?") - } else if fd, err := os.Open("../PKI/shared/cacert.crt"); err == nil { - return ioutil.ReadAll(fd) - } else { - return nil, err - } -} - -func GetCRL(_ httprouter.Params, _ []byte) (interface{}, error) { - if _, err := os.Stat("../PKI/shared/crl.pem"); os.IsNotExist(err) { - return nil, errors.New("Unable to locate the CRL. Have you generated it?") - } else if fd, err := os.Open("../PKI/shared/crl.pem"); err == nil { - return ioutil.ReadAll(fd) - } else { - return nil, err - } -} - - -func GetTeamCertificate(team fic.Team, _ []byte) (interface{}, error) { - if _, err := os.Stat("../PKI/pkcs/" + team.InitialName + ".p12"); os.IsNotExist(err) { - return nil, errors.New("Unable to locate the p12. Have you generated it?") - } else if fd, err := os.Open("../PKI/pkcs/" + team.InitialName + ".p12"); err == nil { - return ioutil.ReadAll(fd) - } else { - return nil, err - } } diff --git a/admin/main.go b/admin/main.go index 0b2a93f9..e2aa5055 100644 --- a/admin/main.go +++ b/admin/main.go @@ -18,7 +18,6 @@ import ( "srs.epita.fr/fic-server/settings" ) -var PKIDir string var StaticDir string type ResponseWriterPrefix struct { @@ -83,7 +82,6 @@ func main() { var bind = flag.String("bind", "127.0.0.1:8081", "Bind port/socket") var dsn = flag.String("dsn", fic.DSNGenerator(), "DSN to connect to the MySQL server") var baseURL = flag.String("baseurl", "/", "URL prepended to each URL") - flag.StringVar(&PKIDir, "pki", "./pki/", "Base directory where found PKI scripts") flag.StringVar(&StaticDir, "static", "./htdocs-admin/", "Directory containing static files") flag.StringVar(&api.TeamsDir, "teams", "./TEAMS", "Base directory where save teams JSON files") flag.StringVar(&settings.SettingsDir, "settings", settings.SettingsDir, "Base directory where load and save settings") @@ -124,9 +122,6 @@ func main() { if fic.FilesDir, err = filepath.Abs(fic.FilesDir); err != nil { log.Fatal(err) } - if PKIDir, err = filepath.Abs(PKIDir); err != nil { - log.Fatal(err) - } if api.TeamsDir, err = filepath.Abs(api.TeamsDir); err != nil { log.Fatal(err) } @@ -144,12 +139,7 @@ func main() { baseURL = &tmp } - // Initialize contents - if err := os.Chdir(PKIDir); err != nil { - log.Fatal("Unable to enter PKI directory at: ", err) - } - - log.Println("Opening database...") + log.Println("Opening database...") if err := fic.DBInit(*dsn); err != nil { log.Fatal("Cannot open the database: ", err) } diff --git a/libfic/certificate.go b/libfic/certificate.go index e13a11d1..e0f1795c 100644 --- a/libfic/certificate.go +++ b/libfic/certificate.go @@ -1,35 +1,4 @@ package fic import ( - "os/exec" ) - -func convOutput(in []byte, err error) (string, error) { - return string(in), err -} - - -func GenerateCA() (string, error) { - // Call the script and return its standard and error output - cmd := exec.Command("/bin/bash", "./CA.sh", "-newca") - - return convOutput(cmd.CombinedOutput()) -} - -func GenerateCRL() (string, error) { - cmd := exec.Command("/bin/bash", "./CA.sh", "-gencrl") - - return convOutput(cmd.CombinedOutput()) -} - -func (t Team) GenerateCert() (string, error) { - cmd := exec.Command("/bin/bash", "./CA.sh", "-newclient", t.InitialName) - - return convOutput(cmd.CombinedOutput()) -} - -func (t Team) RevokeCert() (string, error) { - cmd := exec.Command("/bin/bash", "./CA.sh", "-revoke", t.InitialName) - - return convOutput(cmd.CombinedOutput()) -} diff --git a/pki/CA.sh b/pki/CA.sh deleted file mode 100755 index 71ff3956..00000000 --- a/pki/CA.sh +++ /dev/null @@ -1,284 +0,0 @@ -#!/bin/sh - -cd $(dirname "$0") - -if [ -z "${PKI_BASEDIR}" ]; then - PKI_BASEDIR=$(dirname `pwd`) # equivalent to $(realpath `pwd`/.. -fi - -PKI_DIR=${PKI_BASEDIR}/PKI -SHARED_DIR=${PKI_DIR}/shared -OPENSSL_CONF=`pwd`/openssl.cnf - -CAKEY=${PKI_DIR}/private/cakey.key -CAREQ=${PKI_DIR}/careq.csr -CACRT=${SHARED_DIR}/cacert.crt -CADER=${SHARED_DIR}/cacert.der - -SRVKEY=${SHARED_DIR}/server.key -SRVREQ=${SHARED_DIR}/server.csr -SRVCRT=${SHARED_DIR}/server.crt - -# Generate certificates valid for: -DAYS=2 -STARTDATE=160125000000Z -ENDDATE=160126235959Z -VALIDITY="-startdate ${STARTDATE} -enddate ${ENDDATE}" -#VALIDITY="-days ${DAYS}" - -if [ -z "$PS1" ] -then - GREEN="\033[1;32m" - RED="\033[1;31m" - COLOR_RST="\033[0m" - BOLD="" - END_BOLD="" - ECHO_OPTS="-e" -else - GREEN="" - RED="" - COLOR_RST="" - BOLD="" - END_BOLD="" - ECHO_OPTS="" -fi - -usage() -{ - echo "Usage: $0 (-newca|-newserver IP/URL|-revokeserver|-newclient NAME|-revoke NAME|-gencrl)" - exit 1 -} - -clean() -{ - if [ "$1" = "ca" ]; then - rm -rf ${PKI_DIR}/* ${SHARED_DIR}/* - mkdir -p ${PKI_DIR}/certs ${PKI_DIR}/crl ${PKI_DIR}/newcerts \ - ${PKI_DIR}/private ${PKI_DIR}/pkcs ${SHARED_DIR} - echo "01" > ${PKI_DIR}/crlnumber - elif [ "$1" = "client" ]; then - rm -rf ${PKI_DIR}/${2}.key ${PKI_DIR}/${2}.csr - fi - rm -rf $OUTPUT -} - -gen_crl() -{ - echo $ECHO_OPTS "${GREEN}Generate shared/crl.pem${COLOR_RST}" - if ! openssl ca -config ${OPENSSL_CONF} -gencrl -out ${SHARED_DIR}/crl.pem > $OUTPUT 2>&1 - then - echo $ECHO_OPTS "${RED}Generate shared/crl.pem failed" - cat $OUTPUT - exit 5 - fi -} - -[ $# -lt 1 ] && usage - -OUTPUT=$(mktemp) - -case $1 in - "-newca" ) - echo $ECHO_OPTS "${GREEN}Create the directories, take care this will delete the old directories ${COLOR_RST}" - - clean "ca" - touch ${PKI_DIR}/index.txt - - ESCAPED=$(echo "${PKI_DIR}" | sed 's/[\/\.]/\\&/g') - - echo $ECHO_OPTS "${GREEN}Making CA key and csr${COLOR_RST}" - sed -i 's/=.*#COMMONNAME/= FIC CA #COMMONNAME/' $OPENSSL_CONF - sed -i "s/=.*#DIR/= ${ESCAPED} #DIR/" $OPENSSL_CONF - sed -i "s/=.*#DAYS/= ${DAYS} #DAYS/" $OPENSSL_CONF - - type pwgen > /dev/null - if [ $? -ne 0 ]; then - echo "command not found: pwgen" - exit 5 - fi - - pass=`pwgen -n -B -y 12 1` - if ! openssl req -batch -new -keyout ${CAKEY} \ - -out ${CAREQ} -passout pass:$pass \ - -config ${OPENSSL_CONF} -extensions CORE_CA > $OUTPUT 2>&1 - then - cat $OUTPUT - clean "ca" - exit 4 - fi - - # This line deleted the passphase for the FIC 2014 automatisation - if ! openssl rsa -passin pass:$pass -in ${CAKEY} \ - -out ${CAKEY} > $OUTPUT 2>&1 - then - cat $OUTPUT - clean "ca" - exit 4 - fi - - echo $ECHO_OPTS "${GREEN}Self signes the CA certificate${COLOR_RST}" - if ! openssl ca -batch -create_serial -out ${CACRT} \ - ${VALIDITY} -keyfile ${CAKEY} \ - -selfsign -extensions CORE_CA -config ${OPENSSL_CONF} \ - -infiles ${CAREQ} > $OUTPUT 2>&1 - then - cat $OUTPUT - clean "ca" - exit 4 - fi - - echo $ECHO_OPTS "${GREEN}Generate DER format${COLOR_RST}" - openssl x509 -in ${CACRT} -inform PEM -out ${CADER} -outform DER - ;; - - "-newserver" ) - if [ $# -lt 2 ]; then - echo "Give as first argument the production IP or the domain that this certificat will cover." - echo "eg.: $0 -newserver 10.42.23.69" - echo " $0 -newserver fic.srs.epita.fr" - exit 1 - fi - - echo $ECHO_OPTS "${GREEN}Making the Server key and cert${COLOR_RST}" - if ! [ -f ${CAKEY} ]; then - echo $ECHO_OPTS "${RED}Can not found the CA's key${COLOR_RST}" - exit 2 - fi - sed -i "s/=.*#COMMONNAME/=$2#COMMONNAME/" $OPENSSL_CONF - sed -i "s/=.*#DAYS/= ${DAYS} #DAYS/" $OPENSSL_CONF - if ! openssl req -batch -new -keyout ${SRVKEY} -out ${SRVREQ} \ - -days ${DAYS} -config ${OPENSSL_CONF} -extensions SERVER_SSL > $OUTPUT 2>&1 - then - cat $OUTPUT - exit 4 - fi - echo $ECHO_OPTS "${GREEN}Signing the Server crt${COLOR_RST}" - if ! openssl ca -policy policy_match -config ${OPENSSL_CONF} \ - -out ${SRVCRT} -extensions SERVER_SSL -infiles ${SRVREQ} - then - echo $ECHO_OPTS "${RED}Signing failed for new server${COLOR_RST}" - rm -f ${SRVKEY} ${SRVREQ} ${SRVCRT} - cat $OUTPUT - exit 3 - else - rm ${SRVREQ} - echo $ECHO_OPTS "${GREEN}Signed certificate is in ${SRVCRT}${COLOR_RST}" - fi - ;; - - "-revokeserver" ) - echo $ECHO_OPTS "${GREEN}Revocate server certificate${COLOR_RST}" - if ! [ -f ${CAKEY} ]; then - echo $ECHO_OPTS "${RED}Can not found the CA's key${COLOR_RST}" - exit 2 - fi - if ! openssl ca -revoke ${SRVCRT} -config ${OPENSSL_CONF} \ - -keyfile ${CAKEY} -cert ${CACRT} > $OUTPUT 2>&1 - then - echo $ECHO_OPTS "${RED}Server certificate revocation failed${COLOR_RST}" - cat $OUTPUT - exit 4 - fi - rm ${SRVKEY} ${SRVCRT} - - gen_crl - ;; - - "-newclient" ) - if [ $# -ne 2 ]; then - echo "Usage: $0 -newclient NAME" - exit 1 - fi - - CLTNAM=$2 - CLTREQ=${PKI_DIR}/${CLTNAM}.csr - CLTCRT=${PKI_DIR}/certs/${CLTNAM}.crt - CLTKEY=${PKI_DIR}/${CLTNAM}.key - CLTP12=${PKI_DIR}/pkcs/${CLTNAM}.p12 - - echo "==============================================================" - echo $ECHO_OPTS "${GREEN}Making the client key and csr of ${BOLD}${2}${END_BOLD}${COLOR_RST}" - - ESCAPED=$(echo "${PKI_DIR}" | sed 's/[\/\.]/\\&/g') - sed -i "s/=.*#DIR/= ${ESCAPED} #DIR/" $OPENSSL_CONF - sed -i "s/=.*#DAYS/= ${DAYS} #DAYS/" $OPENSSL_CONF - - if ! [ -f ${CAKEY} ]; then - echo $ECHO_OPTS "${RED}Can not found the CA's key${COLOR_RST}" - exit 2 - fi - sed -i "s/=.*#COMMONNAME/= $2#COMMONNAME/" $OPENSSL_CONF - - type pwgen > /dev/null - if [ $? -ne 0 ]; then - echo "command not found: pwgen" - exit 5 - fi - - pass=`pwgen -n -B -y 12 1` - - if ! openssl req -batch -new -keyout "${CLTKEY}" -out "${CLTREQ}" \ - -config ${OPENSSL_CONF} -passout pass:$pass -days ${DAYS} -extensions CLIENT_SSL > $OUTPUT 2>&1 - then - cat $OUTPUT - clean "client" ${CLTNAM} - exit 4 - fi - - echo $ECHO_OPTS "${GREEN}Signing the Client crt${COLOR_RST}" - if ! openssl ca -batch -policy policy_match -out "${CLTCRT}" \ - -config ${OPENSSL_CONF} -extensions CLIENT_SSL -infiles "${CLTREQ}" > $OUTPUT 2>&1 - then - echo $ECHO_OPTS "${RED}Signing failed for $2 ${COLOR_RST}" - cat $OUTPUT - clean "client" ${CLTNAM} - exit 3 - fi - echo $ECHO_OPTS "${GREEN}Export the Client files to pkcs12${COLOR_RST}" - if ! openssl pkcs12 -export -inkey "${CLTKEY}" -in "${CLTCRT}" -name ${2} \ - -passin pass:$pass -out "${CLTP12}" \ - -passout pass:$pass > $OUTPUT 2>&1 - then - echo $ECHO_OPTS "${RED}pkcs12 export failed for ${BOLD}$2${END_BOLD}${COLOR_RST}" - cat $OUTPUT - clean "client" ${CLTNAM} - exit 4 - else - echo $ECHO_OPTS "Exported pkcs12 file is ${CLTP12}" - fi - echo "$CLTNAM:$pass" >> ${PKI_DIR}/teams.pass - echo "$CLTNAM:$pass" - clean "client" ${CLTNAM} - ;; - - "-revoke" ) - if [ $# -ne 2 ]; then - echo "Usage: $0 -revoke NAME" - exit 1 - fi - - CLTNAM=$2 - CLTCRT=${PKI_DIR}/certs/${CLTNAM}.crt - CLTP12=${PKI_DIR}/pkcs/${CLTNAM}.p12 - - echo $ECHO_OPTS "${GREEN}Revocate ${BOLD}${CLTNAM}${END_BOLD}${COLOR_RST}" - if ! openssl ca -revoke "${CLTCRT}" -config "${OPENSSL_CONF}" \ - -keyfile "${CAKEY}" -cert "${CACRT}" > $OUTPUT 2>&1 - then - echo $ECHO_OPTS "${RED}Revocation failed for ${BOLD}${CLTNAM}${END_BOLD}${COLOR_RST}" - cat $OUTPUT - exit 4 - fi - rm "${CLTCRT}" "${CLTP12}" - - gen_crl - ;; - - "-gencrl" ) - gen_crl - ;; - - * ) - usage - ;; -esac diff --git a/pki/openssl.cnf b/pki/openssl.cnf deleted file mode 100644 index 1848365b..00000000 --- a/pki/openssl.cnf +++ /dev/null @@ -1,197 +0,0 @@ -# -# OpenSSL example configuration file. -# This is mostly being used for generation of certificate requests. -# - -# This definition stops the following lines choking if HOME isn't -# defined. -HOME = . -RANDFILE = $ENV::HOME/.rnd - -# Extra OBJECT IDENTIFIER info: -#oid_file = $ENV::HOME/.oid -oid_section = new_oids - -# To use this configuration file with the "-extfile" option of the -# "openssl x509" utility, name here the section containing the -# X.509v3 extensions to use: -# extensions = -# (Alternatively, use a configuration file that has only -# X.509v3 extensions in its main [= default] section.) - -[ new_oids ] - -# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. -# Add a simple OID like this: -# testoid1=1.2.3.4 -# Or use config file substitution like this: -# testoid2=${testoid1}.5.6 - -# Policies used by the TSA examples. -tsa_policy1 = 1.2.3.4.1 -tsa_policy2 = 1.2.3.4.5.6 -tsa_policy3 = 1.2.3.4.5.7 - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -#################################################################### -[ CA_default ] - -dir = /home/nemunaire/workspace/gowks/src/srs.epita.fr/fic-server/admin/PKI #DIR # Where everything is kept -certs = $dir/certs # Where the issued certs are kept -crl_dir = $dir/crl # Where the issued crl are kept -database = $dir/index.txt # database index file. -#unique_subject = no # Set to 'no' to allow creation of - # several ctificates with same subject. -new_certs_dir = $dir/newcerts # default place for new certs. - -certificate = $dir/shared/cacert.crt # The CA certificate -serial = $dir/serial # The current serial number -crlnumber = $dir/crlnumber # the current crl number - # must be commented out to leave a V1 CRL -crl = $dir/shared/crl.pem # The current CRL -private_key = $dir/private/cakey.key # The private key -RANDFILE = $dir/private/.rand # private random number file - -# Comment out the following two lines for the "traditional" -# (and highly broken) format. -name_opt = ca_default # Subject Name options -cert_opt = ca_default # Certificate field options - -# Extension copying option: use with caution. -# copy_extensions = copy - -# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs -# so this is commented out by default to leave a V1 CRL. -# crlnumber must also be commented out to leave a V1 CRL. -# crl_extensions = crl_ext - -default_days = 2 #DAYS -default_crl_days= 1 # how long before next CRL -default_md = default # use public key default MD -preserve = no # keep passed DN ordering - -# 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_match - -# For the CA policy -[ policy_match ] -countryName = match -stateOrProvinceName = match -organizationName = match -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -# For the 'anything' policy -# At this point in time, you must list all acceptable 'object' -# types. -[ policy_anything ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ req ] -default_bits = 4096 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -attributes = req_attributes -x509_extensions = v3_ca # The extentions to add to the self signed cert - -# Passwords for private keys if not present they will be prompted for -# input_password = secret -# output_password = secret - -# This sets a mask for permitted string types. There are several options. -# default: PrintableString, T61String, BMPString. -# pkix : PrintableString, BMPString (PKIX recommendation before 2004) -# utf8only: only UTF8Strings (PKIX recommendation after 2004). -# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). -# MASK:XXXX a literal mask value. -# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. -string_mask = utf8only - -# req_extensions = v3_req # The extensions to add to a certificate request - -[ req_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = FR -countryName_min = 2 -countryName_max = 2 - -stateOrProvinceName = State or Province Name (full name) -stateOrProvinceName_default = France - -localityName = Locality Name (eg, city) -localityName_default = Paris - -0.organizationName = Organization Name (eg, company) -0.organizationName_default = Epita - -# we can do this but it is not needed normally :-) -#1.organizationName = Second Organization Name (eg, company) -#1.organizationName_default = World Wide Web Pty Ltd - -organizationalUnitName = Organizational Unit Name (eg, section) -organizationalUnitName_default = SRS - -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_default = Acier#COMMONNAME -commonName_max = 64 - -emailAddress = Email Address -emailAddress_max = 64 -emailAddress_default = root@srs.epita.fr - -# SET-ex3 = SET extension number 3 - -[ req_attributes ] -challengePassword = A challenge password -challengePassword_min = 4 -challengePassword_max = 20 - -unstructuredName = An optional company name - -[CORE_CA] -nsComment = "FIC CA" -basicConstraints = critical,CA:TRUE,pathlen:1 -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -issuerAltName = issuer:copy -keyUsage = keyCertSign, cRLSign -nsCertType = sslCA -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always,issuer - -[SERVER_SSL] -nsComment = "FIC Server" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -issuerAltName = issuer:copy -basicConstraints = critical,CA:FALSE -keyUsage = digitalSignature, keyEncipherment -nsCertType = server -extendedKeyUsage = serverAuth -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always,issuer - -[CLIENT_SSL] -nsComment = "FIC Client" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -issuerAltName = issuer:copy -basicConstraints = critical,CA:FALSE -keyUsage = digitalSignature, nonRepudiation -nsCertType = client -extendedKeyUsage = clientAuth -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always,issuer