@@ -17,6 +17,54 @@ import (
1717 "github.com/openshift/gssapi"
1818)
1919
20+ func generate (lib * gssapi.Lib , ctx * gssapi.CtxId , msg []byte ) ([]byte , error ) {
21+ message , err := lib .MakeBufferBytes (msg )
22+ if err != nil {
23+ return nil , err
24+ }
25+
26+ defer func () {
27+ err = multierror .Append (err , message .Release ()).ErrorOrNil ()
28+ }()
29+
30+ token , err := ctx .GetMIC (gssapi .GSS_C_QOP_DEFAULT , message )
31+ if err != nil {
32+ return nil , err
33+ }
34+
35+ defer func () {
36+ err = multierror .Append (err , token .Release ()).ErrorOrNil ()
37+ }()
38+
39+ return token .Bytes (), nil
40+ }
41+
42+ func verify (lib * gssapi.Lib , ctx * gssapi.CtxId , stripped , mac []byte ) error {
43+ message , err := lib .MakeBufferBytes (stripped )
44+ if err != nil {
45+ return err
46+ }
47+
48+ defer func () {
49+ err = multierror .Append (err , message .Release ()).ErrorOrNil ()
50+ }()
51+
52+ token , err := lib .MakeBufferBytes (mac )
53+ if err != nil {
54+ return err
55+ }
56+
57+ defer func () {
58+ err = multierror .Append (err , token .Release ()).ErrorOrNil ()
59+ }()
60+
61+ if _ , err = ctx .VerifyMIC (message , token ); err != nil {
62+ return err
63+ }
64+
65+ return nil
66+ }
67+
2068// Client maps the TKEY name to the context that negotiated it as
2169// well as any other internal state.
2270type Client struct {
@@ -28,16 +76,14 @@ type Client struct {
2876}
2977
3078// WithConfig sets the Kerberos configuration used.
31- func WithConfig (_ string ) func (* Client ) error {
32- return func (c * Client ) error {
33- return errNotSupported
34- }
79+ func WithConfig [T Client ](_ string ) Option [T ] {
80+ return unsupportedOption [T ]
3581}
3682
3783// NewClient performs any library initialization necessary.
3884// It returns a context handle for any further functions along with any error
3985// that occurred.
40- func NewClient (dnsClient * dns.Client , options ... func ( * Client ) error ) (* Client , error ) {
86+ func NewClient (dnsClient * dns.Client , options ... Option [ Client ] ) (* Client , error ) {
4187 client , err := util .CopyDNSClient (dnsClient )
4288 if err != nil {
4389 return nil , err
@@ -57,8 +103,10 @@ func NewClient(dnsClient *dns.Client, options ...func(*Client) error) (*Client,
57103 logger : logr .Discard (),
58104 }
59105
60- if err := c .setOption (options ... ); err != nil {
61- return nil , multierror .Append (err , c .lib .Unload ())
106+ for _ , option := range options {
107+ if err := option (c ); err != nil {
108+ return nil , multierror .Append (err , c .lib .Unload ())
109+ }
62110 }
63111
64112 return c , nil
@@ -72,54 +120,11 @@ func (c *Client) Close() error {
72120}
73121
74122func (c * Client ) generate (ctx * gssapi.CtxId , msg []byte ) ([]byte , error ) {
75- message , err := c .lib .MakeBufferBytes (msg )
76- if err != nil {
77- return nil , err
78- }
79-
80- defer func () {
81- err = multierror .Append (err , message .Release ()).ErrorOrNil ()
82- }()
83-
84- token , err := ctx .GetMIC (gssapi .GSS_C_QOP_DEFAULT , message )
85- if err != nil {
86- return nil , err
87- }
88-
89- defer func () {
90- err = multierror .Append (err , token .Release ()).ErrorOrNil ()
91- }()
92-
93- return token .Bytes (), nil
123+ return generate (c .lib , ctx , msg )
94124}
95125
96126func (c * Client ) verify (ctx * gssapi.CtxId , stripped , mac []byte ) error {
97- // Turn the TSIG-stripped message bytes into a *gssapi.Buffer
98- message , err := c .lib .MakeBufferBytes (stripped )
99- if err != nil {
100- return err
101- }
102-
103- defer func () {
104- err = multierror .Append (err , message .Release ()).ErrorOrNil ()
105- }()
106-
107- // Turn the TSIG MAC bytes into a *gssapi.Buffer
108- token , err := c .lib .MakeBufferBytes (mac )
109- if err != nil {
110- return err
111- }
112-
113- defer func () {
114- err = multierror .Append (err , token .Release ()).ErrorOrNil ()
115- }()
116-
117- // This is the actual verification bit
118- if _ , err = ctx .VerifyMIC (message , token ); err != nil {
119- return err
120- }
121-
122- return nil
127+ return verify (c .lib , ctx , stripped , mac )
123128}
124129
125130// NegotiateContext exchanges RFC 2930 TKEY records with the indicated DNS
@@ -258,3 +263,150 @@ func (c *Client) DeleteContext(keyname string) error {
258263
259264 return nil
260265}
266+
267+ // Server maps the TKEY name to the context that negotiated it as
268+ // well as any other internal state.
269+ type Server struct {
270+ m sync.RWMutex
271+ lib * gssapi.Lib
272+ ctx map [string ]* gssapi.CtxId
273+ logger logr.Logger
274+ }
275+
276+ // NewServer performs any library initialization necessary.
277+ // It returns a context handle for any further functions along with any error
278+ // that occurred.
279+ func NewServer (options ... Option [Server ]) (* Server , error ) {
280+ lib , err := gssapi .Load (nil )
281+ if err != nil {
282+ return nil , err
283+ }
284+
285+ s := & Server {
286+ lib : lib ,
287+ ctx : make (map [string ]* gssapi.CtxId ),
288+ logger : logr .Discard (),
289+ }
290+
291+ for _ , option := range options {
292+ if err := option (s ); err != nil {
293+ return nil , multierror .Append (err , s .lib .Unload ())
294+ }
295+ }
296+
297+ return s , nil
298+ }
299+
300+ // Close deletes any active contexts and unloads any underlying libraries as
301+ // necessary.
302+ // It returns any error that occurred.
303+ func (s * Server ) Close () error {
304+ return multierror .Append (s .close (true ), s .lib .Unload ()).ErrorOrNil ()
305+ }
306+
307+ func (s * Server ) newContext () (* gssapi.CtxId , error ) {
308+ //nolint:nilnil
309+ return nil , nil
310+ }
311+
312+ //nolint:funlen
313+ func (s * Server ) update (ctx * gssapi.CtxId , input []byte ) (* gssapi.CtxId , []byte , error ) {
314+ /*var cred *gssapi.CredId
315+
316+ // equivalent of GSSAPIStrictAcceptorCheck
317+ if s.strict { //nolint:nestif
318+ hostname, err := osHostname()
319+ if err != nil {
320+ return nil, "", false, err
321+ }
322+
323+ buffer, err := s.lib.MakeBufferString("host@" + hostname)
324+ if err != nil {
325+ return nil, "", false, err
326+ }
327+
328+ defer func() {
329+ err = multierror.Append(err, buffer.Release()).ErrorOrNil()
330+ }()
331+
332+ service, err := buffer.Name(s.lib.GSS_C_NT_HOSTBASED_SERVICE)
333+ if err != nil {
334+ return nil, "", false, err
335+ }
336+
337+ defer func() {
338+ err = multierror.Append(err, service.Release()).ErrorOrNil()
339+ }()
340+
341+ oids, err := s.lib.MakeOIDSet(s.lib.GSS_MECH_KRB5)
342+ if err != nil {
343+ return nil, "", false, err
344+ }
345+
346+ defer func() {
347+ err = multierror.Append(err, oids.Release()).ErrorOrNil()
348+ }()
349+
350+ cred, _, _, err = s.lib.AcquireCred(service, gssapi.GSS_C_INDEFINITE, oids, gssapi.GSS_C_ACCEPT)
351+ if err != nil {
352+ return nil, "", false, err
353+ }
354+
355+ defer func() {
356+ err = multierror.Append(err, cred.Release()).ErrorOrNil()
357+ }()
358+ } else {*/
359+ cred := s .lib .GSS_C_NO_CREDENTIAL
360+ //}
361+
362+ token , err := s .lib .MakeBufferBytes (input )
363+ if err != nil {
364+ return nil , nil , err
365+ }
366+
367+ defer func () {
368+ err = multierror .Append (err , token .Release ()).ErrorOrNil ()
369+ }()
370+
371+ //nolint:dogsled
372+ nctx , _ , _ , output , _ , _ , _ , err := s .lib .AcceptSecContext (ctx , cred , token , s .lib .GSS_C_NO_CHANNEL_BINDINGS )
373+ if err != nil && ! s .lib .LastStatus .Major .ContinueNeeded () {
374+ return nil , nil , err
375+ }
376+
377+ defer func () {
378+ err = multierror .Append (err , output .Release ()).ErrorOrNil ()
379+ }()
380+
381+ return nctx , output .Bytes (), nil
382+ }
383+
384+ func (s * Server ) generate (ctx * gssapi.CtxId , msg []byte ) ([]byte , error ) {
385+ return generate (s .lib , ctx , msg )
386+ }
387+
388+ func (s * Server ) verify (ctx * gssapi.CtxId , stripped , mac []byte ) error {
389+ return verify (s .lib , ctx , stripped , mac )
390+ }
391+
392+ func (s * Server ) established (ctx * gssapi.CtxId ) (established bool , err error ) {
393+ if ctx != nil {
394+ _ , _ , _ , _ , _ , _ , established , err = ctx .InquireContext ()
395+ }
396+
397+ return
398+ }
399+
400+ func (s * Server ) expired (ctx * gssapi.CtxId ) (expired bool , err error ) {
401+ if ctx != nil {
402+ var duration time.Duration
403+ _ , _ , duration , _ , _ , _ , _ , err = ctx .InquireContext ()
404+ expired = duration <= 0
405+ }
406+
407+ return
408+ }
409+
410+ func (s * Server ) delete (ctx * gssapi.CtxId ) error {
411+ return ctx .DeleteSecContext ()
412+ }
0 commit comments