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.codec; 021 022 023import java.nio.ByteBuffer; 024 025import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswdErrorType; 026import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswordException; 027import org.apache.directory.api.asn1.DecoderException; 028import org.apache.directory.api.asn1.ber.Asn1Container; 029import org.apache.directory.api.asn1.ber.Asn1Decoder; 030import org.apache.directory.api.asn1.ber.tlv.TLVStateEnum; 031import org.apache.directory.shared.kerberos.codec.EncKdcRepPart.EncKdcRepPartContainer; 032import org.apache.directory.shared.kerberos.codec.apRep.ApRepContainer; 033import org.apache.directory.shared.kerberos.codec.apReq.ApReqContainer; 034import org.apache.directory.shared.kerberos.codec.authenticator.AuthenticatorContainer; 035import org.apache.directory.shared.kerberos.codec.authorizationData.AuthorizationDataContainer; 036import org.apache.directory.shared.kerberos.codec.encApRepPart.EncApRepPartContainer; 037import org.apache.directory.shared.kerberos.codec.encAsRepPart.EncAsRepPartContainer; 038import org.apache.directory.shared.kerberos.codec.encKrbPrivPart.EncKrbPrivPartContainer; 039import org.apache.directory.shared.kerberos.codec.encTgsRepPart.EncTgsRepPartContainer; 040import org.apache.directory.shared.kerberos.codec.encTicketPart.EncTicketPartContainer; 041import org.apache.directory.shared.kerberos.codec.encryptedData.EncryptedDataContainer; 042import org.apache.directory.shared.kerberos.codec.encryptionKey.EncryptionKeyContainer; 043import org.apache.directory.shared.kerberos.codec.krbPriv.KrbPrivContainer; 044import org.apache.directory.shared.kerberos.codec.paEncTsEnc.PaEncTsEncContainer; 045import org.apache.directory.shared.kerberos.codec.principalName.PrincipalNameContainer; 046import org.apache.directory.shared.kerberos.codec.ticket.TicketContainer; 047import org.apache.directory.shared.kerberos.components.AuthorizationData; 048import org.apache.directory.shared.kerberos.components.EncKdcRepPart; 049import org.apache.directory.shared.kerberos.components.EncKrbPrivPart; 050import org.apache.directory.shared.kerberos.components.EncTicketPart; 051import org.apache.directory.shared.kerberos.components.EncryptedData; 052import org.apache.directory.shared.kerberos.components.EncryptionKey; 053import org.apache.directory.shared.kerberos.components.PaEncTsEnc; 054import org.apache.directory.shared.kerberos.components.PrincipalName; 055import org.apache.directory.shared.kerberos.exceptions.ErrorType; 056import org.apache.directory.shared.kerberos.exceptions.KerberosException; 057import org.apache.directory.shared.kerberos.messages.ApRep; 058import org.apache.directory.shared.kerberos.messages.ApReq; 059import org.apache.directory.shared.kerberos.messages.Authenticator; 060import org.apache.directory.shared.kerberos.messages.EncApRepPart; 061import org.apache.directory.shared.kerberos.messages.EncAsRepPart; 062import org.apache.directory.shared.kerberos.messages.EncTgsRepPart; 063import org.apache.directory.shared.kerberos.messages.KrbPriv; 064import org.apache.directory.shared.kerberos.messages.Ticket; 065import org.slf4j.Logger; 066import org.slf4j.LoggerFactory; 067 068 069/** 070 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 071 */ 072public class KerberosDecoder 073{ 074 075 /** The logger */ 076 private static Logger LOG = LoggerFactory.getLogger( KerberosDecoder.class ); 077 078 /** A speedup for logger */ 079 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 080 081 082 public static Object decode( KerberosMessageContainer kerberosMessageContainer ) throws DecoderException 083 { 084 ByteBuffer buf = kerberosMessageContainer.getStream(); 085 086 if ( kerberosMessageContainer.isTCP() ) 087 { 088 if ( buf.remaining() > 4 ) 089 { 090 kerberosMessageContainer.setTcpLength( buf.getInt() ); 091 buf.mark(); 092 } 093 else 094 { 095 return null; 096 } 097 } 098 else 099 { 100 buf.mark(); 101 } 102 103 while ( buf.hasRemaining() ) 104 { 105 try 106 { 107 Asn1Decoder.decode( buf, kerberosMessageContainer ); 108 109 if ( kerberosMessageContainer.getState() == TLVStateEnum.PDU_DECODED ) 110 { 111 if ( IS_DEBUG ) 112 { 113 LOG.debug( "Decoded KerberosMessage : {}", kerberosMessageContainer.getMessage() ); 114 buf.mark(); 115 } 116 117 return kerberosMessageContainer.getMessage(); 118 } 119 } 120 catch ( DecoderException de ) 121 { 122 LOG.warn( "error while decoding", de ); 123 buf.clear(); 124 kerberosMessageContainer.clean(); 125 throw de; 126 } 127 } 128 129 return null; 130 } 131 132 133 /** 134 * Decode an EncrytedData structure 135 * 136 * @param data The byte array containing the data structure to decode 137 * @return An instance of EncryptedData 138 * @throws KerberosException If the decoding fails 139 */ 140 public static EncryptedData decodeEncryptedData( byte[] data ) throws KerberosException 141 { 142 ByteBuffer stream = ByteBuffer.allocate( data.length ); 143 stream.put( data ); 144 stream.flip(); 145 146 // Allocate a EncryptedData Container 147 Asn1Container encryptedDataContainer = new EncryptedDataContainer(); 148 149 // Decode the EncryptedData PDU 150 try 151 { 152 Asn1Decoder.decode( stream, encryptedDataContainer ); 153 } 154 catch ( DecoderException de ) 155 { 156 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 157 } 158 159 // get the decoded EncryptedData 160 return ( ( EncryptedDataContainer ) encryptedDataContainer ).getEncryptedData(); 161 } 162 163 164 /** 165 * Decode an PaEncTsEnc structure 166 * 167 * @param data The byte array containing the data structure to decode 168 * @return An instance of PaEncTsEnc 169 * @throws KerberosException If the decoding fails 170 */ 171 public static PaEncTsEnc decodePaEncTsEnc( byte[] data ) throws KerberosException 172 { 173 ByteBuffer stream = ByteBuffer.allocate( data.length ); 174 stream.put( data ); 175 stream.flip(); 176 177 // Allocate a PaEncTsEnc Container 178 Asn1Container paEncTsEncContainer = new PaEncTsEncContainer(); 179 180 // Decode the PaEncTsEnc PDU 181 try 182 { 183 Asn1Decoder.decode( stream, paEncTsEncContainer ); 184 } 185 catch ( DecoderException de ) 186 { 187 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 188 } 189 190 // get the decoded PaEncTsEnc 191 return ( ( PaEncTsEncContainer ) paEncTsEncContainer ).getPaEncTsEnc(); 192 } 193 194 195 /** 196 * Decode an EncApRepPart structure 197 * 198 * @param data The byte array containing the data structure to decode 199 * @return An instance of EncApRepPart 200 * @throws KerberosException If the decoding fails 201 */ 202 public static EncApRepPart decodeEncApRepPart( byte[] data ) throws KerberosException 203 { 204 ByteBuffer stream = ByteBuffer.allocate( data.length ); 205 stream.put( data ); 206 stream.flip(); 207 208 // Allocate a EncApRepPart Container 209 Asn1Container encApRepPartContainer = new EncApRepPartContainer( stream ); 210 211 // Decode the EncApRepPart PDU 212 try 213 { 214 Asn1Decoder.decode( stream, encApRepPartContainer ); 215 } 216 catch ( DecoderException de ) 217 { 218 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 219 } 220 221 // get the decoded EncApRepPart 222 return ( ( EncApRepPartContainer ) encApRepPartContainer ).getEncApRepPart(); 223 } 224 225 226 /** 227 * Decode an EncKdcRepPart structure 228 * 229 * @param data The byte array containing the data structure to decode 230 * @return An instance of EncKdcRepPart 231 * @throws KerberosException If the decoding fails 232 */ 233 public static EncKdcRepPart decodeEncKdcRepPart( byte[] data ) throws KerberosException 234 { 235 ByteBuffer stream = ByteBuffer.allocate( data.length ); 236 stream.put( data ); 237 stream.flip(); 238 239 // Allocate a EncKdcRepPart Container 240 Asn1Container encKdcRepPartContainer = new EncKdcRepPartContainer( stream ); 241 242 // Decode the EncKdcRepPart PDU 243 try 244 { 245 Asn1Decoder.decode( stream, encKdcRepPartContainer ); 246 } 247 catch ( DecoderException de ) 248 { 249 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 250 } 251 252 // get the decoded EncKdcRepPart 253 return ( ( EncKdcRepPartContainer ) encKdcRepPartContainer ).getEncKdcRepPart(); 254 } 255 256 257 /** 258 * Decode an EncKrbPrivPart structure 259 * 260 * @param data The byte array containing the data structure to decode 261 * @return An instance of EncKrbPrivPart 262 * @throws KerberosException If the decoding fails 263 */ 264 public static EncKrbPrivPart decodeEncKrbPrivPart( byte[] data ) throws KerberosException 265 { 266 ByteBuffer stream = ByteBuffer.allocate( data.length ); 267 stream.put( data ); 268 stream.flip(); 269 270 // Allocate a EncKrbPrivPart Container 271 Asn1Container encKrbPrivPartContainer = new EncKrbPrivPartContainer( stream ); 272 273 // Decode the EncKrbPrivPart PDU 274 try 275 { 276 Asn1Decoder.decode( stream, encKrbPrivPartContainer ); 277 } 278 catch ( DecoderException de ) 279 { 280 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 281 } 282 283 // get the decoded EncKrbPrivPart 284 return ( ( EncKrbPrivPartContainer ) encKrbPrivPartContainer ).getEncKrbPrivPart(); 285 } 286 287 288 /** 289 * Decode an EncTicketPart structure 290 * 291 * @param data The byte array containing the data structure to decode 292 * @return An instance of EncTicketPart 293 * @throws KerberosException If the decoding fails 294 */ 295 public static EncTicketPart decodeEncTicketPart( byte[] data ) throws KerberosException 296 { 297 ByteBuffer stream = ByteBuffer.allocate( data.length ); 298 stream.put( data ); 299 stream.flip(); 300 301 // Allocate a EncTicketPart Container 302 Asn1Container encTicketPartContainer = new EncTicketPartContainer( stream ); 303 304 // Decode the EncTicketPart PDU 305 try 306 { 307 Asn1Decoder.decode( stream, encTicketPartContainer ); 308 } 309 catch ( DecoderException de ) 310 { 311 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 312 } 313 314 // get the decoded EncTicketPart 315 return ( ( EncTicketPartContainer ) encTicketPartContainer ).getEncTicketPart(); 316 } 317 318 319 /** 320 * Decode an EncryptionKey structure 321 * 322 * @param data The byte array containing the data structure to decode 323 * @return An instance of EncryptionKey 324 * @throws KerberosException If the decoding fails 325 */ 326 public static EncryptionKey decodeEncryptionKey( byte[] data ) throws KerberosException 327 { 328 ByteBuffer stream = ByteBuffer.allocate( data.length ); 329 stream.put( data ); 330 stream.flip(); 331 332 // Allocate a EncryptionKey Container 333 Asn1Container encryptionKeyContainer = new EncryptionKeyContainer(); 334 335 // Decode the EncryptionKey PDU 336 try 337 { 338 Asn1Decoder.decode( stream, encryptionKeyContainer ); 339 } 340 catch ( DecoderException de ) 341 { 342 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 343 } 344 345 // get the decoded EncryptionKey 346 return ( ( EncryptionKeyContainer ) encryptionKeyContainer ).getEncryptionKey(); 347 } 348 349 350 /** 351 * Decode an PrincipalName structure 352 * 353 * @param data The byte array containing the data structure to decode 354 * @return An instance of PrincipalName 355 * @throws KerberosException If the decoding fails 356 */ 357 public static PrincipalName decodePrincipalName( byte[] data ) throws KerberosException 358 { 359 ByteBuffer stream = ByteBuffer.allocate( data.length ); 360 stream.put( data ); 361 stream.flip(); 362 363 // Allocate a PrincipalName Container 364 Asn1Container principalNameContainer = new PrincipalNameContainer(); 365 366 // Decode the PrincipalName PDU 367 try 368 { 369 Asn1Decoder.decode( stream, principalNameContainer ); 370 } 371 catch ( DecoderException de ) 372 { 373 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 374 } 375 376 // get the decoded PrincipalName 377 return ( ( PrincipalNameContainer ) principalNameContainer ).getPrincipalName(); 378 } 379 380 381 /** 382 * Decode a Ticket structure 383 * 384 * @param data The byte array containing the data structure to decode 385 * @return An instance of Ticket 386 * @throws KerberosException If the decoding fails 387 */ 388 public static Ticket decodeTicket( byte[] data ) throws KerberosException 389 { 390 ByteBuffer stream = ByteBuffer.allocate( data.length ); 391 stream.put( data ); 392 stream.flip(); 393 394 // Allocate a Ticket Container 395 Asn1Container ticketContainer = new TicketContainer( stream ); 396 397 // Decode the Ticket PDU 398 try 399 { 400 Asn1Decoder.decode( stream, ticketContainer ); 401 } 402 catch ( DecoderException de ) 403 { 404 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 405 } 406 407 // get the decoded Ticket 408 return ( ( TicketContainer ) ticketContainer ).getTicket(); 409 } 410 411 412 /** 413 * Decode a Authenticator structure 414 * 415 * @param data The byte array containing the data structure to decode 416 * @return An instance of Authenticator 417 * @throws KerberosException If the decoding fails 418 */ 419 public static Authenticator decodeAuthenticator( byte[] data ) throws KerberosException 420 { 421 ByteBuffer stream = ByteBuffer.allocate( data.length ); 422 stream.put( data ); 423 stream.flip(); 424 425 // Allocate a Authenticator Container 426 Asn1Container authenticatorContainer = new AuthenticatorContainer( stream ); 427 428 // Decode the Ticket PDU 429 try 430 { 431 Asn1Decoder.decode( stream, authenticatorContainer ); 432 } 433 catch ( DecoderException de ) 434 { 435 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 436 } 437 438 // get the decoded Authenticator 439 return ( ( AuthenticatorContainer ) authenticatorContainer ).getAuthenticator(); 440 } 441 442 443 /** 444 * Decode a AuthorizationData structure 445 * 446 * @param data The byte array containing the data structure to decode 447 * @return An instance of AuthorizationData 448 * @throws KerberosException If the decoding fails 449 */ 450 public static AuthorizationData decodeAuthorizationData( byte[] data ) throws KerberosException 451 { 452 ByteBuffer stream = ByteBuffer.allocate( data.length ); 453 stream.put( data ); 454 stream.flip(); 455 456 // Allocate a AuthorizationData Container 457 Asn1Container authorizationDataContainer = new AuthorizationDataContainer(); 458 459 // Decode the Ticket PDU 460 try 461 { 462 Asn1Decoder.decode( stream, authorizationDataContainer ); 463 } 464 catch ( DecoderException de ) 465 { 466 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 467 } 468 469 // get the decoded AuthorizationData 470 return ( ( AuthorizationDataContainer ) authorizationDataContainer ).getAuthorizationData(); 471 } 472 473 474 /** 475 * Decode a AP-REP structure 476 * 477 * @param data The byte array containing the data structure to decode 478 * @return An instance of ApRep 479 * @throws KerberosException If the decoding fails 480 */ 481 public static ApRep decodeApRep( byte[] data ) throws KerberosException 482 { 483 ByteBuffer stream = ByteBuffer.allocate( data.length ); 484 stream.put( data ); 485 stream.flip(); 486 487 // Allocate a ApRep Container 488 Asn1Container apRepContainer = new ApRepContainer( stream ); 489 490 // Decode the ApRep PDU 491 try 492 { 493 Asn1Decoder.decode( stream, apRepContainer ); 494 } 495 catch ( DecoderException de ) 496 { 497 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 498 } 499 500 // get the decoded ApRep 501 return ( ( ApRepContainer ) apRepContainer ).getApRep(); 502 } 503 504 505 /** 506 * Decode a AP-REQ structure 507 * 508 * @param data The byte array containing the data structure to decode 509 * @return An instance of ApReq 510 * @throws KerberosException If the decoding fails 511 */ 512 public static ApReq decodeApReq( byte[] data ) throws KerberosException 513 { 514 ByteBuffer stream = ByteBuffer.allocate( data.length ); 515 stream.put( data ); 516 stream.flip(); 517 518 // Allocate a ApReq Container 519 Asn1Container apReqContainer = new ApReqContainer( stream ); 520 521 // Decode the ApReq PDU 522 try 523 { 524 Asn1Decoder.decode( stream, apReqContainer ); 525 } 526 catch ( DecoderException de ) 527 { 528 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 529 } 530 531 // get the decoded ApReq 532 return ( ( ApReqContainer ) apReqContainer ).getApReq(); 533 } 534 535 536 /** 537 * Decode a KRB-PRIV structure 538 * 539 * @param data The byte array containing the data structure to decode 540 * @return An instance of KrbPriv 541 * @throws KerberosException If the decoding fails 542 */ 543 public static KrbPriv decodeKrbPriv( byte[] data ) throws KerberosException 544 { 545 ByteBuffer stream = ByteBuffer.allocate( data.length ); 546 stream.put( data ); 547 stream.flip(); 548 549 // Allocate a KrbPriv Container 550 Asn1Container krbPrivContainer = new KrbPrivContainer( stream ); 551 552 // Decode the KrbPriv PDU 553 try 554 { 555 Asn1Decoder.decode( stream, krbPrivContainer ); 556 } 557 catch ( DecoderException de ) 558 { 559 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 560 } 561 562 // get the decoded KrbPriv 563 return ( ( KrbPrivContainer ) krbPrivContainer ).getKrbPriv(); 564 } 565 566 567 /** 568 * Decode an EncAsRepPart structure 569 * 570 * @param data The byte array containing the data structure to decode 571 * @return An instance of EncAsRepPart 572 * @throws KerberosException If the decoding fails 573 */ 574 public static EncAsRepPart decodeEncAsRepPart( byte[] data ) throws KerberosException 575 { 576 ByteBuffer stream = ByteBuffer.allocate( data.length ); 577 stream.put( data ); 578 stream.flip(); 579 580 // Allocate a EncAsRepPart Container 581 Asn1Container encAsRepPartContainer = new EncAsRepPartContainer( stream ); 582 583 // Decode the EncAsRepPart PDU 584 try 585 { 586 Asn1Decoder.decode( stream, encAsRepPartContainer ); 587 } 588 catch ( DecoderException de ) 589 { 590 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de ); 591 } 592 593 // get the decoded EncAsRepPart 594 return ( ( EncAsRepPartContainer ) encAsRepPartContainer ).getEncAsRepPart(); 595 } 596 597 598 /** 599 * Decode an EncTgsRepPart structure 600 * 601 * @param data The byte array containing the data structure to decode 602 * @return An instance of EncTgsRepPart 603 * @throws ChangePasswordException If the decoding fails 604 */ 605 public static EncTgsRepPart decodeEncTgsRepPart( byte[] data ) throws ChangePasswordException 606 { 607 ByteBuffer stream = ByteBuffer.allocate( data.length ); 608 stream.put( data ); 609 stream.flip(); 610 611 // Allocate a EncTgsRepPart Container 612 Asn1Container encTgsRepPartContainer = new EncTgsRepPartContainer( stream ); 613 614 // Decode the EncTgsRepPart PDU 615 try 616 { 617 Asn1Decoder.decode( stream, encTgsRepPartContainer ); 618 } 619 catch ( DecoderException de ) 620 { 621 throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_MALFORMED, de ); 622 } 623 624 // get the decoded EncTgsRepPart 625 return ( ( EncTgsRepPartContainer ) encTgsRepPartContainer ).getEncTgsRepPart(); 626 } 627}