Jonathan Turner пре 9 година
родитељ
комит
bc8d60b1d8

+ 18 - 0
crypto/aes-cts-hmac-sha1-96.go

@@ -4,12 +4,14 @@ import (
 	"bytes"
 	"crypto/aes"
 	"crypto/cipher"
+	"crypto/hmac"
 	"crypto/sha1"
 	"encoding/binary"
 	"encoding/hex"
 	"errors"
 	"fmt"
 	"golang.org/x/crypto/pbkdf2"
+	"os"
 	"strings"
 )
 
@@ -232,6 +234,22 @@ func swapLastTwoBlocks(b []byte, c int) ([]byte, error) {
 	return out, nil
 }
 
+func VerifyChecksum(ct, pt, key []byte, usage int, etype EType) bool {
+	//The ciphertext output is the concatenation of the output of the basic
+	//encryption function E and a (possibly truncated) HMAC using the
+	//specified hash function H, both applied to the plaintext with a
+	//random confounder prefix and sufficient padding to bring it to a
+	//multiple of the message block size.  When the HMAC is computed, the
+	//key is used in the protocol key form.
+	h := ct[len(ct)-12:]
+	k, _ := etype.DeriveKey(key, GetUsageKi(uint32(usage)))
+	mac := hmac.New(sha1.New, k)
+	mac.Write(pt)
+	expectedMAC := mac.Sum(nil)
+	fmt.Fprintf(os.Stderr, "%v\n%v", h, expectedMAC[:12])
+	return hmac.Equal(h, expectedMAC[:12])
+}
+
 /*func DEwithHMAC(key, message []byte) (ct []byte, err error) {
 	if len(key) != KeySize {
 		return nil, fmt.Errorf("Incorrect keysize: expected: %v actual: %v", KeySize, len(key))

+ 4 - 0
messages/KDCRep.go

@@ -67,6 +67,10 @@ func (k *KDCRep) DecryptEncPart(kt keytab.Keytab) error {
 	// Strip off the checksum from the end
 	//TODO should this check be moved to the Decrypt method?
 	b, err := etype.Decrypt(key, k.EncPart.Cipher[:len(k.EncPart.Cipher)-etype.GetHMACBitLength()/8])
+	//Verify checksum
+	if !crypto.VerifyChecksum(k.EncPart.Cipher, b, kt.Entries[0].Key.KeyMaterial, 3, etype) {
+		return errors.New("Error decrypting encrypted part: checksum verification failed")
+	}
 	//Remove the confounder bytes
 	b = b[etype.GetConfounderByteSize():]
 	if err != nil {

+ 2 - 0
testenv/krb5kdc-vagrant/.gitignore

@@ -0,0 +1,2 @@
+.vagrant
+.vagrant/*

+ 12 - 0
testenv/krb5kdc-vagrant/Vagrantfile

@@ -0,0 +1,12 @@
+Vagrant.configure("2") do |config|
+  config.vm.provider "virtualbox" do |v|
+    v.memory = 1024
+    v.cpus = 1
+  end
+  config.vm.define "krb5kdc", primary: true do |krb5kdc|
+    krb5kdc.vm.hostname = "kdc.test.gokrb5"
+    krb5kdc.vm.box = "centos/7"
+    krb5kdc.vm.network "private_network", ip: "10.80.88.88", netmask: "255.255.0.0"
+    krb5kdc.vm.provision :shell, path: "bootstrap.sh"
+  end
+end

+ 25 - 0
testenv/krb5kdc-vagrant/bootstrap.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+rm /etc/localtime
+ln -s /usr/share/zoneinfo/Europe/London /etc/localtime
+setenforce 0
+sed -i "s/SELINUX=enforcing/SELINUX=permissive/g" /etc/sysconfig/selinux
+
+yum update -y && yum clean all
+yum install -y krb5-server krb5-workstation httpd mod_auth_kerb mod_ssl
+
+systemctl stop firewalld
+systemctl disable firewalld
+
+cat <<EOF >> /etc/sysctl.conf
+net.ipv6.conf.all.disable_ipv6 = 1
+net.ipv6.conf.default.disable_ipv6 = 1
+net.ipv6.conf.lo.disable_ipv6 = 1
+EOF
+
+echo "10.80.88.89 client.test.gokrb5" >> /etc/hosts
+
+
+sh /vagrant/kdc-setup.sh
+
+reboot

+ 4 - 0
testenv/krb5kdc-vagrant/kadm5.acl

@@ -0,0 +1,4 @@
+__ADMIN_USER__@__REALM__	*
+*/admin@__REALM__	*
+*/*@__REALM__		i
+*@__REALM__		i

+ 93 - 0
testenv/krb5kdc-vagrant/kdc-setup.sh

@@ -0,0 +1,93 @@
+#!/bin/bash
+
+
+REALM=TEST.GOKRB5
+DOMAIN=test.gokrb5
+SERVER_HOST=kdc.test.gokrb5
+ADMIN_USERNAME=adminuser
+HOST_PRINCIPALS="kdc.test.gokrb5 host.test.gokrb5"
+SPNs="HTTP/host.test.gokrb5"
+KEYTABS="http.keytab!0:48!HTTP/host.test.gokrb5"
+INITIAL_USERS="testuser1 testuser2 testuser3"
+
+cp /vagrant/krb5.conf /etc/krb5.conf
+cp /var/kerberos/krb5kdc/kdc.conf /var/kerberos/krb5kdc/kdc.conf-old
+cp /vagrant/kdc.conf /var/kerberos/krb5kdc/kdc.conf
+cp /vagrant/kadm5.acl /var/kerberos/krb5kdc/kadm5.acl
+
+sed -i "s/__ADMIN_USER__/${ADMIN_USERNAME}/g" /var/kerberos/krb5kdc/kadm5.acl
+sed -i "s/__REALM__/${REALM}/g" /var/kerberos/krb5kdc/kadm5.acl
+sed -i "s/__REALM__/${REALM}/g" /var/kerberos/krb5kdc/kdc.conf
+sed -i "s/__REALM__/${REALM}/g" /etc/krb5.conf
+sed -i "s/__DOMAIN__/${DOMAIN}/g" /etc/krb5.conf
+sed -i "s/__SERVER_HOST__/${SERVER_HOST}/g" /etc/krb5.conf
+
+#Check and initialise if needs be
+if [ ! -f /opt/krb5/data/principal ]; then
+  echo "Kerberos initialisation required. Creating database for ${REALM} ..."
+  echo "This can take some time if there is little entropy. SSH in another terminal and hit some keys..."
+  MASTER_PASSWORD=$(echo $RANDOM$RANDOM$RANDOM | md5sum | awk '{print $1}')
+  /usr/sbin/kdb5_util create -r ${REALM} -s -P ${MASTER_PASSWORD}
+  echo "Kerberos database created."
+  /usr/sbin/kadmin.local -q "add_principal -randkey ${ADMIN_USERNAME}/admin"
+  echo "Kerberos admin user created: ${ADMIN_USERNAME} To update password: sudo /usr/sbin/kadmin.local -q \"change_password ${ADMIN_USERNAME}/admin\""
+
+  KEYTAB_DIR="/opt/krb5/data/keytabs"
+  mkdir -p $KEYTAB_DIR
+
+  if [ ! -z "${HOST_PRINCIPALS}" ]; then
+    for host in ${HOST_PRINCIPALS}
+    do
+      /usr/sbin/kadmin.local -q "add_principal -randkey host/$host"
+      /usr/sbin/kadmin.local -q "ktadd -k ${KEYTAB_DIR}/${host}.keytab host/$host"
+      chmod 600 ${KEYTAB_DIR}/${host}.keytab
+      echo "Created host principal host/$host"
+    done
+  fi
+
+  if [ ! -z "${SPNs}" ]; then
+    for service in ${SPNs}
+    do
+      /usr/sbin/kadmin.local -q "add_principal -randkey ${service}"
+      echo "Created principal for service $service"
+    done
+  fi
+
+  if [ ! -z "$INITIAL_USERS" ]; then
+    for user in $INITIAL_USERS
+    do
+      /usr/sbin/kadmin.local -q "add_principal -randkey $user"
+      echo "User $user added to kerberos database with random password. To update password: sudo /usr/sbin/kadmin.local -q \"change_password $user\""
+    done
+  fi
+
+  if [ ! -z "$KEYTABS" ]; then
+    echo "Exporting keytabs"
+    OLDIFS=$IFS
+    IFS=";"
+    KEYTAB=($KEYTABS)
+    for keytabInst in ${KEYTAB[@]}
+    do
+      keytabFileName=$(echo $keytabInst | cut -d! -f1)
+      permissions=$(echo $keytabInst | cut -d! -f2)
+      principals=$(echo $keytabInst | cut -d! -f3)
+      IFS=" "
+      for princ in $principals
+      do
+        /usr/sbin/kadmin.local -q "ktadd -k ${KEYTAB_DIR}/${keytabFileName} $princ"
+        echo "Add principal ${princ} to ${keytabFileName}"
+      done
+      IFS=";"
+      chown $permissions ${KEYTAB_DIR}/${keytabFileName}
+      chmod 440 ${KEYTAB_DIR}/${keytabFileName}
+    done
+    IFS=$OLDIFS
+  fi
+
+  echo "Kerberos initialisation complete"
+fi
+
+
+
+systemctl restart krb5kdc
+systemctl enable krb5kdc

+ 14 - 0
testenv/krb5kdc-vagrant/kdc.conf

@@ -0,0 +1,14 @@
+[kdcdefaults]
+ kdc_ports = 88
+ kdc_tcp_ports = 88
+
+[realms]
+ __REALM__ = {
+  master_key_type = aes256-cts
+  max_life = 12h 0m 0s
+  max_renewable_life = 7d 0h 0m 0s
+  acl_file = /var/kerberos/krb5kdc/kadm5.acl
+  dict_file = /usr/share/dict/words
+  admin_keytab = /opt/krb5/data/kadm5.keytab
+  supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
+ }

+ 32 - 0
testenv/krb5kdc-vagrant/krb5.conf

@@ -0,0 +1,32 @@
+[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+
+[libdefaults]
+  default_realm = __REALM__
+  dns_lookup_realm = false
+  dns_lookup_kdc = false
+  ticket_lifetime = 24h
+  forwardable = yes
+
+[realms]
+ __REALM__ = {
+  kdc = __SERVER_HOST__:88
+  admin_server = __SERVER_HOST__:749
+  default_domain = __DOMAIN__
+ }
+
+[domain_realm]
+ .__DOMAIN__ = __REALM__
+ __DOMAIN__ = __REALM__
+
+[appdefaults]
+ pam = {
+   debug = false
+   ticket_lifetime = 36000
+   renew_lifetime = 36000
+   forwardable = true
+   krb4_convert = false
+ }

+ 2 - 0
testenv/krbclient-vagrant/.gitignore

@@ -0,0 +1,2 @@
+.vagrant
+.vagrant/*

+ 12 - 0
testenv/krbclient-vagrant/Vagrantfile

@@ -0,0 +1,12 @@
+Vagrant.configure("2") do |config|
+  config.vm.provider "virtualbox" do |v|
+    v.memory = 1024
+    v.cpus = 1
+  end
+  config.vm.define "krb5kdc", primary: true do |krb5kdc|
+    krb5kdc.vm.hostname = "client.test.gokrb5"
+    krb5kdc.vm.box = "centos/7"
+    krb5kdc.vm.network "private_network", ip: "10.80.88.89", netmask: "255.255.0.0"
+    krb5kdc.vm.provision :shell, path: "bootstrap.sh"
+  end
+end

+ 24 - 0
testenv/krbclient-vagrant/bootstrap.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+rm /etc/localtime
+ln -s /usr/share/zoneinfo/Europe/London /etc/localtime
+setenforce 0
+sed -i "s/SELINUX=enforcing/SELINUX=permissive/g" /etc/sysconfig/selinux
+
+yum update -y && yum clean all
+yum install -y krb5-workstation
+
+systemctl stop firewalld
+systemctl disable firewalld
+
+cat <<EOF >> /etc/sysctl.conf
+net.ipv6.conf.all.disable_ipv6 = 1
+net.ipv6.conf.default.disable_ipv6 = 1
+net.ipv6.conf.lo.disable_ipv6 = 1
+EOF
+
+mkdir -p /var/log/kerberos
+cp /vagrant/krb5.conf /etc/krb5.conf
+echo "10.80.88.88 kdc.test.gokrb5" >> /etc/hosts
+
+reboot

+ 32 - 0
testenv/krbclient-vagrant/krb5.conf

@@ -0,0 +1,32 @@
+[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+
+[libdefaults]
+  default_realm = TEST.GOKRB5
+  dns_lookup_realm = false
+  dns_lookup_kdc = false
+  ticket_lifetime = 24h
+  forwardable = yes
+
+[realms]
+ __REALM__ = {
+  kdc = kdc.test.gokrb5:88
+  admin_server = kdc.test.gokrb5:749
+  default_domain = test.gokrb5
+ }
+
+[domain_realm]
+ .test.com = TEST.GOKRB5
+ test.com = TEST.GOKRB5
+
+[appdefaults]
+ pam = {
+   debug = false
+   ticket_lifetime = 36000
+   renew_lifetime = 36000
+   forwardable = true
+   krb4_convert = false
+ }