#!/bin/bash
#
# create Domainkey
#
# Author: Joerg Backschues
# Modified by: Roberto Puzzanghera
# Modified by: Tatsuya Yokota (https://github.com/kotaroman/domainkey)
#

#CONFIGDIR="/usr/local/etc/domainkeys"
CONFIGDIR="/var/qmail/control/domainkeys"

# DKIMSIGNOPTIONS="-z 2" is required when 2048 bit
#BIT=1024
BIT=2048

# Create a separated key for each domain in $CONFIGDIR/$DOMAIN. Comment out to disable and a have the same key for all domains
#DK_SHARED=1

# Number of characters to split
SPLIT=255

# Use this if you are going to sign at qmail-remote level
CHOWN_USER_GROUP="qmailr:qmail"
# Use this if you are going to sign at qmail-smtpd level. The domainkey dir must be owned by the user who runs qmail-smtpd
#CHOWN_USER_GROUP="vpopmail:vchkpw"

if [ "$1" = "" ] ; then
    echo;
    echo "Usage: $0 [-p] domain [selector]";
    echo "       Create domainkey";
    echo "       Print domainkey with -p";
    echo;
    exit 1;
fi

function split_str () {

    DOMAIN=$1

    if [ -n "$DK_SHARED" ]; then
      DIR=""
    else
      DIR="/${DOMAIN}"
    fi

    STR="`grep -v -e "^-" ${CONFIGDIR}${DIR}/rsa.public_$SELECTOR | tr -d "\n"`"
    STR="v=DKIM1; k=rsa; t=y; p=${STR}"

    if [ $BIT = 2048 ]; then
        echo -n "("
    fi

    STR_COUNT=0
    while true
    do
        START=$STR_COUNT
        STR_COUNT=`expr $STR_COUNT + $SPLIT`
        LINE=${STR:$START:$SPLIT}

        if [ ${#LINE} -eq 0 ]; then
            break
        fi

        if [ $START -ne 0 ]; then
            OPTION="-e"
            if [ ${#LINE} -ne $SPLIT ]; then
                OPTION="-en"
            fi
            echo $OPTION "\t\"${LINE}\""
        else
            echo \"${LINE}\"
        fi
    done

    if [ $BIT = 2048 ]; then
        echo -n ")"
    fi
}

# Create the key
function create_dk () {
    SELECTOR=$2

    if [ -n "$DK_SHARED" ]; then
      DIR=""
    else
      DIR="/${1}"
    fi

    test -f ${CONFIGDIR}${DIR}/rsa.private_$SELECTOR && { echo; echo "Domainkey for domain \"$1\" with selector \"$SELECTOR\" already exists."; echo; exit 1;}

    mkdir -p ${CONFIGDIR}${DIR}

    echo $SELECTOR > ${CONFIGDIR}${DIR}/selector

    openssl genrsa -out ${CONFIGDIR}${DIR}/rsa.private_$SELECTOR $BIT
    openssl rsa -in ${CONFIGDIR}${DIR}/rsa.private_$SELECTOR -out ${CONFIGDIR}${DIR}/rsa.public_$SELECTOR -pubout -outform PEM

    ln -sf ${CONFIGDIR}${DIR}/rsa.private_$SELECTOR ${CONFIGDIR}${DIR}/$SELECTOR

    chmod 0700 $CONFIGDIR
    if [ -n "$DIR" ]; then
      chmod 0700 $CONFIGDIR/$1
    fi
    chmod 0600 ${CONFIGDIR}${DIR}/*
    chown -R $CHOWN_USER_GROUP $CONFIGDIR
}

# print the key
function print_dk () {

    DOMAIN=$1
    SELECTOR=$2

    if [ -n "$DK_SHARED" ]; then
      DIR=""
    else
      DIR="/${DOMAIN}"
    fi

    test -f ${CONFIGDIR}${DIR}/rsa.public_$SELECTOR || { echo; echo "Domainkey for domain \"$DOMAIN\" with selector \"$SELECTOR\" does not exist."; echo; exit 1;}

    # <selector>._domainkey.<domain>. IN TXT "<domainkey>"

    echo -e "\nTXT record for BIND:"
    echo -n "$SELECTOR._domainkey.$DOMAIN. IN TXT "
    split_str "$DOMAIN"
    echo
}


case "$1" in

    "-p")
    #
    # print domainkey
    #

    SELECTOR=$3

    if [ "$SELECTOR" = "" ] ; then
        SELECTOR="default"
    fi

    print_dk $2 $SELECTOR

    exit 0
    ;;


    *)
    #
    # create domainkey
    #

    SELECTOR=$2

    if [ "$SELECTOR" = "" ] ; then
        SELECTOR="default"
    fi

    create_dk $1 $SELECTOR

    # <selector>._domainkey.<domain>. IN TXT "<domainkey>"

    echo -e "\nTXT record for BIND:"
    echo -n "$SELECTOR._domainkey.$1. IN TXT "
    split_str "$1"
    echo

    exit 0
    ;;

esac
