@@ -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
@@ -260,3 +265,150 @@ func (c *Client) DeleteContext(keyname string) error {
260265
261266 return nil
262267}
268+
269+ // Server maps the TKEY name to the context that negotiated it as
270+ // well as any other internal state.
271+ type Server struct {
272+ m sync.RWMutex
273+ lib * gssapi.Lib
274+ ctx map [string ]* gssapi.CtxId
275+ logger logr.Logger
276+ }
277+
278+ // NewServer performs any library initialization necessary.
279+ // It returns a context handle for any further functions along with any error
280+ // that occurred.
281+ func NewServer (options ... Option [Server ]) (* Server , error ) {
282+ lib , err := gssapi .Load (nil )
283+ if err != nil {
284+ return nil , err
285+ }
286+
287+ s := & Server {
288+ lib : lib ,
289+ ctx : make (map [string ]* gssapi.CtxId ),
290+ logger : logr .Discard (),
291+ }
292+
293+ for _ , option := range options {
294+ if err := option (s ); err != nil {
295+ return nil , multierror .Append (err , s .lib .Unload ())
296+ }
297+ }
298+
299+ return s , nil
300+ }
301+
302+ // Close deletes any active contexts and unloads any underlying libraries as
303+ // necessary.
304+ // It returns any error that occurred.
305+ func (s * Server ) Close () error {
306+ return multierror .Append (s .close (true ), s .lib .Unload ()).ErrorOrNil ()
307+ }
308+
309+ func (s * Server ) newContext () (* gssapi.CtxId , error ) {
310+ //nolint:nilnil
311+ return nil , nil
312+ }
313+
314+ //nolint:funlen
315+ func (s * Server ) update (ctx * gssapi.CtxId , input []byte ) (* gssapi.CtxId , []byte , error ) {
316+ /*var cred *gssapi.CredId
317+
318+ // equivalent of GSSAPIStrictAcceptorCheck
319+ if s.strict { //nolint:nestif
320+ hostname, err := osHostname()
321+ if err != nil {
322+ return nil, "", false, err
323+ }
324+
325+ buffer, err := s.lib.MakeBufferString("host@" + hostname)
326+ if err != nil {
327+ return nil, "", false, err
328+ }
329+
330+ defer func() {
331+ err = multierror.Append(err, buffer.Release()).ErrorOrNil()
332+ }()
333+
334+ service, err := buffer.Name(s.lib.GSS_C_NT_HOSTBASED_SERVICE)
335+ if err != nil {
336+ return nil, "", false, err
337+ }
338+
339+ defer func() {
340+ err = multierror.Append(err, service.Release()).ErrorOrNil()
341+ }()
342+
343+ oids, err := s.lib.MakeOIDSet(s.lib.GSS_MECH_KRB5)
344+ if err != nil {
345+ return nil, "", false, err
346+ }
347+
348+ defer func() {
349+ err = multierror.Append(err, oids.Release()).ErrorOrNil()
350+ }()
351+
352+ cred, _, _, err = s.lib.AcquireCred(service, gssapi.GSS_C_INDEFINITE, oids, gssapi.GSS_C_ACCEPT)
353+ if err != nil {
354+ return nil, "", false, err
355+ }
356+
357+ defer func() {
358+ err = multierror.Append(err, cred.Release()).ErrorOrNil()
359+ }()
360+ } else {*/
361+ cred := s .lib .GSS_C_NO_CREDENTIAL
362+ //}
363+
364+ token , err := s .lib .MakeBufferBytes (input )
365+ if err != nil {
366+ return nil , nil , err
367+ }
368+
369+ defer func () {
370+ err = multierror .Append (err , token .Release ()).ErrorOrNil ()
371+ }()
372+
373+ //nolint:dogsled
374+ nctx , _ , _ , output , _ , _ , _ , err := s .lib .AcceptSecContext (ctx , cred , token , s .lib .GSS_C_NO_CHANNEL_BINDINGS )
375+ if err != nil && ! s .lib .LastStatus .Major .ContinueNeeded () {
376+ return nil , nil , err
377+ }
378+
379+ defer func () {
380+ err = multierror .Append (err , output .Release ()).ErrorOrNil ()
381+ }()
382+
383+ return nctx , output .Bytes (), nil
384+ }
385+
386+ func (s * Server ) generate (ctx * gssapi.CtxId , msg []byte ) ([]byte , error ) {
387+ return generate (s .lib , ctx , msg )
388+ }
389+
390+ func (s * Server ) verify (ctx * gssapi.CtxId , stripped , mac []byte ) error {
391+ return verify (s .lib , ctx , stripped , mac )
392+ }
393+
394+ func (s * Server ) established (ctx * gssapi.CtxId ) (established bool , err error ) {
395+ if ctx != nil {
396+ _ , _ , _ , _ , _ , _ , established , err = ctx .InquireContext ()
397+ }
398+
399+ return
400+ }
401+
402+ func (s * Server ) expired (ctx * gssapi.CtxId ) (expired bool , err error ) {
403+ if ctx != nil {
404+ var duration time.Duration
405+ _ , _ , duration , _ , _ , _ , _ , err = ctx .InquireContext ()
406+ expired = duration <= 0
407+ }
408+
409+ return
410+ }
411+
412+ func (s * Server ) delete (ctx * gssapi.CtxId ) error {
413+ return ctx .DeleteSecContext ()
414+ }
0 commit comments