github.com/jcmturner/gokrb5/v8@v8.4.4/service/APExchange_test.go (about)

     1  package service
     2  
     3  import (
     4  	"encoding/hex"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/jcmturner/gokrb5/v8/client"
    10  	"github.com/jcmturner/gokrb5/v8/config"
    11  	"github.com/jcmturner/gokrb5/v8/credentials"
    12  	"github.com/jcmturner/gokrb5/v8/iana/errorcode"
    13  	"github.com/jcmturner/gokrb5/v8/iana/flags"
    14  	"github.com/jcmturner/gokrb5/v8/iana/nametype"
    15  	"github.com/jcmturner/gokrb5/v8/keytab"
    16  	"github.com/jcmturner/gokrb5/v8/messages"
    17  	"github.com/jcmturner/gokrb5/v8/test/testdata"
    18  	"github.com/jcmturner/gokrb5/v8/types"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  func TestVerifyAPREQ(t *testing.T) {
    23  	t.Parallel()
    24  	cl := getClient()
    25  	sname := types.PrincipalName{
    26  		NameType:   nametype.KRB_NT_PRINCIPAL,
    27  		NameString: []string{"HTTP", "host.test.gokrb5"},
    28  	}
    29  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
    30  	kt := keytab.New()
    31  	kt.Unmarshal(b)
    32  	st := time.Now().UTC()
    33  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
    34  		sname, "TEST.GOKRB5",
    35  		types.NewKrbFlags(),
    36  		kt,
    37  		18,
    38  		1,
    39  		st,
    40  		st,
    41  		st.Add(time.Duration(24)*time.Hour),
    42  		st.Add(time.Duration(48)*time.Hour),
    43  	)
    44  	if err != nil {
    45  		t.Fatalf("Error getting test ticket: %v", err)
    46  	}
    47  	APReq, err := messages.NewAPReq(
    48  		tkt,
    49  		sessionKey,
    50  		newTestAuthenticator(*cl.Credentials),
    51  	)
    52  	if err != nil {
    53  		t.Fatalf("Error getting test AP_REQ: %v", err)
    54  	}
    55  
    56  	h, _ := types.GetHostAddress("127.0.0.1:1234")
    57  	s := NewSettings(kt, ClientAddress(h))
    58  	ok, _, err := VerifyAPREQ(&APReq, s)
    59  	if !ok || err != nil {
    60  		t.Fatalf("Validation of AP_REQ failed when it should not have: %v", err)
    61  	}
    62  }
    63  
    64  func TestVerifyAPREQWithPrincipalOverride(t *testing.T) {
    65  	t.Parallel()
    66  	cl := getClient()
    67  	sname := types.PrincipalName{
    68  		NameType:   nametype.KRB_NT_PRINCIPAL,
    69  		NameString: []string{"HTTP", "host.test.gokrb5"},
    70  	}
    71  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
    72  	kt := keytab.New()
    73  	kt.Unmarshal(b)
    74  	st := time.Now().UTC()
    75  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
    76  		sname, "TEST.GOKRB5",
    77  		types.NewKrbFlags(),
    78  		kt,
    79  		18,
    80  		1,
    81  		st,
    82  		st,
    83  		st.Add(time.Duration(24)*time.Hour),
    84  		st.Add(time.Duration(48)*time.Hour),
    85  	)
    86  	if err != nil {
    87  		t.Fatalf("Error getting test ticket: %v", err)
    88  	}
    89  	apReq, err := messages.NewAPReq(
    90  		tkt,
    91  		sessionKey,
    92  		newTestAuthenticator(*cl.Credentials),
    93  	)
    94  	if err != nil {
    95  		t.Fatalf("Error getting test AP_REQ: %v", err)
    96  	}
    97  
    98  	h, _ := types.GetHostAddress("127.0.0.1:1234")
    99  	s := NewSettings(kt, ClientAddress(h), KeytabPrincipal("foo"))
   100  	ok, _, err := VerifyAPREQ(&apReq, s)
   101  	if ok || err == nil {
   102  		t.Fatalf("Validation of AP_REQ should have failed")
   103  	}
   104  	if !strings.Contains(err.Error(), "Looking for \"foo\" realm") {
   105  		t.Fatalf("Looking for wrong entity: %s", err.Error())
   106  	}
   107  }
   108  
   109  func TestVerifyAPREQ_KRB_AP_ERR_BADMATCH(t *testing.T) {
   110  	t.Parallel()
   111  	cl := getClient()
   112  	sname := types.PrincipalName{
   113  		NameType:   nametype.KRB_NT_PRINCIPAL,
   114  		NameString: []string{"HTTP", "host.test.gokrb5"},
   115  	}
   116  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
   117  	kt := keytab.New()
   118  	kt.Unmarshal(b)
   119  	st := time.Now().UTC()
   120  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
   121  		sname, "TEST.GOKRB5",
   122  		types.NewKrbFlags(),
   123  		kt,
   124  		18,
   125  		1,
   126  		st,
   127  		st,
   128  		st.Add(time.Duration(24)*time.Hour),
   129  		st.Add(time.Duration(48)*time.Hour),
   130  	)
   131  	if err != nil {
   132  		t.Fatalf("Error getting test ticket: %v", err)
   133  	}
   134  	a := newTestAuthenticator(*cl.Credentials)
   135  	a.CName = types.PrincipalName{
   136  		NameType:   nametype.KRB_NT_PRINCIPAL,
   137  		NameString: []string{"BADMATCH"},
   138  	}
   139  	APReq, err := messages.NewAPReq(
   140  		tkt,
   141  		sessionKey,
   142  		a,
   143  	)
   144  	if err != nil {
   145  		t.Fatalf("Error getting test AP_REQ: %v", err)
   146  	}
   147  	h, _ := types.GetHostAddress("127.0.0.1:1234")
   148  	s := NewSettings(kt, ClientAddress(h))
   149  	ok, _, err := VerifyAPREQ(&APReq, s)
   150  	if ok || err == nil {
   151  		t.Fatal("Validation of AP_REQ passed when it should not have")
   152  	}
   153  	if _, ok := err.(messages.KRBError); ok {
   154  		assert.Equal(t, errorcode.KRB_AP_ERR_BADMATCH, err.(messages.KRBError).ErrorCode, "Error code not as expected")
   155  	} else {
   156  		t.Fatalf("Error is not a KRBError: %v", err)
   157  	}
   158  }
   159  
   160  func TestVerifyAPREQ_LargeClockSkew(t *testing.T) {
   161  	t.Parallel()
   162  	cl := getClient()
   163  	sname := types.PrincipalName{
   164  		NameType:   nametype.KRB_NT_PRINCIPAL,
   165  		NameString: []string{"HTTP", "host.test.gokrb5"},
   166  	}
   167  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
   168  	kt := keytab.New()
   169  	kt.Unmarshal(b)
   170  	st := time.Now().UTC()
   171  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
   172  		sname, "TEST.GOKRB5",
   173  		types.NewKrbFlags(),
   174  		kt,
   175  		18,
   176  		1,
   177  		st,
   178  		st,
   179  		st.Add(time.Duration(24)*time.Hour),
   180  		st.Add(time.Duration(48)*time.Hour),
   181  	)
   182  	if err != nil {
   183  		t.Fatalf("Error getting test ticket: %v", err)
   184  	}
   185  	a := newTestAuthenticator(*cl.Credentials)
   186  	a.CTime = a.CTime.Add(time.Duration(-10) * time.Minute)
   187  	APReq, err := messages.NewAPReq(
   188  		tkt,
   189  		sessionKey,
   190  		a,
   191  	)
   192  	if err != nil {
   193  		t.Fatalf("Error getting test AP_REQ: %v", err)
   194  	}
   195  
   196  	h, _ := types.GetHostAddress("127.0.0.1:1234")
   197  	s := NewSettings(kt, ClientAddress(h))
   198  	ok, _, err := VerifyAPREQ(&APReq, s)
   199  	if ok || err == nil {
   200  		t.Fatal("Validation of AP_REQ passed when it should not have")
   201  	}
   202  	if _, ok := err.(messages.KRBError); ok {
   203  		assert.Equal(t, errorcode.KRB_AP_ERR_SKEW, err.(messages.KRBError).ErrorCode, "Error code not as expected")
   204  	} else {
   205  		t.Fatalf("Error is not a KRBError: %v", err)
   206  	}
   207  }
   208  
   209  func TestVerifyAPREQ_Replay(t *testing.T) {
   210  	t.Parallel()
   211  	cl := getClient()
   212  	sname := types.PrincipalName{
   213  		NameType:   nametype.KRB_NT_PRINCIPAL,
   214  		NameString: []string{"HTTP", "host.test.gokrb5"},
   215  	}
   216  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
   217  	kt := keytab.New()
   218  	kt.Unmarshal(b)
   219  	st := time.Now().UTC()
   220  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
   221  		sname, "TEST.GOKRB5",
   222  		types.NewKrbFlags(),
   223  		kt,
   224  		18,
   225  		1,
   226  		st,
   227  		st,
   228  		st.Add(time.Duration(24)*time.Hour),
   229  		st.Add(time.Duration(48)*time.Hour),
   230  	)
   231  	if err != nil {
   232  		t.Fatalf("Error getting test ticket: %v", err)
   233  	}
   234  	APReq, err := messages.NewAPReq(
   235  		tkt,
   236  		sessionKey,
   237  		newTestAuthenticator(*cl.Credentials),
   238  	)
   239  	if err != nil {
   240  		t.Fatalf("Error getting test AP_REQ: %v", err)
   241  	}
   242  
   243  	h, _ := types.GetHostAddress("127.0.0.1:1234")
   244  	s := NewSettings(kt, ClientAddress(h))
   245  	ok, _, err := VerifyAPREQ(&APReq, s)
   246  	if !ok || err != nil {
   247  		t.Fatalf("Validation of AP_REQ failed when it should not have: %v", err)
   248  	}
   249  	// Replay
   250  	ok, _, err = VerifyAPREQ(&APReq, s)
   251  	if ok || err == nil {
   252  		t.Fatal("Validation of AP_REQ passed when it should not have")
   253  	}
   254  	assert.IsType(t, messages.KRBError{}, err, "Error is not a KRBError")
   255  	assert.Equal(t, errorcode.KRB_AP_ERR_REPEAT, err.(messages.KRBError).ErrorCode, "Error code not as expected")
   256  }
   257  
   258  func TestVerifyAPREQ_FutureTicket(t *testing.T) {
   259  	t.Parallel()
   260  	cl := getClient()
   261  	sname := types.PrincipalName{
   262  		NameType:   nametype.KRB_NT_PRINCIPAL,
   263  		NameString: []string{"HTTP", "host.test.gokrb5"},
   264  	}
   265  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
   266  	kt := keytab.New()
   267  	kt.Unmarshal(b)
   268  	st := time.Now().UTC()
   269  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
   270  		sname, "TEST.GOKRB5",
   271  		types.NewKrbFlags(),
   272  		kt,
   273  		18,
   274  		1,
   275  		st,
   276  		st.Add(time.Duration(60)*time.Minute),
   277  		st.Add(time.Duration(24)*time.Hour),
   278  		st.Add(time.Duration(48)*time.Hour),
   279  	)
   280  	if err != nil {
   281  		t.Fatalf("Error getting test ticket: %v", err)
   282  	}
   283  	a := newTestAuthenticator(*cl.Credentials)
   284  	APReq, err := messages.NewAPReq(
   285  		tkt,
   286  		sessionKey,
   287  		a,
   288  	)
   289  	if err != nil {
   290  		t.Fatalf("Error getting test AP_REQ: %v", err)
   291  	}
   292  
   293  	h, _ := types.GetHostAddress("127.0.0.1:1234")
   294  	s := NewSettings(kt, ClientAddress(h))
   295  	ok, _, err := VerifyAPREQ(&APReq, s)
   296  	if ok || err == nil {
   297  		t.Fatal("Validation of AP_REQ passed when it should not have")
   298  	}
   299  	if _, ok := err.(messages.KRBError); ok {
   300  		assert.Equal(t, errorcode.KRB_AP_ERR_TKT_NYV, err.(messages.KRBError).ErrorCode, "Error code not as expected")
   301  	} else {
   302  		t.Fatalf("Error is not a KRBError: %v", err)
   303  	}
   304  }
   305  
   306  func TestVerifyAPREQ_InvalidTicket(t *testing.T) {
   307  	t.Parallel()
   308  	cl := getClient()
   309  	sname := types.PrincipalName{
   310  		NameType:   nametype.KRB_NT_PRINCIPAL,
   311  		NameString: []string{"HTTP", "host.test.gokrb5"},
   312  	}
   313  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
   314  	kt := keytab.New()
   315  	kt.Unmarshal(b)
   316  	st := time.Now().UTC()
   317  	f := types.NewKrbFlags()
   318  	types.SetFlag(&f, flags.Invalid)
   319  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
   320  		sname, "TEST.GOKRB5",
   321  		f,
   322  		kt,
   323  		18,
   324  		1,
   325  		st,
   326  		st,
   327  		st.Add(time.Duration(24)*time.Hour),
   328  		st.Add(time.Duration(48)*time.Hour),
   329  	)
   330  	if err != nil {
   331  		t.Fatalf("Error getting test ticket: %v", err)
   332  	}
   333  	APReq, err := messages.NewAPReq(
   334  		tkt,
   335  		sessionKey,
   336  		newTestAuthenticator(*cl.Credentials),
   337  	)
   338  	if err != nil {
   339  		t.Fatalf("Error getting test AP_REQ: %v", err)
   340  	}
   341  
   342  	h, _ := types.GetHostAddress("127.0.0.1:1234")
   343  	s := NewSettings(kt, ClientAddress(h))
   344  	ok, _, err := VerifyAPREQ(&APReq, s)
   345  	if ok || err == nil {
   346  		t.Fatal("Validation of AP_REQ passed when it should not have")
   347  	}
   348  	if _, ok := err.(messages.KRBError); ok {
   349  		assert.Equal(t, errorcode.KRB_AP_ERR_TKT_NYV, err.(messages.KRBError).ErrorCode, "Error code not as expected")
   350  	} else {
   351  		t.Fatalf("Error is not a KRBError: %v", err)
   352  	}
   353  }
   354  
   355  func TestVerifyAPREQ_ExpiredTicket(t *testing.T) {
   356  	t.Parallel()
   357  	cl := getClient()
   358  	sname := types.PrincipalName{
   359  		NameType:   nametype.KRB_NT_PRINCIPAL,
   360  		NameString: []string{"HTTP", "host.test.gokrb5"},
   361  	}
   362  	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
   363  	kt := keytab.New()
   364  	kt.Unmarshal(b)
   365  	st := time.Now().UTC()
   366  	tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
   367  		sname, "TEST.GOKRB5",
   368  		types.NewKrbFlags(),
   369  		kt,
   370  		18,
   371  		1,
   372  		st,
   373  		st,
   374  		st.Add(time.Duration(-30)*time.Minute),
   375  		st.Add(time.Duration(48)*time.Hour),
   376  	)
   377  	if err != nil {
   378  		t.Fatalf("Error getting test ticket: %v", err)
   379  	}
   380  	a := newTestAuthenticator(*cl.Credentials)
   381  	APReq, err := messages.NewAPReq(
   382  		tkt,
   383  		sessionKey,
   384  		a,
   385  	)
   386  	if err != nil {
   387  		t.Fatalf("Error getting test AP_REQ: %v", err)
   388  	}
   389  
   390  	h, _ := types.GetHostAddress("127.0.0.1:1234")
   391  	s := NewSettings(kt, ClientAddress(h))
   392  	ok, _, err := VerifyAPREQ(&APReq, s)
   393  	if ok || err == nil {
   394  		t.Fatal("Validation of AP_REQ passed when it should not have")
   395  	}
   396  	if _, ok := err.(messages.KRBError); ok {
   397  		assert.Equal(t, errorcode.KRB_AP_ERR_TKT_EXPIRED, err.(messages.KRBError).ErrorCode, "Error code not as expected")
   398  	} else {
   399  		t.Fatalf("Error is not a KRBError: %v", err)
   400  	}
   401  }
   402  
   403  func newTestAuthenticator(creds credentials.Credentials) types.Authenticator {
   404  	auth, _ := types.NewAuthenticator(creds.Domain(), creds.CName())
   405  	auth.GenerateSeqNumberAndSubKey(18, 32)
   406  	//auth.Cksum = types.Checksum{
   407  	//	CksumType: chksumtype.GSSAPI,
   408  	//	Checksum:  newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG}),
   409  	//}
   410  	return auth
   411  }
   412  
   413  func getClient() *client.Client {
   414  	b, _ := hex.DecodeString(testdata.KEYTAB_TESTUSER1_TEST_GOKRB5)
   415  	kt := keytab.New()
   416  	kt.Unmarshal(b)
   417  	c, _ := config.NewFromString(testdata.KRB5_CONF)
   418  	cl := client.NewWithKeytab("testuser1", "TEST.GOKRB5", kt, c)
   419  	return cl
   420  }