#!/bin/sh

# custom-ca-mgr status
# custom-ca-mgr refresh
# custom-ca-mgr restore

USER_DIR=/mnt/data/ca-certificates
SYS_DIR=/usr/share/ca-certificates/barix
CACERTS_CONF=/etc/ca-certificates.conf

#USER_DIR=$(pwd)/user-certs
#SYS_DIR=$(pwd)/sys-certs
#CACERTS_CONF=$(pwd)/ca-certificates.conf

CONTROL_DIR=$SYS_DIR.installed

run_update() {
    update-ca-certificates
}

get_ca_status() {
    #echo "checking $CERT ..." 1>&2
    if test -f $USER_DIR/$CERT && test -f $CONTROL_DIR/$CERT; then
        echo -n "INSTALLED"
    elif test -f $USER_DIR/$CERT && test ! -f $CONTROL_DIR/$CERT; then
        echo -n "INSTALL_PENDING"
    elif test ! -f $USER_DIR/$CERT && test -f $CONTROL_DIR/$CERT; then
        echo -n "REMOVE_PENDING"
    else
        echo -n "BROKEN"
    fi    
}


#
# (cert) -> true|false
in_cfgfile() {
    CERT="$(basename $1)"
    M=$(cat $CACERTS_CONF | grep -E "^barix/$CERT$")
    if [ -n "$M" ]; then
        true
    else
        false
    fi
}


install_ca() {
    CERT=$1
    
    rm -f $CONTROL_DIR/$CERT
    rm -f $SYS_DIR/$CERT
    ln -s $USER_DIR/$CERT $SYS_DIR/$CERT
    
    if ! in_cfgfile $CERT; then
        echo "barix/$CERT" >> $CACERTS_CONF
    fi
    
    if run_update; then
        touch $CONTROL_DIR/$CERT
    fi    
}


remove_ca() {
    CERT=$1
    if in_cfgfile $CERT; then
        echo "$CERT appears to be installed. Marking for removal..."
        sed -i "s|^barix/$CERT$|!barix/$CERT|" $CACERTS_CONF
        run_update
    fi
    cat $CACERTS_CONF | sed "s|^!barix/$CERT$||" | sed '/^$/d' > $CACERTS_CONF.tmp
    cp $CACERTS_CONF.tmp $CACERTS_CONF
    rm -f $SYS_DIR/$CERT
    rm -f $USER_DIR/$CERT
    rm -f $CONTROL_DIR/$CERT
}


refresh() {
    for CERT in $(ls $USER_DIR/); do
        S=$(get_ca_status $CERT)
        case "$S" in
            INSTALL_PENDING)
                echo "Installing: $CERT ..."            
                install_ca $CERT
                ;;
            
            INSTALLED)
                echo "Up to date: $CERT"
                ;;
                
            *)
                ;;
        esac
    done
    
    for CERT in $(ls $CONTROL_DIR/); do
        case "$(get_ca_status $CERT)" in
            REMOVE_PENDING)
                echo "Removing: $CERT ..."
                remove_ca $CERT
                ;;
            
            BROKEN)
                echo "Cleaning up [broken] $CERT ..."
                remove_ca $CERT
                ;;
                
            *)
                ;;
        esac
    done

    for CERT in $(ls $SYS_DIR/); do
        case "$(get_ca_status $CERT)" in
            BROKEN)
                echo "Cleaning up [broken] $CERT ..."
                remove_ca $CERT
                ;;
                
            *)
                ;;
        esac
    done
}


status() {
    for CERT in $(ls $USER_DIR/); do
        #echo "checking USER: $CERT"
        S=$(get_ca_status $CERT)
        #echo "got '$S'"
        case "$S" in
            INSTALLED|INSTALL_PENDING)
                echo "$S $CERT"
                ;;
                
            "*")
                ;;
        esac
    done

    for CERT in $(ls $CONTROL_DIR/); do
        #echo "checking SYS: $CERT"
        S=$(get_ca_status $CERT)
        #echo "got '$S'"
        case "$S" in
            REMOVE_PENDING)
                echo "$S $CERT"
                ;;
                
            BROKEN)
                echo "$S $CERT"
                ;;
                
            *)
                ;;
        esac
    done
}


restore() {
    cp $CACERTS_CONF.original $CACERTS_CONF
    run_update
    rm -f $SYS_DIR/*
    rm -f $USER_DIR/*
}


test -d $SYS_DIR || mkdir -p $SYS_DIR
test -d $CONTROL_DIR || mkdir -p $CONTROL_DIR
test -f $CACERTS_CONF.original || cp $CACERTS_CONF $CACERTS_CONF.original


if [ $# -ne 1 ]; then
    echo "usage $0 status|refresh|restore"
    exit 1
fi

case "$1" in
    refresh)
        refresh
        ;;
        
    status)
        status
        ;;
        
    restore)
        restore
        ;;
        
    *)
        echo "usage $0 status|refresh|restore"
        exit 1
        ;;
esac
