github.com/jcmturner/gokrb5/v8@v8.4.4/keytab/keytab_test.go (about)

     1  package keytab
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/jcmturner/gokrb5/v8/iana/etypeID"
    13  	"github.com/jcmturner/gokrb5/v8/iana/nametype"
    14  	"github.com/jcmturner/gokrb5/v8/test/testdata"
    15  	"github.com/jcmturner/gokrb5/v8/types"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  func TestUnmarshal(t *testing.T) {
    20  	t.Parallel()
    21  	b, _ := hex.DecodeString(testdata.KEYTAB_TESTUSER1_TEST_GOKRB5)
    22  	kt := New()
    23  	err := kt.Unmarshal(b)
    24  	if err != nil {
    25  		t.Fatalf("Error parsing keytab data: %v\n", err)
    26  	}
    27  	assert.Equal(t, uint8(2), kt.version, "Keytab version not as expected")
    28  	assert.Equal(t, uint32(1), kt.Entries[0].KVNO, "KVNO not as expected")
    29  	assert.Equal(t, uint8(1), kt.Entries[0].KVNO8, "KVNO8 not as expected")
    30  	assert.Equal(t, time.Unix(1505669592, 0), kt.Entries[0].Timestamp, "Timestamp not as expected")
    31  	assert.Equal(t, int32(17), kt.Entries[0].Key.KeyType, "Key's EType not as expected")
    32  	assert.Equal(t, "698c4df8e9f60e7eea5a21bf4526ad25", hex.EncodeToString(kt.Entries[0].Key.KeyValue), "Key material not as expected")
    33  	assert.Equal(t, int16(1), kt.Entries[0].Principal.NumComponents, "Number of components in principal not as expected")
    34  	assert.Equal(t, int32(1), kt.Entries[0].Principal.NameType, "Name type of principal not as expected")
    35  	assert.Equal(t, "TEST.GOKRB5", kt.Entries[0].Principal.Realm, "Realm of principal not as expected")
    36  	assert.Equal(t, "testuser1", kt.Entries[0].Principal.Components[0], "Component in principal not as expected")
    37  }
    38  
    39  func TestMarshal(t *testing.T) {
    40  	t.Parallel()
    41  	b, _ := hex.DecodeString(testdata.KEYTAB_TESTUSER1_TEST_GOKRB5)
    42  	kt := New()
    43  	err := kt.Unmarshal(b)
    44  	if err != nil {
    45  		t.Fatalf("Error parsing keytab data: %v\n", err)
    46  	}
    47  	mb, err := kt.Marshal()
    48  	if err != nil {
    49  		t.Fatalf("Error marshaling: %v", err)
    50  	}
    51  	assert.Equal(t, b, mb, "Marshaled bytes not the same as input bytes")
    52  	err = kt.Unmarshal(mb)
    53  	if err != nil {
    54  		t.Fatalf("Error parsing marshaled bytes: %v", err)
    55  	}
    56  }
    57  
    58  func TestLoad(t *testing.T) {
    59  	t.Parallel()
    60  	f := "test/testdata/testuser1.testtab"
    61  	cwd, _ := os.Getwd()
    62  	dir := os.Getenv("TRAVIS_BUILD_DIR")
    63  	if dir != "" {
    64  		f = dir + "/" + f
    65  	} else if filepath.Base(cwd) == "keytab" {
    66  		f = "../" + f
    67  	}
    68  	kt, err := Load(f)
    69  	if err != nil {
    70  		t.Fatalf("could not load keytab: %v", err)
    71  	}
    72  	assert.Equal(t, uint8(2), kt.version, "keytab version not as expected")
    73  	assert.Equal(t, 12, len(kt.Entries), "keytab entry count not as expected: %+v", *kt)
    74  	for _, e := range kt.Entries {
    75  		if e.Principal.Realm != "TEST.GOKRB5" {
    76  			t.Error("principal realm not as expected")
    77  		}
    78  		if e.Principal.NameType != int32(1) {
    79  			t.Error("name type not as expected")
    80  		}
    81  		if e.Principal.NumComponents != int16(1) {
    82  			t.Error("number of component not as expected")
    83  		}
    84  		if len(e.Principal.Components) != 1 {
    85  			t.Error("number of component not as expected")
    86  		}
    87  		if e.Principal.Components[0] != "testuser1" {
    88  			t.Error("principal components not as expected")
    89  		}
    90  		if e.Timestamp.IsZero() {
    91  			t.Error("entry timestamp incorrect")
    92  		}
    93  		if e.KVNO == uint32(0) {
    94  			t.Error("entry kvno not as expected")
    95  		}
    96  		if e.KVNO8 == uint8(0) {
    97  			t.Error("entry kvno8 not as expected")
    98  		}
    99  	}
   100  }
   101  
   102  // This test provides inputs to readBytes that previously
   103  // caused a panic.
   104  func TestReadBytes(t *testing.T) {
   105  	var endian binary.ByteOrder
   106  	endian = binary.BigEndian
   107  	p := 0
   108  
   109  	if _, err := readBytes(nil, &p, 1, &endian); err == nil {
   110  		t.Fatal("err should be populated because s was given that exceeds array length")
   111  	}
   112  	if _, err := readBytes(nil, &p, -1, &endian); err == nil {
   113  		t.Fatal("err should be given because negative s was given")
   114  	}
   115  }
   116  
   117  func TestUnmarshalPotentialPanics(t *testing.T) {
   118  	kt := New()
   119  
   120  	// Test a good keytab with bad bytes to unmarshal. These should
   121  	// return errors, but not panic.
   122  	if err := kt.Unmarshal(nil); err == nil {
   123  		t.Fatal("should have errored, input is absent")
   124  	}
   125  	if err := kt.Unmarshal([]byte{}); err == nil {
   126  		t.Fatal("should have errored, input is empty")
   127  	}
   128  	// Incorrect first byte.
   129  	if err := kt.Unmarshal([]byte{4}); err == nil {
   130  		t.Fatal("should have errored, input isn't long enough")
   131  	}
   132  	// First byte, but no further content.
   133  	if err := kt.Unmarshal([]byte{5}); err == nil {
   134  		t.Fatal("should have errored, input isn't long enough")
   135  	}
   136  }
   137  
   138  // cxf testing stuff
   139  func TestBadKeytabs(t *testing.T) {
   140  	badPayloads := make([]string, 3)
   141  	badPayloads = append(badPayloads, "BQIwMDAwMDA=")
   142  	badPayloads = append(badPayloads, "BQIAAAAwAAEACjAwMDAwMDAwMDAAIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw")
   143  	badPayloads = append(badPayloads, "BQKAAAAA")
   144  	for _, v := range badPayloads {
   145  		decodedKt, _ := base64.StdEncoding.DecodeString(v)
   146  		parsedKt := new(Keytab)
   147  		parsedKt.Unmarshal(decodedKt)
   148  	}
   149  }
   150  
   151  func TestKeytabEntriesUser(t *testing.T) {
   152  
   153  	// Load known-good keytab generated with ktutil
   154  	ktutilb64 := "BQIAAABGAAEAC0VYQU1QTEUuT1JHAAR1c2VyAAAAAV5ePQAfABIAIG6I6ys5Me8XyS54Ck7kIfFBH/WxBOP3W1DdE/ntBPnGAAAAHwAAADYAAQALRVhBTVBMRS5PUkcABHVzZXIAAAABXl49AB8AEQAQm7fVug9VRBJVhEGjHyN3EgAAAB8AAAA2AAEAC0VYQU1QTEUuT1JHAAR1c2VyAAAAAV5ePQAfABcAEBENDFHhRNNvt+T54BL7uIgAAAAf"
   155  	ktutilbytes, err := base64.StdEncoding.DecodeString(ktutilb64)
   156  	if err != nil {
   157  		t.Errorf("Could not parse b64 ktutil keytab: %s", err)
   158  	}
   159  	ktutil := new(Keytab)
   160  	err = ktutil.Unmarshal(ktutilbytes)
   161  	if err != nil {
   162  		t.Fatalf("Could not load ktutil-generated keytab: %s", err)
   163  	}
   164  
   165  	// Generate the same keytab with gokrb5
   166  	var ts time.Time = ktutil.Entries[0].Timestamp
   167  	var encTypes []int32 = []int32{
   168  		etypeID.AES256_CTS_HMAC_SHA1_96,
   169  		etypeID.AES128_CTS_HMAC_SHA1_96,
   170  		etypeID.RC4_HMAC,
   171  	}
   172  
   173  	kt := New()
   174  	for _, et := range encTypes {
   175  		err = kt.AddEntry("user", "EXAMPLE.ORG", "hello123", ts, uint8(31), et)
   176  		if err != nil {
   177  			t.Errorf("Error adding entry to keytab: %s", err)
   178  		}
   179  	}
   180  	generated, err := kt.Marshal()
   181  	if err != nil {
   182  		t.Errorf("Error marshalling generated keytab: %s", err)
   183  	}
   184  
   185  	// Compare content
   186  	assert.Equal(t, generated, ktutilbytes, "Service keytab doesn't match ktutil keytab")
   187  }
   188  
   189  func TestKeytabEntriesService(t *testing.T) {
   190  
   191  	// Load known-good keytab generated with ktutil
   192  	ktutilb64 := "BQIAAABXAAIAC0VYQU1QTEUuT1JHAARIVFRQAA93d3cuZXhhbXBsZS5vcmcAAAABXl49ggoAEgAgOCSpM5CdiZQn1+rUtLtt6sTrg5Saw1DXJMai7vDWJ0QAAAAKAAAARwACAAtFWEFNUExFLk9SRwAESFRUUAAPd3d3LmV4YW1wbGUub3JnAAAAAV5ePYIKABEAEDpczoDyER1jscz0RWkThCMAAAAKAAAARwACAAtFWEFNUExFLk9SRwAESFRUUAAPd3d3LmV4YW1wbGUub3JnAAAAAV5ePYIKABcAELP27YfH0Th5rD+GtJkQmXQAAAAK"
   193  	ktutilbytes, err := base64.StdEncoding.DecodeString(ktutilb64)
   194  	if err != nil {
   195  		t.Errorf("Could not parse b64 ktutil keytab: %s", err)
   196  	}
   197  	ktutil := new(Keytab)
   198  	err = ktutil.Unmarshal(ktutilbytes)
   199  	if err != nil {
   200  		t.Errorf("Could not load ktutil-generated keytab: %s", err)
   201  	}
   202  
   203  	// Generate the same keytab with gokrb5
   204  	var ts time.Time = ktutil.Entries[0].Timestamp
   205  	var encTypes []int32 = []int32{
   206  		etypeID.AES256_CTS_HMAC_SHA1_96,
   207  		etypeID.AES128_CTS_HMAC_SHA1_96,
   208  		etypeID.RC4_HMAC,
   209  	}
   210  
   211  	kt := New()
   212  	for _, et := range encTypes {
   213  		err = kt.AddEntry("HTTP/www.example.org", "EXAMPLE.ORG", "hello456", ts, uint8(10), et)
   214  		if err != nil {
   215  			t.Errorf("Error adding entry to keytab: %s", err)
   216  		}
   217  	}
   218  	generated, err := kt.Marshal()
   219  	if err != nil {
   220  		t.Errorf("Error marshalling generated keytab: %s", err)
   221  	}
   222  
   223  	// Compare content
   224  	assert.Equal(t, generated, ktutilbytes, "Service keytab doesn't match ktutil keytab")
   225  }
   226  
   227  func TestKeytab_GetEncryptionKey(t *testing.T) {
   228  	princ := "HTTP/princ.test.gokrb5"
   229  	realm := "TEST.GOKRB5"
   230  
   231  	kt := New()
   232  	kt.AddEntry(princ, realm, "abcdefg", time.Unix(100, 0), 1, 18)
   233  	kt.AddEntry(princ, realm, "abcdefg", time.Unix(200, 0), 2, 18)
   234  	kt.AddEntry(princ, realm, "abcdefg", time.Unix(300, 0), 3, 18)
   235  	kt.AddEntry(princ, realm, "abcdefg", time.Unix(400, 0), 4, 18)
   236  	kt.AddEntry(princ, realm, "abcdefg", time.Unix(350, 0), 5, 18)
   237  	kt.AddEntry("HTTP/other.test.gokrb5", realm, "abcdefg", time.Unix(500, 0), 5, 18)
   238  
   239  	pn := types.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, princ)
   240  
   241  	_, kvno, err := kt.GetEncryptionKey(pn, realm, 0, 18)
   242  	if err != nil {
   243  		t.Error(err)
   244  	}
   245  	assert.Equal(t, 4, kvno)
   246  	_, kvno, err = kt.GetEncryptionKey(pn, realm, 3, 18)
   247  	if err != nil {
   248  		t.Error(err)
   249  	}
   250  	assert.Equal(t, 3, kvno)
   251  }