001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.shared.kerberos.messages; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025 026import org.apache.directory.api.asn1.EncoderException; 027import org.apache.directory.api.asn1.ber.tlv.BerValue; 028import org.apache.directory.api.asn1.ber.tlv.TLV; 029import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 030import org.apache.directory.api.util.Strings; 031import org.apache.directory.server.i18n.I18n; 032import org.apache.directory.shared.kerberos.KerberosConstants; 033import org.apache.directory.shared.kerberos.KerberosMessageType; 034import org.apache.directory.shared.kerberos.KerberosTime; 035import org.apache.directory.shared.kerberos.components.AuthorizationData; 036import org.apache.directory.shared.kerberos.components.Checksum; 037import org.apache.directory.shared.kerberos.components.EncryptionKey; 038import org.apache.directory.shared.kerberos.components.PrincipalName; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042 043/** 044 * A structure to hold the authenticator data. 045 * It will store the object described by the ASN.1 grammar : 046 * <pre> 047 * Authenticator ::= [APPLICATION 2] SEQUENCE { 048 * authenticator-vno [0] INTEGER (5), 049 * crealm [1] Realm, 050 * cname [2] <PrincipalName>, 051 * cksum [3] <Checksum> OPTIONAL, 052 * cusec [4] Microseconds, 053 * ctime [5] KerberosTime, 054 * subkey [6] <EncryptionKey> OPTIONAL, 055 * seq-number [7] UInt32 OPTIONAL, 056 * authorization-data [8] <AuthorizationData> OPTIONAL 057 * } 058 * </pre> 059 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 060 */ 061public class Authenticator extends KerberosMessage 062{ 063 /** The logger */ 064 private static final Logger LOG = LoggerFactory.getLogger( Authenticator.class ); 065 066 /** Speedup for logs */ 067 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 068 069 /** The authenticator version number */ 070 private int versionNumber; 071 072 /** The client realm */ 073 private String crealm; 074 075 /** The client principalName */ 076 private PrincipalName cname; 077 078 /** The checksum */ 079 private Checksum cksum; 080 081 /** The client microseconds */ 082 private int cusec; 083 084 /** The client time */ 085 private KerberosTime ctime; 086 087 /** The sub-session key */ 088 private EncryptionKey subKey; 089 090 /** The sequence number */ 091 private Integer seqNumber; 092 093 /** The authorization Data */ 094 private AuthorizationData authorizationData; 095 096 // Storage for computed lengths 097 private int authenticatorVnoLength; 098 private int crealmLength; 099 private byte[] crealmBytes; 100 private int cnameLength; 101 private int cksumLength; 102 private int cusecLength; 103 private int ctimeLength; 104 private int subkeyLength; 105 private int seqNumberLength; 106 private int authorizationDataLength; 107 private int authenticatorSeqLength; 108 private int authenticatorLength; 109 110 111 /** 112 * Creates a new instance of Authenticator. 113 */ 114 public Authenticator() 115 { 116 super( KerberosMessageType.AUTHENTICATOR ); 117 versionNumber = getProtocolVersionNumber(); 118 } 119 120 121 /** 122 * Returns the {@link AuthorizationData}. 123 * 124 * @return The {@link AuthorizationData}. 125 */ 126 public AuthorizationData getAuthorizationData() 127 { 128 return authorizationData; 129 } 130 131 132 /** 133 * @param authorizationData the authorizationData to set 134 */ 135 public void setAuthorizationData( AuthorizationData authorizationData ) 136 { 137 this.authorizationData = authorizationData; 138 } 139 140 141 /** 142 * @return the cksum 143 */ 144 public Checksum getCksum() 145 { 146 return cksum; 147 } 148 149 150 /** 151 * @param cksum the cksum to set 152 */ 153 public void setCksum( Checksum cksum ) 154 { 155 this.cksum = cksum; 156 } 157 158 159 /** 160 * @return the cname 161 */ 162 public PrincipalName getCName() 163 { 164 return cname; 165 } 166 167 168 /** 169 * @param cname the cname to set 170 */ 171 public void setCName( PrincipalName cname ) 172 { 173 this.cname = cname; 174 } 175 176 177 /** 178 * @return the crealm 179 */ 180 public String getCRealm() 181 { 182 return crealm; 183 } 184 185 186 /** 187 * @param crealm the crealm to set 188 */ 189 public void setCRealm( String crealm ) 190 { 191 this.crealm = crealm; 192 } 193 194 195 /** 196 * @return the ctime 197 */ 198 public KerberosTime getCtime() 199 { 200 return ctime; 201 } 202 203 204 /** 205 * @param ctime the ctime to set 206 */ 207 public void setCTime( KerberosTime ctime ) 208 { 209 this.ctime = ctime; 210 } 211 212 213 /** 214 * @return the cusec 215 */ 216 public int getCusec() 217 { 218 return cusec; 219 } 220 221 222 /** 223 * @param cusec the cusec to set 224 */ 225 public void setCusec( int cusec ) 226 { 227 this.cusec = cusec; 228 } 229 230 231 /** 232 * @return the seqNumber 233 */ 234 public Integer getSeqNumber() 235 { 236 return seqNumber; 237 } 238 239 240 /** 241 * @param seqNumber the seqNumber to set 242 */ 243 public void setSeqNumber( int seqNumber ) 244 { 245 this.seqNumber = Integer.valueOf( seqNumber ); 246 } 247 248 249 /** 250 * @return the subKey 251 */ 252 public EncryptionKey getSubKey() 253 { 254 return subKey; 255 } 256 257 258 /** 259 * @param subKey the subKey to set 260 */ 261 public void setSubKey( EncryptionKey subKey ) 262 { 263 this.subKey = subKey; 264 } 265 266 267 /** 268 * Returns the version number of the {@link Authenticator}. 269 * 270 * @return The version number of the {@link Authenticator}. 271 */ 272 public int getVersionNumber() 273 { 274 return versionNumber; 275 } 276 277 278 /** 279 * @param versionNumber the versionNumber to set 280 */ 281 public void setVersionNumber( int versionNumber ) 282 { 283 this.versionNumber = versionNumber; 284 } 285 286 287 /** 288 * Compute the Authenticator length 289 * <pre> 290 * Authenticator : 291 * 292 * 0x62 L1 Authenticator [APPLICATION 2] 293 * | 294 * +--> 0x30 L2 Authenticator SEQUENCE 295 * | 296 * +--> 0xA0 03 authenticator-vno tag 297 * | | 298 * | +--> 0x02 0x01 0x05 authenticator-vno (int, 5) 299 * | 300 * +--> 0xA1 L3 crealm tag 301 * | | 302 * | +--> 0x1B L3-1 crealm (KerberosString) 303 * | 304 * +--> 0xA2 L4 cname (PrincipalName) 305 * | 306 * +--> 0xA3 L5 cksum (CheckSum) 307 * | 308 * +--> 0xA4 L6 cusec tag 309 * | | 310 * | +--> 0x02 L6-1 nnn cusec value (Integer) 311 * | 312 * +--> 0xA5 0x11 ctime tag 313 * | | 314 * | +--> 0x18 0x0F ttt ctime (KerberosTime) 315 * | 316 * +--> 0xA6 L7 subkey (EncryptionKey) 317 * | 318 * +--> 0xA7 L8 seq-number tag 319 * | | 320 * | +--> 0x02 L8-1 nnn seq-number (Integer) 321 * | 322 * +--> 0xA8 L9 authorization-data (AuthorizationData) 323 * </pre> 324 */ 325 @Override 326 public int computeLength() 327 { 328 reset(); 329 330 // Compute the Authenticator version length. 331 authenticatorVnoLength = 1 + 1 + BerValue.getNbBytes( getVersionNumber() ); 332 authenticatorSeqLength = 1 + TLV.getNbBytes( authenticatorVnoLength ) + authenticatorVnoLength; 333 334 // Compute the crealm length. 335 crealmBytes = Strings.getBytesUtf8( crealm ); 336 crealmLength = 1 + TLV.getNbBytes( crealmBytes.length ) + crealmBytes.length; 337 authenticatorSeqLength += 1 + TLV.getNbBytes( crealmLength ) + crealmLength; 338 339 // Compute the cname length 340 cnameLength = cname.computeLength(); 341 authenticatorSeqLength += 1 + TLV.getNbBytes( cnameLength ) + cnameLength; 342 343 // Compute the cksum length if any 344 if ( cksum != null ) 345 { 346 cksumLength = cksum.computeLength(); 347 authenticatorSeqLength += 1 + TLV.getNbBytes( cksumLength ) + cksumLength; 348 } 349 350 // Compute the cusec length 351 cusecLength = 1 + 1 + BerValue.getNbBytes( cusec ); 352 authenticatorSeqLength += 1 + TLV.getNbBytes( cusecLength ) + cusecLength; 353 354 // Compute the ctime length 355 ctimeLength = 1 + 1 + 0x0F; 356 authenticatorSeqLength += 1 + 1 + ctimeLength; 357 358 // Compute the subkey length if any 359 if ( subKey != null ) 360 { 361 subkeyLength = subKey.computeLength(); 362 authenticatorSeqLength += 1 + TLV.getNbBytes( subkeyLength ) + subkeyLength; 363 } 364 365 // Compute the seq-number length if any 366 if ( seqNumber != null ) 367 { 368 seqNumberLength = 1 + 1 + BerValue.getNbBytes( seqNumber ); 369 authenticatorSeqLength += 1 + TLV.getNbBytes( seqNumberLength ) + seqNumberLength; 370 } 371 372 // Compute the authorization-data length if any 373 if ( authorizationData != null ) 374 { 375 authorizationDataLength = authorizationData.computeLength(); 376 authenticatorSeqLength += 1 + TLV.getNbBytes( authorizationDataLength ) + authorizationDataLength; 377 } 378 379 // compute the global size 380 authenticatorLength = 1 + TLV.getNbBytes( authenticatorSeqLength ) + authenticatorSeqLength; 381 382 return 1 + TLV.getNbBytes( authenticatorLength ) + authenticatorLength; 383 } 384 385 386 /** 387 * Encode the Authenticator message to a PDU. 388 * <pre> 389 * Authenticator : 390 * 391 * 0x62 LL 392 * 0x30 LL 393 * 0xA0 0x03 394 * 0x02 0x01 0x05 authenticator-vno 395 * 0xA1 LL 396 * 0x1B LL abcd crealm 397 * 0xA2 LL 398 * 0x30 LL abcd cname 399 * [0xA3 LL 400 * 0x30 LL abcd] cksum 401 * 0xA4 LL 402 * 0x02 LL nnn cusec 403 * 0xA5 0x11 404 * 0x18 0x0F ttt ctime 405 * [0xA6 LL 406 * 0x30 LL abcd] subkey 407 * [0xA7 LL 408 * 0x02 LL nnn] seq-number 409 * [0xA8 LL 410 * 0x30 LL abcd] authorization-data 411 * </pre> 412 * @return The constructed PDU. 413 */ 414 @Override 415 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 416 { 417 if ( buffer == null ) 418 { 419 buffer = ByteBuffer.allocate( computeLength() ); 420 } 421 422 try 423 { 424 // The Authenticator APPLICATION Tag 425 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_TAG ); 426 buffer.put( TLV.getBytes( authenticatorLength ) ); 427 428 // The Authenticator SEQUENCE Tag 429 buffer.put( UniversalTag.SEQUENCE.getValue() ); 430 buffer.put( TLV.getBytes( authenticatorSeqLength ) ); 431 432 // The authenticator-vno ------------------------------------------ 433 // The tag 434 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_AUTHENTICATOR_VNO_TAG ); 435 buffer.put( TLV.getBytes( authenticatorVnoLength ) ); 436 437 // The value 438 BerValue.encode( buffer, getVersionNumber() ); 439 440 // The crealm ----------------------------------------------------- 441 // The tag 442 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CREALM_TAG ); 443 buffer.put( TLV.getBytes( crealmLength ) ); 444 445 // The value 446 buffer.put( UniversalTag.GENERAL_STRING.getValue() ); 447 buffer.put( TLV.getBytes( crealmBytes.length ) ); 448 buffer.put( crealmBytes ); 449 450 // The cname ------------------------------------------------------ 451 // The tag 452 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CNAME_TAG ); 453 buffer.put( TLV.getBytes( cnameLength ) ); 454 455 // The value 456 cname.encode( buffer ); 457 458 // The cksum, if any ---------------------------------------------- 459 if ( cksum != null ) 460 { 461 // The tag 462 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CKSUM_TAG ); 463 buffer.put( TLV.getBytes( cksumLength ) ); 464 465 // The value 466 cksum.encode( buffer ); 467 } 468 469 // The cusec ------------------------------------------------------ 470 // The tag 471 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CUSEC_TAG ); 472 buffer.put( TLV.getBytes( cusecLength ) ); 473 474 // The value 475 BerValue.encode( buffer, cusec ); 476 477 // The ctime ------------------------------------------------------ 478 // The tag 479 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CTIME_TAG ); 480 buffer.put( TLV.getBytes( ctimeLength ) ); 481 482 // The value 483 buffer.put( UniversalTag.GENERALIZED_TIME.getValue() ); 484 buffer.put( ( byte ) 0x0F ); 485 buffer.put( ctime.getBytes() ); 486 487 // The subkey if any --------------------------------------------------- 488 if ( subKey != null ) 489 { 490 // The tag 491 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_SUBKEY_TAG ); 492 buffer.put( TLV.getBytes( subkeyLength ) ); 493 494 // The value 495 subKey.encode( buffer ); 496 } 497 498 // The seq-number, if any ----------------------------------------- 499 if ( seqNumber != null ) 500 { 501 // The tag 502 buffer.put( (byte)KerberosConstants.AUTHENTICATOR_SEQ_NUMBER_TAG ); 503 buffer.put( TLV.getBytes( seqNumberLength ) ); 504 505 // The value 506 BerValue.encode( buffer, seqNumber ); 507 } 508 509 // The authorization-data, if any --------------------------------- 510 if ( authorizationData != null ) 511 { 512 // The tag 513 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_AUTHORIZATION_DATA_TAG ); 514 buffer.put( TLV.getBytes( authorizationDataLength ) ); 515 516 // The value 517 authorizationData.encode( buffer ); 518 } 519 } 520 catch ( BufferOverflowException boe ) 521 { 522 LOG.error( I18n.err( I18n.ERR_139, 1 + TLV.getNbBytes( 0 ) 523 + 0, buffer.capacity() ) ); 524 throw new EncoderException( I18n.err( I18n.ERR_138 ), boe ); 525 } 526 527 if ( IS_DEBUG ) 528 { 529 LOG.debug( "Authenticator encoding : {}", Strings.dumpBytes( buffer.array() ) ); 530 LOG.debug( "Authenticator initial value : {}", this ); 531 } 532 533 return buffer; 534 } 535 536 537 /** 538 * reset the fields used while computing length 539 */ 540 private void reset() 541 { 542 authenticatorVnoLength = 0; 543 crealmLength = 0; 544 crealmBytes = null; 545 cnameLength = 0; 546 cksumLength = 0; 547 cusecLength = 0; 548 ctimeLength = 0; 549 subkeyLength = 0; 550 seqNumberLength = 0; 551 authorizationDataLength = 0; 552 authenticatorSeqLength = 0; 553 authenticatorLength = 0; 554 } 555 556 557 /** 558 * @see Object#toString() 559 */ 560 public String toString() 561 { 562 StringBuilder sb = new StringBuilder(); 563 564 sb.append( "Authenticator : \n" ); 565 566 sb.append( " authenticator-vno : " ).append( getVersionNumber() ).append( '\n' ); 567 sb.append( " crealm : " ).append( crealm ).append( '\n' ); 568 sb.append( " cname : " ).append( cname ).append( '\n' ); 569 570 if ( cksum != null ) 571 { 572 sb.append( " cksum : " ).append( cksum ).append( '\n' ); 573 } 574 575 sb.append( " cusec : " ).append( cusec ).append( '\n' ); 576 sb.append( " ctime : " ).append( ctime ).append( '\n' ); 577 578 if ( subKey != null ) 579 { 580 sb.append( " subkey : " ).append( subKey ).append( '\n' ); 581 } 582 583 if ( seqNumber != null ) 584 { 585 sb.append( " seq-number : " ).append( seqNumber ).append( '\n' ); 586 } 587 588 if ( authorizationData != null ) 589 { 590 sb.append( " authorization-data : " ).append( authorizationData ).append( '\n' ); 591 } 592 593 return sb.toString(); 594 } 595}