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.components; 021 022 023import java.nio.ByteBuffer; 024import java.util.ArrayList; 025import java.util.List; 026 027import org.apache.directory.api.asn1.EncoderException; 028import org.apache.directory.api.asn1.ber.tlv.BerValue; 029import org.apache.directory.api.asn1.ber.tlv.TLV; 030import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 031import org.apache.directory.api.util.Strings; 032import org.apache.directory.server.i18n.I18n; 033import org.apache.directory.shared.kerberos.KerberosConstants; 034import org.apache.directory.shared.kerberos.KerberosMessageType; 035import org.apache.directory.shared.kerberos.messages.KerberosMessage; 036import org.apache.directory.shared.kerberos.messages.Ticket; 037 038 039/** 040 * The KDC-REP data structure. It will store the object described by the ASN.1 grammar : 041 * <pre> 042 * KDC-REP ::= SEQUENCE { 043 * pvno [0] INTEGER (5), 044 * msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --), 045 * padata [2] SEQUENCE OF PA-DATA OPTIONAL 046 * -- NOTE: not empty --, 047 * crealm [3] Realm, 048 * cname [4] <PrincipalName>, 049 * ticket [5] <Ticket@gt;, 050 * enc-part [6] <EncryptedData> 051 * -- EncASRepPart or EncTGSRepPart, 052 * -- as appropriate 053 * } 054 * </pre> 055 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 056 */ 057public class KdcRep extends KerberosMessage 058{ 059 /** The PA-DATAs */ 060 private List<PaData> paData; 061 062 /** The client realm */ 063 private String crealm; 064 065 /** A storage for a byte array representation of the realm */ 066 private byte[] crealmBytes; 067 068 /** The client principal name */ 069 private PrincipalName cname; 070 071 /** The ticket tickets */ 072 private Ticket ticket; 073 074 /** Encoded part */ 075 private EncryptedData encPart; 076 077 /** The decoded KDC-REP part */ 078 protected EncKdcRepPart encKdcRepPart; 079 080 // Storage for computed lengths 081 private int pvnoLength; 082 private int msgTypeLength; 083 private int paDataLength; 084 private int paDataSeqLength; 085 private int[] paDataLengths; 086 private int cnameLength; 087 private int crealmLength; 088 private int ticketLength; 089 private int encPartLength; 090 private int kdcRepSeqLength; 091 private int kdcRepLength; 092 093 094 /** 095 * Creates a new instance of KDC-REP. 096 */ 097 public KdcRep( KerberosMessageType msgType ) 098 { 099 super( msgType ); 100 paData = new ArrayList<>(); 101 } 102 103 104 /** 105 * @return the pvno 106 */ 107 public int getPvno() 108 { 109 return getProtocolVersionNumber(); 110 } 111 112 113 /** 114 * @param pvno the pvno to set 115 */ 116 public void setPvno( int pvno ) 117 { 118 setProtocolVersionNumber( pvno ); 119 } 120 121 122 /** 123 * @return the paData 124 */ 125 public List<PaData> getPaData() 126 { 127 return paData; 128 } 129 130 131 /** 132 * @param paData the paData to set 133 */ 134 public void addPaData( PaData paData ) 135 { 136 this.paData.add( paData ); 137 } 138 139 140 /** 141 * Returns the client realm. 142 * 143 * @return The client realm. 144 */ 145 public String getCRealm() 146 { 147 return crealm; 148 } 149 150 151 /** 152 * Set the client realm 153 * @param crealm the client realm 154 */ 155 public void setCRealm( String crealm ) 156 { 157 this.crealm = crealm; 158 } 159 160 161 /** 162 * Returns the client {@link PrincipalName}. 163 * 164 * @return The client {@link PrincipalName}. 165 */ 166 public PrincipalName getCName() 167 { 168 return cname; 169 } 170 171 172 /** 173 * Set the client principalName 174 * @param cname the client principalName 175 */ 176 public void setCName( PrincipalName cname ) 177 { 178 this.cname = cname; 179 } 180 181 182 /** 183 * Returns the {@link Ticket} 184 * 185 * @return The {@link Ticket} 186 */ 187 public Ticket getTicket() 188 { 189 return ticket; 190 } 191 192 193 /** 194 * Set the Ticket 195 * @param ticket the ticket to set 196 */ 197 public void setTicket( Ticket ticket ) 198 { 199 this.ticket = ticket; 200 } 201 202 203 /** 204 * Returns the encrypted part as {@link EncryptedData}. 205 * 206 * @return The encrypted part as {@link EncryptedData}. 207 */ 208 public EncryptedData getEncPart() 209 { 210 return encPart; 211 } 212 213 214 /** 215 * @param encPart the encPart to set 216 */ 217 public void setEncPart( EncryptedData encPart ) 218 { 219 this.encPart = encPart; 220 } 221 222 223 /** 224 * @return the encKdcRepPart 225 */ 226 public EncKdcRepPart getEncKdcRepPart() 227 { 228 return encKdcRepPart; 229 } 230 231 232 /** 233 * @param encKdcRepPart the encKdcRepPart to set 234 */ 235 public void setEncKdcRepPart( EncKdcRepPart encKdcRepPart ) 236 { 237 this.encKdcRepPart = encKdcRepPart; 238 } 239 240 241 /** 242 * Compute the KDC-REP length 243 * <pre> 244 * KDC-REP : 245 * 246 * 0x30 L1 KDC-REP sequence 247 * | 248 * +--> 0xA0 0x03 pvno tag 249 * | | 250 * | +--> 0x02 0x01 0x05 pvno (5) 251 * | 252 * +--> 0xA1 0x03 msg-type tag 253 * | | 254 * | +--> 0x02 0x01 0x0B/0x0D msg-type : either AS-REP (0x0B) or TGS-REP (0x0D) 255 * | 256 * +--> 0xA2 L2 pa-data tag 257 * | | 258 * | +--> 0x30 L2-1 pa-data SEQ 259 * | | 260 * | +--> 0x30 L2-1-1 pa-data 261 * | | 262 * | +--> 0x30 L2-1-2 pa-data 263 * | : 264 * | 265 * +--> 0xA3 L3 crealm tag 266 * | | 267 * | +--> 0x1B L3-1 crealm 268 * | 269 * +--> 0xA4 L4 cname tag 270 * | | 271 * | +--> 0x30 L4-1 cname 272 * | 273 * +--> 0xA5 L5 ticket tag 274 * | | 275 * | +--> 0x61 L5-1 ticket 276 * | 277 * +--> 0xA6 L6 enc-part tag 278 * | 279 * +--> 0x30 L6-1 enc-part 280 * 281 * </pre> 282 */ 283 public int computeLength() 284 { 285 // The pvno length 286 pvnoLength = 1 + 1 + 1; 287 kdcRepSeqLength = 1 + TLV.getNbBytes( pvnoLength ) + pvnoLength; 288 289 // The msg-type length 290 msgTypeLength = 1 + 1 + 1; 291 kdcRepSeqLength += 1 + TLV.getNbBytes( msgTypeLength ) + msgTypeLength; 292 293 // Compute the pa-data length. 294 if ( !paData.isEmpty() ) 295 { 296 paDataLengths = new int[paData.size()]; 297 int pos = 0; 298 paDataSeqLength = 0; 299 300 for ( PaData paDataElem : paData ) 301 { 302 paDataLengths[pos] = paDataElem.computeLength(); 303 paDataSeqLength += paDataLengths[pos]; 304 pos++; 305 } 306 307 paDataLength = 1 + TLV.getNbBytes( paDataSeqLength ) + paDataSeqLength; 308 kdcRepSeqLength += 1 + TLV.getNbBytes( paDataLength ) + paDataLength; 309 } 310 311 // The crealm length 312 crealmBytes = Strings.getBytesUtf8( crealm ); 313 crealmLength = 1 + TLV.getNbBytes( crealmBytes.length ) + crealmBytes.length; 314 kdcRepSeqLength += 1 + TLV.getNbBytes( crealmLength ) + crealmLength; 315 316 // Compute the client principalName length 317 cnameLength = cname.computeLength(); 318 kdcRepSeqLength += 1 + TLV.getNbBytes( cnameLength ) + cnameLength; 319 320 // Compute the ticket length 321 ticketLength = ticket.computeLength(); 322 kdcRepSeqLength += 1 + TLV.getNbBytes( ticketLength ) + ticketLength; 323 324 // Compute the encrypted part 325 encPartLength = encPart.computeLength(); 326 kdcRepSeqLength += 1 + TLV.getNbBytes( encPartLength ) + encPartLength; 327 328 // compute the global size 329 kdcRepLength = 1 + TLV.getNbBytes( kdcRepSeqLength ) + kdcRepSeqLength; 330 331 return kdcRepLength; 332 } 333 334 335 /** 336 * Encode the KDC-REP component 337 * 338 * @param buffer The buffer containing the encoded result 339 * @return The encoded component 340 * @throws EncoderException If the encoding failed 341 */ 342 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 343 { 344 if ( buffer == null ) 345 { 346 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 347 } 348 349 // The KDC-REP SEQ Tag 350 buffer.put( UniversalTag.SEQUENCE.getValue() ); 351 buffer.put( TLV.getBytes( kdcRepSeqLength ) ); 352 353 // The PVNO ----------------------------------------------------------- 354 // The tag 355 buffer.put( ( byte ) KerberosConstants.KDC_REP_PVNO_TAG ); 356 buffer.put( TLV.getBytes( pvnoLength ) ); 357 358 // The value 359 BerValue.encode( buffer, getProtocolVersionNumber() ); 360 361 // The MSG-TYPE if any ------------------------------------------------ 362 // The tag 363 buffer.put( ( byte ) KerberosConstants.KDC_REP_MSG_TYPE_TAG ); 364 buffer.put( TLV.getBytes( msgTypeLength ) ); 365 366 // The value 367 BerValue.encode( buffer, getMessageType().getValue() ); 368 369 // The PD-DATA if any ------------------------------------------------- 370 if ( !paData.isEmpty() ) 371 { 372 // The tag 373 buffer.put( ( byte ) KerberosConstants.KDC_REP_PA_DATA_TAG ); 374 buffer.put( TLV.getBytes( paDataLength ) ); 375 376 // The sequence 377 buffer.put( UniversalTag.SEQUENCE.getValue() ); 378 buffer.put( TLV.getBytes( paDataSeqLength ) ); 379 380 // The values 381 for ( PaData paDataElem : paData ) 382 { 383 paDataElem.encode( buffer ); 384 } 385 } 386 387 // The CREALM --------------------------------------------------------- 388 // The tag 389 buffer.put( ( byte ) KerberosConstants.KDC_REP_CREALM_TAG ); 390 buffer.put( TLV.getBytes( crealmLength ) ); 391 392 // The value 393 buffer.put( UniversalTag.GENERAL_STRING.getValue() ); 394 buffer.put( TLV.getBytes( crealmBytes.length ) ); 395 buffer.put( crealmBytes ); 396 397 // The CNAME ---------------------------------------------------------- 398 // The tag 399 buffer.put( ( byte ) KerberosConstants.KDC_REP_CNAME_TAG ); 400 buffer.put( TLV.getBytes( cnameLength ) ); 401 402 // The value 403 cname.encode( buffer ); 404 405 // The TICKET --------------------------------------------------------- 406 // The tag 407 buffer.put( ( byte ) KerberosConstants.KDC_REP_TICKET_TAG ); 408 buffer.put( TLV.getBytes( ticketLength ) ); 409 410 // The value 411 ticket.encode( buffer ); 412 413 // The ENC-PART ------------------------------------------------------- 414 // The tag 415 buffer.put( ( byte ) KerberosConstants.KDC_REP_ENC_PART_TAG ); 416 buffer.put( TLV.getBytes( encPartLength ) ); 417 418 // The value 419 encPart.encode( buffer ); 420 421 return buffer; 422 } 423 424 425 /** 426 * Pretty print the instance 427 */ 428 public String toString( String tabs ) 429 { 430 StringBuilder sb = new StringBuilder(); 431 432 sb.append( tabs ).append( 433 "\n>-------------------------------------------------------------------------------\n" ); 434 sb.append( tabs ).append( "KdcRep : " ); 435 436 if ( getMessageType() == KerberosMessageType.AS_REP ) 437 { 438 sb.append( "AS-REP" ).append( '\n' ); 439 } 440 else if ( getMessageType() == KerberosMessageType.TGS_REP ) 441 { 442 sb.append( "TGS-REP" ).append( '\n' ); 443 } 444 else 445 { 446 sb.append( "Unknown" ).append( '\n' ); 447 } 448 449 sb.append( tabs ).append( "pvno : " ).append( getProtocolVersionNumber() ).append( '\n' ); 450 451 sb.append( tabs ).append( "msg-type : " ).append( getMessageType() ).append( '\n' ); 452 453 for ( PaData paDataElem : paData ) 454 { 455 sb.append( tabs ).append( "padata : " ).append( paDataElem.toString( tabs + " " ) ).append( '\n' ); 456 } 457 458 sb.append( tabs ).append( "crealm : " ).append( crealm ).append( '\n' ); 459 sb.append( tabs ).append( "cname : " ).append( cname ).append( '\n' ); 460 sb.append( ticket.toString( tabs ) ); 461 sb.append( encPart.toString( tabs ) ); 462 sb.append( tabs ).append( 463 "\n-------------------------------------------------------------------------------<\n" ); 464 465 return sb.toString(); 466 } 467 468 469 /** 470 * @see Object#toString() 471 */ 472 public String toString() 473 { 474 return toString( "" ); 475 } 476}