Skip to content

Commit

Permalink
krb5.conf parameter expansion
Browse files Browse the repository at this point in the history
Fixes #428

Support parameter expansion for default_ccache_name,
default_client_keytab_name and default_keytab_name.

Additionally, parse krb5-config if it exists, for defaults that aren't
set in krb5.conf.  This should support MIT sites that use a self-maintained
version or distros that change MIT defaults.
  • Loading branch information
jake-scott authored and jcmturner committed Jun 13, 2022
1 parent b3564a0 commit 995c1e9
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 13 deletions.
126 changes: 114 additions & 12 deletions v8/config/krb5conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (
"io"
"net"
"os"
"os/exec"
"os/user"
"regexp"
"runtime"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -46,12 +48,12 @@ func New() *Config {
type LibDefaults struct {
AllowWeakCrypto bool //default false
// ap_req_checksum_type int //unlikely to support this
Canonicalize bool //default false
CCacheType int //default is 4. unlikely to implement older
Clockskew time.Duration //max allowed skew in seconds, default 300
//Default_ccache_name string // default /tmp/krb5cc_%{uid} //Not implementing as will hold in memory
DefaultClientKeytabName string //default /usr/local/var/krb5/user/%{euid}/client.keytab
DefaultKeytabName string //default /etc/krb5.keytab
Canonicalize bool //default false
CCacheType int //default is 4. unlikely to implement older
Clockskew time.Duration //max allowed skew in seconds, default 300
DefaultCcacheName string // default /tmp/krb5cc_%{uid} //Not implementing as will hold in memory
DefaultClientKeytabName string //default /usr/local/var/krb5/user/%{euid}/client.keytab
DefaultKeytabName string //default /etc/krb5.keytab
DefaultRealm string
DefaultTGSEnctypes []string //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
DefaultTktEnctypes []string //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
Expand Down Expand Up @@ -85,11 +87,11 @@ type LibDefaults struct {

// Create a new LibDefaults struct.
func newLibDefaults() LibDefaults {
uid := "0"
vars := PkgConfigVars(nil)

var hdir string
usr, _ := user.Current()
if usr != nil {
uid = usr.Uid
hdir = usr.HomeDir
}
opts := asn1.BitString{}
Expand All @@ -98,8 +100,9 @@ func newLibDefaults() LibDefaults {
return LibDefaults{
CCacheType: 4,
Clockskew: time.Duration(300) * time.Second,
DefaultClientKeytabName: fmt.Sprintf("/usr/local/var/krb5/user/%s/client.keytab", uid),
DefaultKeytabName: "/etc/krb5.keytab",
DefaultCcacheName: ExpandParams(vars["DEFCCNAME"]),
DefaultClientKeytabName: ExpandParams(vars["DEFCKTNAME"]),
DefaultKeytabName: ExpandParams(vars["DEFKTNAME"]),
DefaultTGSEnctypes: []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
DefaultTktEnctypes: []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
DNSCanonicalizeHostname: true,
Expand Down Expand Up @@ -160,10 +163,12 @@ func (l *LibDefaults) parseLines(lines []string) error {
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
}
l.Clockskew = d
case "default_ccache_name":
l.DefaultCcacheName = ExpandParams(strings.TrimSpace(p[1]))
case "default_client_keytab_name":
l.DefaultClientKeytabName = strings.TrimSpace(p[1])
l.DefaultClientKeytabName = ExpandParams(strings.TrimSpace(p[1]))
case "default_keytab_name":
l.DefaultKeytabName = strings.TrimSpace(p[1])
l.DefaultKeytabName = ExpandParams(strings.TrimSpace(p[1]))
case "default_realm":
l.DefaultRealm = strings.TrimSpace(p[1])
case "default_tgs_enctypes":
Expand Down Expand Up @@ -726,3 +731,100 @@ func (c *Config) JSON() (string, error) {
}
return string(b), nil
}

var expandMap map[string]string

func init() {
expandMap = makeExpandMap()
}

func makeExpandMap() (out map[string]string) {
out = make(map[string]string)
vars := PkgConfigVars(nil)

out["TEMP"] = os.TempDir()

user, err := user.Current()
if err == nil {
out["uid"] = user.Uid
out["USERID"] = user.Uid
out["username"] = user.Username
}

if runtime.GOOS == "windows" {
out["euid"] = out["uid"]
} else {
out["euid"] = fmt.Sprintf("%d", os.Geteuid())
}

out["null"] = ""
out["LIBDIR"] = vars["libdir"]
out["BINDIR"] = vars["exec_prefix"] + "/bin"
out["SBINDIR"] = vars["exec_prefix"] + "/sbin"

return
}

func ExpandParams(in string) (out string) {
out = in

for k, v := range expandMap {
repl := fmt.Sprintf("%%{%s}", k)
out = strings.ReplaceAll(out, repl, v)
}
return
}

// PkgConfigVars returns useful variables from the krb5 pkg-config file, if it is found
// otherwise returns a set of defaults
func PkgConfigVars(cfg *string) (out map[string]string) {
out = make(map[string]string)
for k, v := range defaultPkgConfigVars {
out[k] = v
}

if cfg == nil {
// find krb5-config
file, err := exec.LookPath("krb5-config")
if err == nil {
cfg = &file
}
}

if cfg == nil {
return
}

fh, err := os.Open(*cfg)
if err != nil {
return
}
defer fh.Close()

var lineRegex = regexp.MustCompile(`^(\w+)='?([^']+)'?$`)

scanner := bufio.NewScanner(fh)
for scanner.Scan() {
line := scanner.Text()
kv := lineRegex.FindStringSubmatch(line)
if len(kv) != 3 {
continue
}

if _, ok := defaultPkgConfigVars[kv[1]]; ok {
out[kv[1]] = kv[2]
}
}

return
}

var defaultPkgConfigVars = map[string]string{
"prefix": "/usr",
"exec_prefix": "/usr",
"includedir": "/usr/include",
"libdir": "/usr/lib",
"DEFCCNAME": "FILE:/tmp/krb5cc_%{uid}",
"DEFKTNAME": "FILE:/etc/krb5.keytab",
"DEFCKTNAME": "FILE:/var/kerberos/krb5/user/%{euid}/client.keytab",
}
95 changes: 94 additions & 1 deletion v8/config/krb5conf_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"fmt"
"io/ioutil"
"os"
"testing"
Expand Down Expand Up @@ -31,7 +32,7 @@ const (
default_client_keytab_name = FILE:/home/gokrb5/client.keytab
default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 # comment to be ignored
default_ccache_name = FILE:%{TEMP}/krb5cc.%{uid}
[realms]
TEST.GOKRB5 = {
Expand Down Expand Up @@ -85,6 +86,7 @@ const (
"Canonicalize": false,
"CCacheType": 4,
"Clockskew": 300000000000,
"DefaultCcacheName": "/tmp/testcc",
"DefaultClientKeytabName": "FILE:/home/gokrb5/client.keytab",
"DefaultKeytabName": "FILE:/etc/krb5.keytab",
"DefaultRealm": "TEST.GOKRB5",
Expand Down Expand Up @@ -440,6 +442,53 @@ const (
forwardable = true
krb4_convert = false
}
`

pkg_config = `
#!/usr/bin/sh
# Copyright 2001, 2002, 2003 by the Massachusetts Institute of Technology.
# All Rights Reserved.
#
# Configurable parameters set by autoconf
version_string="Kerberos 5 release 1.18.2"
prefix=/test/usr
exec_prefix=/test/usr
includedir=/usr/include
libdir=/test/usr/lib
CC_LINK='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) -pie -Wl,-z,relro -Wl,-z,now $(LDFLAGS)'
KDB5_DB_LIB=
LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,now '
RPATH_FLAG=''
PROG_RPATH_FLAGS=''
PTHREAD_CFLAGS='-pthread'
DL_LIB='-ldl'
DEFCCNAME='FILE:/test/tmp/krb5cc_%{uid}'
DEFKTNAME='FILE:/test/etc/krb5.keytab'
DEFCKTNAME='FILE:/test/var/kerberos/krb5/user/%{euid}/client.keytab'
SELINUX_LIBS='-lselinux '
LIBS='-lkeyutils -lcrypto -lresolv'
GEN_LIB=
# Defaults for program
library=krb5
# Some constants
vendor_string="Massachusetts Institute of Technology"
# Process arguments
# Yes, we are sloppy, library specifications can come before options
while test $# != 0; do
case $1 in
--all)
do_all=1
;;
#### truncated for test
exit 0
`
)

Expand All @@ -462,6 +511,7 @@ func TestLoad(t *testing.T) {
assert.Equal(t, "FILE:/etc/krb5.keytab", c.LibDefaults.DefaultKeytabName, "[libdefaults] default_keytab_name not as expected")
assert.Equal(t, "FILE:/home/gokrb5/client.keytab", c.LibDefaults.DefaultClientKeytabName, "[libdefaults] default_client_keytab_name not as expected")
assert.Equal(t, []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96"}, c.LibDefaults.DefaultTktEnctypes, "[libdefaults] default_tkt_enctypes not as expected")
assert.Equal(t, fmt.Sprintf("FILE:%s/krb5cc.%d", os.TempDir(), os.Getuid()), c.LibDefaults.DefaultCcacheName, "[libdefaults] default_ccache_name not as expected")

assert.Equal(t, 3, len(c.Realms), "Number of realms not as expected")
assert.Equal(t, "TEST.GOKRB5", c.Realms[0].Realm, "[realm] realm name not as expectd")
Expand Down Expand Up @@ -671,6 +721,7 @@ func TestJSON(t *testing.T) {
t.Fatalf("Error loading config: %v", err)
}
c.LibDefaults.K5LoginDirectory = "/home/test"
c.LibDefaults.DefaultCcacheName = "/tmp/testcc"
j, err := c.JSON()
if err != nil {
t.Errorf("error marshaling krb config to JSON: %v", err)
Expand All @@ -679,3 +730,45 @@ func TestJSON(t *testing.T) {

t.Log(j)
}

func TestPkgConfigVars(t *testing.T) {
t.Parallel()

fh, err := ioutil.TempFile("", "test")
if err != nil {
t.Fatalf("creating temp file: %v", err)
}

defer os.Remove(fh.Name())

if _, err := fh.Write([]byte(pkg_config)); err != nil {
t.Fatalf("writing temp file: %v", err)
}

fh.Sync()

fname := fh.Name()
vars := PkgConfigVars(&fname)
assert.Equal(t, "/test/usr", vars["prefix"])
assert.Equal(t, "/test/usr", vars["exec_prefix"])
assert.Equal(t, "/usr/include", vars["includedir"])
assert.Equal(t, "/test/usr/lib", vars["libdir"])
assert.Equal(t, "FILE:/test/tmp/krb5cc_%{uid}", vars["DEFCCNAME"])
assert.Equal(t, "FILE:/test/etc/krb5.keytab", vars["DEFKTNAME"])
assert.Equal(t, "FILE:/test/var/kerberos/krb5/user/%{euid}/client.keytab", vars["DEFCKTNAME"])
}

func TestExpandParams(t *testing.T) {
t.Parallel()

vars := PkgConfigVars(nil)

want := fmt.Sprintf("FILE:/tmp/krb5cc_%d", os.Getuid())
assert.Equal(t, want, ExpandParams("FILE:/tmp/krb5cc_%{uid}"))

want = fmt.Sprintf("test %s", vars["libdir"])
assert.Equal(t, want, ExpandParams("test %{LIBDIR}"))

want = fmt.Sprintf("%s/user-%d", os.TempDir(), os.Getuid())
assert.Equal(t, want, ExpandParams("%{TEMP}/user-%{uid}"))
}

0 comments on commit 995c1e9

Please sign in to comment.