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 */ 020 package org.apache.directory.server.kerberos.kdc; 021 022 023 import java.io.IOException; 024 import java.util.HashSet; 025 import java.util.Set; 026 027 import javax.security.auth.kerberos.KerberosPrincipal; 028 029 import org.apache.directory.server.constants.ServerDNConstants; 030 import org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler; 031 import org.apache.directory.server.kerberos.protocol.KerberosTcpProtocolCodecFactory; 032 import org.apache.directory.server.kerberos.protocol.KerberosUdpProtocolCodecFactory; 033 import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType; 034 import org.apache.directory.server.kerberos.shared.store.DirectoryPrincipalStore; 035 import org.apache.directory.server.kerberos.shared.store.PrincipalStore; 036 import org.apache.directory.server.protocol.shared.DirectoryBackedService; 037 import org.apache.directory.server.protocol.shared.transport.TcpTransport; 038 import org.apache.directory.server.protocol.shared.transport.Transport; 039 import org.apache.directory.server.protocol.shared.transport.UdpTransport; 040 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException; 041 import org.apache.directory.shared.ldap.name.DN; 042 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; 043 import org.apache.mina.core.filterchain.IoFilterChainBuilder; 044 import org.apache.mina.core.service.IoAcceptor; 045 import org.apache.mina.filter.codec.ProtocolCodecFilter; 046 import org.apache.mina.transport.socket.DatagramAcceptor; 047 import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 048 import org.slf4j.Logger; 049 import org.slf4j.LoggerFactory; 050 051 052 /** 053 * Contains the configuration parameters for the Kerberos protocol provider. 054 * 055 * @org.apache.xbean.XBean 056 * 057 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 058 * @version $Rev: 923757 $, $Date: 2010-03-16 15:33:59 +0100 (Tue, 16 Mar 2010) $ 059 */ 060 public class KdcServer extends DirectoryBackedService 061 { 062 private static final long serialVersionUID = 522567370475574165L; 063 064 /** logger for this class */ 065 private static final Logger LOG = LoggerFactory.getLogger( KdcServer.class.getName() ); 066 067 068 /** The default kdc port */ 069 private static final int DEFAULT_IP_PORT = 88; 070 071 /** The default kdc service pid */ 072 private static final String DEFAULT_PID = "org.apache.directory.server.kerberos"; 073 074 /** The default kdc service name */ 075 private static final String DEFAULT_NAME = "ApacheDS Kerberos Service"; 076 077 /** The default kdc service principal */ 078 private static final String DEFAULT_PRINCIPAL = "krbtgt/EXAMPLE.COM@EXAMPLE.COM"; 079 080 /** The default kdc realm */ 081 private static final String DEFAULT_REALM = "EXAMPLE.COM"; 082 083 /** The default allowable clockskew */ 084 private static final long DEFAULT_ALLOWABLE_CLOCKSKEW = 5 * 60000; 085 086 /** The default encryption types */ 087 private static final String[] DEFAULT_ENCRYPTION_TYPES = new String[] 088 { "des-cbc-md5" }; 089 090 /** The default for allowing empty addresses */ 091 private static final boolean DEFAULT_EMPTY_ADDRESSES_ALLOWED = true; 092 093 /** The default for requiring encrypted timestamps */ 094 private static final boolean DEFAULT_PA_ENC_TIMESTAMP_REQUIRED = true; 095 096 /** The default for the maximum ticket lifetime */ 097 private static final int DEFAULT_TGS_MAXIMUM_TICKET_LIFETIME = 60000 * 1440; 098 099 /** The default for the maximum renewable lifetime */ 100 private static final int DEFAULT_TGS_MAXIMUM_RENEWABLE_LIFETIME = 60000 * 10080; 101 102 /** The default for allowing forwardable tickets */ 103 private static final boolean DEFAULT_TGS_FORWARDABLE_ALLOWED = true; 104 105 /** The default for allowing proxiable tickets */ 106 private static final boolean DEFAULT_TGS_PROXIABLE_ALLOWED = true; 107 108 /** The default for allowing postdated tickets */ 109 private static final boolean DEFAULT_TGS_POSTDATED_ALLOWED = true; 110 111 /** The default for allowing renewable tickets */ 112 private static final boolean DEFAULT_TGS_RENEWABLE_ALLOWED = true; 113 114 /** The default for verifying the body checksum */ 115 private static final boolean DEFAULT_VERIFY_BODY_CHECKSUM = true; 116 117 /** The encryption types. */ 118 private Set<EncryptionType> encryptionTypes; 119 120 /** The primary realm */ 121 private String primaryRealm = DEFAULT_REALM; 122 123 /** The service principal name. */ 124 private String servicePrincipal = DEFAULT_PRINCIPAL; 125 126 /** The allowable clock skew. */ 127 private long allowableClockSkew = DEFAULT_ALLOWABLE_CLOCKSKEW; 128 129 /** Whether pre-authentication by encrypted timestamp is required. */ 130 private boolean isPaEncTimestampRequired = DEFAULT_PA_ENC_TIMESTAMP_REQUIRED; 131 132 /** The maximum ticket lifetime. */ 133 private long maximumTicketLifetime = DEFAULT_TGS_MAXIMUM_TICKET_LIFETIME; 134 135 /** The maximum renewable lifetime. */ 136 private long maximumRenewableLifetime = DEFAULT_TGS_MAXIMUM_RENEWABLE_LIFETIME; 137 138 /** Whether empty addresses are allowed. */ 139 private boolean isEmptyAddressesAllowed = DEFAULT_EMPTY_ADDRESSES_ALLOWED; 140 141 /** Whether forwardable addresses are allowed. */ 142 private boolean isForwardableAllowed = DEFAULT_TGS_FORWARDABLE_ALLOWED; 143 144 /** Whether proxiable addresses are allowed. */ 145 private boolean isProxiableAllowed = DEFAULT_TGS_PROXIABLE_ALLOWED; 146 147 /** Whether postdated tickets are allowed. */ 148 private boolean isPostdatedAllowed = DEFAULT_TGS_POSTDATED_ALLOWED; 149 150 /** Whether renewable tickets are allowed. */ 151 private boolean isRenewableAllowed = DEFAULT_TGS_RENEWABLE_ALLOWED; 152 153 /** Whether to verify the body checksum. */ 154 private boolean isBodyChecksumVerified = DEFAULT_VERIFY_BODY_CHECKSUM; 155 156 157 /** 158 * Creates a new instance of KdcConfiguration. 159 */ 160 public KdcServer() 161 { 162 super.setServiceName( DEFAULT_NAME ); 163 super.setServiceId( DEFAULT_PID ); 164 super.setSearchBaseDn( ServerDNConstants.USER_EXAMPLE_COM_DN ); 165 166 prepareEncryptionTypes(); 167 } 168 169 170 /** 171 * Returns the allowable clock skew. 172 * 173 * @return The allowable clock skew. 174 */ 175 public long getAllowableClockSkew() 176 { 177 return allowableClockSkew; 178 } 179 180 181 /** 182 * @return the isEmptyAddressesAllowed 183 */ 184 public boolean isEmptyAddressesAllowed() 185 { 186 return isEmptyAddressesAllowed; 187 } 188 189 190 /** 191 * @return the isForwardableAllowed 192 */ 193 public boolean isForwardableAllowed() 194 { 195 return isForwardableAllowed; 196 } 197 198 199 /** 200 * @return the isPostdatedAllowed 201 */ 202 public boolean isPostdatedAllowed() 203 { 204 return isPostdatedAllowed; 205 } 206 207 208 /** 209 * @return the isProxiableAllowed 210 */ 211 public boolean isProxiableAllowed() 212 { 213 return isProxiableAllowed; 214 } 215 216 217 /** 218 * @return the isRenewableAllowed 219 */ 220 public boolean isRenewableAllowed() 221 { 222 return isRenewableAllowed; 223 } 224 225 226 /** 227 * @return the maximumRenewableLifetime 228 */ 229 public long getMaximumRenewableLifetime() 230 { 231 return maximumRenewableLifetime; 232 } 233 234 235 /** 236 * @return the maximumTicketLifetime 237 */ 238 public long getMaximumTicketLifetime() 239 { 240 return maximumTicketLifetime; 241 } 242 243 244 /** 245 * @param allowableClockSkew the allowableClockSkew to set 246 */ 247 public void setAllowableClockSkew( long allowableClockSkew ) 248 { 249 this.allowableClockSkew = allowableClockSkew; 250 } 251 252 253 /** 254 * Initialize the encryptionTypes set 255 * 256 * @param encryptionTypes the encryptionTypes to set 257 */ 258 public void setEncryptionTypes( EncryptionType[] encryptionTypes ) 259 { 260 if ( encryptionTypes != null ) 261 { 262 this.encryptionTypes.clear(); 263 264 for ( EncryptionType encryptionType:encryptionTypes ) 265 { 266 this.encryptionTypes.add( encryptionType ); 267 } 268 } 269 } 270 271 272 /** 273 * Initialize the encryptionTypes set 274 * 275 * @param encryptionTypes the encryptionTypes to set 276 */ 277 public void setEncryptionTypes( Set<EncryptionType> encryptionTypes ) 278 { 279 this.encryptionTypes = encryptionTypes; 280 } 281 282 283 /** 284 * @param isEmptyAddressesAllowed the isEmptyAddressesAllowed to set 285 */ 286 public void setEmptyAddressesAllowed( boolean isEmptyAddressesAllowed ) 287 { 288 this.isEmptyAddressesAllowed = isEmptyAddressesAllowed; 289 } 290 291 292 /** 293 * @param isForwardableAllowed the isForwardableAllowed to set 294 */ 295 public void setForwardableAllowed( boolean isForwardableAllowed ) 296 { 297 this.isForwardableAllowed = isForwardableAllowed; 298 } 299 300 301 /** 302 * @param isPaEncTimestampRequired the isPaEncTimestampRequired to set 303 */ 304 public void setPaEncTimestampRequired( boolean isPaEncTimestampRequired ) 305 { 306 this.isPaEncTimestampRequired = isPaEncTimestampRequired; 307 } 308 309 310 /** 311 * @param isPostdatedAllowed the isPostdatedAllowed to set 312 */ 313 public void setPostdatedAllowed( boolean isPostdatedAllowed ) 314 { 315 this.isPostdatedAllowed = isPostdatedAllowed; 316 } 317 318 319 /** 320 * @param isProxiableAllowed the isProxiableAllowed to set 321 */ 322 public void setProxiableAllowed( boolean isProxiableAllowed ) 323 { 324 this.isProxiableAllowed = isProxiableAllowed; 325 } 326 327 328 /** 329 * @param isRenewableAllowed the isRenewableAllowed to set 330 */ 331 public void setRenewableAllowed( boolean isRenewableAllowed ) 332 { 333 this.isRenewableAllowed = isRenewableAllowed; 334 } 335 336 337 /** 338 * @param kdcPrincipal the kdcPrincipal to set 339 */ 340 public void setKdcPrincipal( String kdcPrincipal ) 341 { 342 this.servicePrincipal = kdcPrincipal; 343 } 344 345 346 /** 347 * @param maximumRenewableLifetime the maximumRenewableLifetime to set 348 */ 349 public void setMaximumRenewableLifetime( long maximumRenewableLifetime ) 350 { 351 this.maximumRenewableLifetime = maximumRenewableLifetime; 352 } 353 354 355 /** 356 * @param maximumTicketLifetime the maximumTicketLifetime to set 357 */ 358 public void setMaximumTicketLifetime( long maximumTicketLifetime ) 359 { 360 this.maximumTicketLifetime = maximumTicketLifetime; 361 } 362 363 364 /** 365 * @param primaryRealm the primaryRealm to set 366 */ 367 public void setPrimaryRealm( String primaryRealm ) 368 { 369 this.primaryRealm = primaryRealm; 370 } 371 372 373 /** 374 * Returns the primary realm. 375 * 376 * @return The primary realm. 377 */ 378 public String getPrimaryRealm() 379 { 380 return primaryRealm; 381 } 382 383 384 /** 385 * Returns the service principal for this KDC service. 386 * 387 * @return The service principal for this KDC service. 388 */ 389 public KerberosPrincipal getServicePrincipal() 390 { 391 return new KerberosPrincipal( servicePrincipal ); 392 } 393 394 395 /** 396 * Returns the encryption types. 397 * 398 * @return The encryption types. 399 */ 400 public Set<EncryptionType> getEncryptionTypes() 401 { 402 return encryptionTypes; 403 } 404 405 406 /** 407 * Returns whether pre-authentication by encrypted timestamp is required. 408 * 409 * @return Whether pre-authentication by encrypted timestamp is required. 410 */ 411 public boolean isPaEncTimestampRequired() 412 { 413 return isPaEncTimestampRequired; 414 } 415 416 417 /** 418 * @return the isBodyChecksumVerified 419 */ 420 public boolean isBodyChecksumVerified() 421 { 422 return isBodyChecksumVerified; 423 } 424 425 426 /** 427 * @param isBodyChecksumVerified the isBodyChecksumVerified to set 428 */ 429 public void setBodyChecksumVerified( boolean isBodyChecksumVerified ) 430 { 431 this.isBodyChecksumVerified = isBodyChecksumVerified; 432 } 433 434 435 /** 436 * @throws IOException if we cannot bind to the sockets 437 */ 438 public void start() throws IOException, LdapInvalidDnException 439 { 440 PrincipalStore store; 441 442 // TODO - for now ignoring this catalog crap 443 store = new DirectoryPrincipalStore( getDirectoryService(), new DN(this.getSearchBaseDn()) ); 444 445 if ( ( transports == null ) || ( transports.size() == 0 ) ) 446 { 447 // Default to UDP with port 88 448 // We have to create a DatagramAcceptor 449 UdpTransport transport = new UdpTransport( DEFAULT_IP_PORT ); 450 setTransports( transport ); 451 452 DatagramAcceptor acceptor = (DatagramAcceptor)transport.getAcceptor(); 453 454 // Inject the chain 455 IoFilterChainBuilder udpChainBuilder = new DefaultIoFilterChainBuilder(); 456 457 ((DefaultIoFilterChainBuilder)udpChainBuilder).addFirst( "codec", 458 new ProtocolCodecFilter( 459 KerberosUdpProtocolCodecFactory.getInstance() ) ); 460 461 acceptor.setFilterChainBuilder( udpChainBuilder ); 462 463 // Inject the protocol handler 464 acceptor.setHandler( new KerberosProtocolHandler( this, store ) ); 465 466 // Bind to the configured address 467 acceptor.bind(); 468 } 469 else 470 { 471 // Kerberos can use UDP or TCP 472 for ( Transport transport:transports ) 473 { 474 IoAcceptor acceptor = transport.getAcceptor(); 475 476 // Now, configure the acceptor 477 // Inject the chain 478 IoFilterChainBuilder chainBuilder = new DefaultIoFilterChainBuilder(); 479 480 if ( transport instanceof TcpTransport ) 481 { 482 // Now, configure the acceptor 483 // Disable the disconnection of the clients on unbind 484 acceptor.setCloseOnDeactivation( false ); 485 486 // No Nagle's algorithm 487 ((NioSocketAcceptor)acceptor).getSessionConfig().setTcpNoDelay( true ); 488 489 // Allow the port to be reused even if the socket is in TIME_WAIT state 490 ((NioSocketAcceptor)acceptor).setReuseAddress( true ); 491 492 // Inject the codec 493 ((DefaultIoFilterChainBuilder)chainBuilder).addFirst( "codec", 494 new ProtocolCodecFilter( 495 KerberosTcpProtocolCodecFactory.getInstance() ) ); 496 } 497 else 498 { 499 // Inject the codec 500 ((DefaultIoFilterChainBuilder)chainBuilder).addFirst( "codec", 501 new ProtocolCodecFilter( 502 KerberosUdpProtocolCodecFactory.getInstance() ) ); 503 } 504 505 acceptor.setFilterChainBuilder( chainBuilder ); 506 507 // Inject the protocol handler 508 acceptor.setHandler( new KerberosProtocolHandler( this, store ) ); 509 510 // Bind to the configured address 511 acceptor.bind(); 512 } 513 } 514 515 LOG.info( "Kerberos service started." ); 516 System.out.println( "Kerberos service started." ); 517 } 518 519 520 public void stop() 521 { 522 for ( Transport transport :getTransports() ) 523 { 524 IoAcceptor acceptor = transport.getAcceptor(); 525 526 if ( acceptor != null ) 527 { 528 acceptor.dispose(); 529 } 530 } 531 532 LOG.info( "Kerberos service stopped." ); 533 System.out.println( "Kerberos service stopped." ); 534 } 535 536 537 /** 538 * Construct an HashSet containing the default encryption types 539 */ 540 private void prepareEncryptionTypes() 541 { 542 String[] encryptionTypeStrings = DEFAULT_ENCRYPTION_TYPES; 543 544 encryptionTypes = new HashSet<EncryptionType>(); 545 546 for ( String enc : encryptionTypeStrings ) 547 { 548 for ( EncryptionType type : EncryptionType.getEncryptionTypes() ) 549 { 550 if ( type.getName().equalsIgnoreCase( enc ) ) 551 { 552 encryptionTypes.add( type ); 553 } 554 } 555 } 556 } 557 558 559 /** 560 * @see Object#toString() 561 */ 562 public String toString() 563 { 564 StringBuilder sb = new StringBuilder(); 565 566 sb.append( "KDCServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' ); 567 568 if ( getTransports() != null ) 569 { 570 for ( Transport transport:getTransports() ) 571 { 572 sb.append( " " ).append( transport ).append( '\n' ); 573 } 574 } 575 576 return sb.toString(); 577 } 578 }