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 16:33:59 +0200 (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 }