66 "fmt"
77 "io"
88 "math"
9+ "net"
910 "strings"
1011 "time"
1112
@@ -108,16 +109,14 @@ func (krbAuth *GSSAPIKerberosAuth) newAuthenticatorChecksum() []byte {
108109 return a
109110}
110111
111- /*
112- *
113- * Construct Kerberos AP_REQ package, conforming to RFC-4120
114- * https://tools.ietf.org/html/rfc4120#page-84
115- *
116- */
112+ // Construct Kerberos AP_REQ package, conforming to RFC-4120
113+ // https://tools.ietf.org/html/rfc4120#page-84
117114func (krbAuth * GSSAPIKerberosAuth ) createKrb5Token (
118- domain string , cname types.PrincipalName ,
115+ domain string ,
116+ cname types.PrincipalName ,
119117 ticket messages.Ticket ,
120- sessionKey types.EncryptionKey ) ([]byte , error ) {
118+ sessionKey types.EncryptionKey ,
119+ ) ([]byte , error ) {
121120 auth , err := types .NewAuthenticator (domain , cname )
122121 if err != nil {
123122 return nil , err
@@ -144,16 +143,12 @@ func (krbAuth *GSSAPIKerberosAuth) createKrb5Token(
144143 return aprBytes , nil
145144}
146145
147- /*
148- *
149- * Append the GSS-API header to the payload, conforming to RFC-2743
150- * Section 3.1, Mechanism-Independent Token Format
151- *
152- * https://tools.ietf.org/html/rfc2743#page-81
153- *
154- * GSSAPIHeader + <specific mechanism payload>
155- *
156- */
146+ // Append the GSS-API header to the payload, conforming to RFC-2743
147+ // Section 3.1, Mechanism-Independent Token Format
148+ //
149+ // https://tools.ietf.org/html/rfc2743#page-81
150+ //
151+ // GSSAPIHeader + <specific mechanism payload>
157152func (krbAuth * GSSAPIKerberosAuth ) appendGSSAPIHeader (payload []byte ) ([]byte , error ) {
158153 oidBytes , err := asn1 .Marshal (gssapi .OIDKRB5 .OID ())
159154 if err != nil {
@@ -166,12 +161,15 @@ func (krbAuth *GSSAPIKerberosAuth) appendGSSAPIHeader(payload []byte) ([]byte, e
166161 return GSSPackage , nil
167162}
168163
169- func (krbAuth * GSSAPIKerberosAuth ) initSecContext (bytes []byte , kerberosClient KerberosClient ) ([]byte , error ) {
164+ func (krbAuth * GSSAPIKerberosAuth ) initSecContext (
165+ client KerberosClient ,
166+ bytes []byte ,
167+ ) ([]byte , error ) {
170168 switch krbAuth .step {
171169 case GSS_API_INITIAL :
172170 aprBytes , err := krbAuth .createKrb5Token (
173- kerberosClient .Domain (),
174- kerberosClient .CName (),
171+ client .Domain (),
172+ client .CName (),
175173 krbAuth .ticket ,
176174 krbAuth .encKey )
177175 if err != nil {
@@ -200,63 +198,123 @@ func (krbAuth *GSSAPIKerberosAuth) initSecContext(bytes []byte, kerberosClient K
200198 return nil , nil
201199}
202200
203- /* This does the handshake for authorization */
204- func (krbAuth * GSSAPIKerberosAuth ) Authorize (broker * Broker ) error {
205- kerberosClient , err := krbAuth .NewKerberosClientFunc (krbAuth .Config )
206- if err != nil {
207- Logger .Printf ("Kerberos client error: %s" , err )
208- return err
209- }
210-
211- err = kerberosClient .Login ()
212- if err != nil {
213- Logger .Printf ("Kerberos client error: %s" , err )
214- return err
215- }
216- // Construct SPN using serviceName and host
217- // default SPN format: <SERVICE>/<FQDN>
218-
219- host := strings .SplitN (broker .addr , ":" , 2 )[0 ] // Strip port part
201+ func (krbAuth * GSSAPIKerberosAuth ) spn (broker * Broker ) string {
202+ host , _ , _ := net .SplitHostPort (broker .addr )
220203 var spn string
221204 if krbAuth .Config .BuildSpn != nil {
222205 spn = krbAuth .Config .BuildSpn (broker .conf .Net .SASL .GSSAPI .ServiceName , host )
223206 } else {
224207 spn = fmt .Sprintf ("%s/%s" , broker .conf .Net .SASL .GSSAPI .ServiceName , host )
225208 }
209+ return spn
210+ }
226211
227- ticket , encKey , err := kerberosClient .GetServiceTicket (spn )
212+ // Login will use the given KerberosClient to login and get a ticket for the given spn.
213+ func (krbAuth * GSSAPIKerberosAuth ) Login (
214+ client KerberosClient ,
215+ spn string ,
216+ ) (* messages.Ticket , error ) {
217+ if err := client .Login (); err != nil {
218+ Logger .Printf ("Kerberos client login error: %s" , err )
219+ return nil , err
220+ }
221+
222+ ticket , encKey , err := client .GetServiceTicket (spn )
228223 if err != nil {
229- Logger .Printf ("Error getting Kerberos service ticket : %s" , err )
230- return err
224+ Logger .Printf ("Kerberos service ticket error for %s : %s" , spn , err )
225+ return nil , err
231226 }
232227 krbAuth .ticket = ticket
233228 krbAuth .encKey = encKey
234229 krbAuth .step = GSS_API_INITIAL
235- var receivedBytes []byte = nil
236- defer kerberosClient .Destroy ()
230+
231+ return & ticket , nil
232+ }
233+
234+ // Authorize performs the kerberos auth handshake for authorization
235+ func (krbAuth * GSSAPIKerberosAuth ) Authorize (broker * Broker ) error {
236+ client , err := krbAuth .NewKerberosClientFunc (krbAuth .Config )
237+ if err != nil {
238+ Logger .Printf ("Kerberos client initialization error: %s" , err )
239+ return err
240+ }
241+ defer client .Destroy ()
242+
243+ ticket , err := krbAuth .Login (client , krbAuth .spn (broker ))
244+ if err != nil {
245+ return err
246+ }
247+
248+ principal := strings .Join (ticket .SName .NameString , "/" ) + "@" + ticket .Realm
249+ var receivedBytes []byte
250+
237251 for {
238- packBytes , err := krbAuth .initSecContext (receivedBytes , kerberosClient )
252+ packBytes , err := krbAuth .initSecContext (client , receivedBytes )
239253 if err != nil {
240- Logger .Printf ("Error while performing GSSAPI Kerberos Authentication : %s\n " , err )
254+ Logger .Printf ("Kerberos init error as %s : %s" , principal , err )
241255 return err
242256 }
257+
243258 requestTime := time .Now ()
244259 bytesWritten , err := krbAuth .writePackage (broker , packBytes )
245260 if err != nil {
246- Logger .Printf ("Error while performing GSSAPI Kerberos Authentication : %s\n " , err )
261+ Logger .Printf ("Kerberos write error as %s : %s" , principal , err )
247262 return err
248263 }
249264 broker .updateOutgoingCommunicationMetrics (bytesWritten )
250- if krbAuth .step == GSS_API_VERIFY {
251- bytesRead := 0
265+
266+ switch krbAuth .step {
267+ case GSS_API_VERIFY :
268+ var bytesRead int
252269 receivedBytes , bytesRead , err = krbAuth .readPackage (broker )
253270 requestLatency := time .Since (requestTime )
254271 broker .updateIncomingCommunicationMetrics (bytesRead , requestLatency )
255272 if err != nil {
256- Logger .Printf ("Error while performing GSSAPI Kerberos Authentication : %s\n " , err )
273+ Logger .Printf ("Kerberos read error as %s : %s" , principal , err )
257274 return err
258275 }
259- } else if krbAuth .step == GSS_API_FINISH {
276+ case GSS_API_FINISH :
277+ return nil
278+ }
279+ }
280+ }
281+
282+ // AuthorizeV2 performs the SASL v2 GSSAPI authentication with the Kafka broker.
283+ func (krbAuth * GSSAPIKerberosAuth ) AuthorizeV2 (
284+ broker * Broker ,
285+ authSendReceiver func (authBytes []byte ) (* SaslAuthenticateResponse , error ),
286+ ) error {
287+ client , err := krbAuth .NewKerberosClientFunc (krbAuth .Config )
288+ if err != nil {
289+ Logger .Printf ("Kerberos client initialization error: %s" , err )
290+ return err
291+ }
292+ defer client .Destroy ()
293+
294+ ticket , err := krbAuth .Login (client , krbAuth .spn (broker ))
295+ if err != nil {
296+ return err
297+ }
298+
299+ principal := strings .Join (ticket .SName .NameString , "/" ) + "@" + ticket .Realm
300+ var receivedBytes []byte
301+
302+ for {
303+ token , err := krbAuth .initSecContext (client , receivedBytes )
304+ if err != nil {
305+ Logger .Printf ("SASL Kerberos init error as %s: %s" , principal , err )
306+ return err
307+ }
308+
309+ authResponse , err := authSendReceiver (token )
310+ if err != nil {
311+ Logger .Printf ("SASL Kerberos authenticate error as %s: %s" , principal , err )
312+ return err
313+ }
314+
315+ receivedBytes = authResponse .SaslAuthBytes
316+
317+ if krbAuth .step == GSS_API_FINISH {
260318 return nil
261319 }
262320 }
0 commit comments