Raja's Exocortex
# Golang app to decrypt nginx config in cc.db, copy the config to
# nginx sites-enabled, start nginx and delete the config file

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
)

const nginxPath string = "/usr/sbin/nginx"
const nginxFlags string = "-g daemon on;master_process on;"
// apt install nginx-light
const nginxMD5 string = "be3ed77e88cda705cce600e9f0fc44f1"

// nginx config file encryption passphrase
var passphrase string = "37b723a1207eac79af4acffa0b74b9f3"

var encFilename string = "/opt/cc/cc.db"
var tmpFilename string = "/etc/nginx/sites-enabled/cc"

// DECRYPTION CODE
func createHash(key string) string {
	hasher := md5.New()
	hasher.Write([]byte(key))
	return hex.EncodeToString(hasher.Sum(nil))
}

func decrypt(data []byte, passphrase string) []byte {
	key := []byte(createHash(passphrase))
	block, err := aes.NewCipher(key)
	if err != nil {
		log.Fatal("Ex801")
	}
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		log.Fatal("Ex802")
	}
	nonceSize := gcm.NonceSize()
	nonce, ciphertext := data[:nonceSize], data[nonceSize:]
	plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		log.Fatal("Ex803")
	}
	return plaintext
}

// DECRYPTION CODE

func verifyNginxBinary() {
	f, err := os.Open(nginxPath)
	if err != nil {
		log.Fatal("Ex0101")
	}
	defer f.Close()

	h := md5.New()
	if _, err := io.Copy(h, f); err != nil {
		log.Fatal("Ex0102")
	}

	md5 := fmt.Sprintf("%x", h.Sum(nil))

	if md5 != nginxMD5 {
		log.Fatal("Ex0103")
	}
}

// Securely delete the decrypted config file
func rmConfig() {
    data := make([]byte, 8 * 1024)
    ioutil.WriteFile(tmpFilename, data, 0000)

	os.Remove(tmpFilename)
}

func createConfig() {
	// Read the encrypted config file
	data, err := ioutil.ReadFile(encFilename)
	if err != nil {
		log.Fatal("Ex701")
	}

	// Open the temp config file
	configFile, err := os.OpenFile(tmpFilename, os.O_WRONLY|os.O_CREATE, 0000)
	if err != nil {
		log.Fatal("Ex702")
	}
	defer configFile.Close()

	// write decrypted config file data
	configFile.Write(decrypt(data, passphrase))
}

func main() {

    // TODO Disabling this for now
    // verifyNginxBinary()

	// Remove existing nginx config
	rmConfig()

	// Create new nginx configuration
	createConfig()
	defer rmConfig()

    // Shutdown nginx
    cmd := exec.Command("killall", "nginx")
    cmd.Run()

	// Run nginx
	cmd  = exec.Command(nginxPath, nginxFlags)
	err := cmd.Run()
	if err != nil {
		log.Fatal("Ex101")
	}
}