001/*
002 * Copyright 2011-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2011-2017 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk;
022
023
024
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.Arrays;
028import java.util.Collection;
029import java.util.Collections;
030import java.util.Iterator;
031import java.util.LinkedHashSet;
032import java.util.List;
033import java.util.Set;
034
035import com.unboundid.asn1.ASN1OctetString;
036import com.unboundid.util.Mutable;
037import com.unboundid.util.StaticUtils;
038import com.unboundid.util.ThreadSafety;
039import com.unboundid.util.ThreadSafetyLevel;
040import com.unboundid.util.Validator;
041
042
043
044/**
045 * This class provides a data structure that may be used to hold a number of
046 * properties that may be used during processing for a SASL GSSAPI bind
047 * operation.
048 */
049@Mutable()
050@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
051public final class GSSAPIBindRequestProperties
052       implements Serializable
053{
054  /**
055   * The serial version UID for this serializable class.
056   */
057  private static final long serialVersionUID = 6872295509330315713L;
058
059
060
061  // The password for the GSSAPI bind request.
062  private ASN1OctetString password;
063
064  // Indicates whether to enable JVM-level debugging for GSSAPI processing.
065  private boolean enableGSSAPIDebugging;
066
067  // Indicates whether the client should be considered the GSSAPI initiator or
068  // the acceptor.
069  private Boolean isInitiator;
070
071  // Indicates whether to attempt to refresh the configuration before the JAAS
072  // login method is called.
073  private boolean refreshKrb5Config;
074
075  // Indicates whether to attempt to renew the client's existing ticket-granting
076  // ticket if authentication uses an existing Kerberos session.
077  private boolean renewTGT;
078
079  // Indicates whether to require that the credentials be obtained from the
080  // ticket cache such that authentication will fail if the client does not have
081  // an existing Kerberos session.
082  private boolean requireCachedCredentials;
083
084  // Indicates whether to allow the to obtain the credentials to be obtained
085  // from a keytab.
086  private boolean useKeyTab;
087
088  // Indicates whether to allow the client to use credentials that are outside
089  // of the current subject.
090  private boolean useSubjectCredentialsOnly;
091
092  // Indicates whether to enable the use of a ticket cache.
093  private boolean useTicketCache;
094
095  // The SASL quality of protection value(s) allowed for the DIGEST-MD5 bind
096  // request.
097  private List<SASLQualityOfProtection> allowedQoP;
098
099  // The names of any system properties that should not be altered by GSSAPI
100  // processing.
101  private Set<String> suppressedSystemProperties;
102
103  // The authentication ID string for the GSSAPI bind request.
104  private String authenticationID;
105
106  // The authorization ID string for the GSSAPI bind request, if available.
107  private String authorizationID;
108
109  // The path to the JAAS configuration file to use for bind processing.
110  private String configFilePath;
111
112  // The name that will be used to identify this client in the JAAS framework.
113  private String jaasClientName;
114
115  // The KDC address for the GSSAPI bind request, if available.
116  private String kdcAddress;
117
118  // The path to the keytab file to use if useKeyTab is true.
119  private String keyTabPath;
120
121  // The realm for the GSSAPI bind request, if available.
122  private String realm;
123
124  // The server name to use when creating the SASL client.
125  private String saslClientServerName;
126
127  // The protocol that should be used in the Kerberos service principal for
128  // the server system.
129  private String servicePrincipalProtocol;
130
131  // The path to the Kerberos ticket cache to use.
132  private String ticketCachePath;
133
134
135
136  /**
137   * Creates a new set of GSSAPI bind request properties with the provided
138   * information.
139   *
140   * @param  authenticationID  The authentication ID for the GSSAPI bind
141   *                           request.  It may be {@code null} if an existing
142   *                           Kerberos session should be used.
143   * @param  password          The password for the GSSAPI bind request.  It may
144   *                           be {@code null} if an existing Kerberos session
145   *                           should be used.
146   */
147  public GSSAPIBindRequestProperties(final String authenticationID,
148                                     final String password)
149  {
150    this(authenticationID, null,
151         (password == null ? null : new ASN1OctetString(password)), null, null,
152         null);
153  }
154
155
156
157  /**
158   * Creates a new set of GSSAPI bind request properties with the provided
159   * information.
160   *
161   * @param  authenticationID  The authentication ID for the GSSAPI bind
162   *                           request.  It may be {@code null} if an existing
163   *                           Kerberos session should be used.
164   * @param  password          The password for the GSSAPI bind request.  It may
165   *                           be {@code null} if an existing Kerberos session
166   *                           should be used.
167   */
168  public GSSAPIBindRequestProperties(final String authenticationID,
169                                     final byte[] password)
170  {
171    this(authenticationID, null,
172         (password == null ? null : new ASN1OctetString(password)), null, null,
173         null);
174  }
175
176
177
178  /**
179   * Creates a new set of GSSAPI bind request properties with the provided
180   * information.
181   *
182   * @param  authenticationID  The authentication ID for the GSSAPI bind
183   *                           request.  It may be {@code null} if an existing
184   *                           Kerberos session should be used.
185   * @param  authorizationID   The authorization ID for the GSSAPI bind request.
186   *                           It may be {@code null} if the authorization ID
187   *                           should be the same as the authentication ID.
188   * @param  password          The password for the GSSAPI bind request.  It may
189   *                           be {@code null} if an existing Kerberos session
190   *                           should be used.
191   * @param  realm             The realm to use for the authentication.  It may
192   *                           be {@code null} to attempt to use the default
193   *                           realm from the system configuration.
194   * @param  kdcAddress        The address of the Kerberos key distribution
195   *                           center.  It may be {@code null} to attempt to use
196   *                           the default KDC from the system configuration.
197   * @param  configFilePath    The path to the JAAS configuration file to use
198   *                           for the authentication processing.  It may be
199   *                           {@code null} to use the default JAAS
200   *                           configuration.
201   */
202  GSSAPIBindRequestProperties(final String authenticationID,
203                              final String authorizationID,
204                              final ASN1OctetString password,
205                              final String realm,
206                              final String kdcAddress,
207                              final String configFilePath)
208  {
209    this.authenticationID = authenticationID;
210    this.authorizationID  = authorizationID;
211    this.password         = password;
212    this.realm            = realm;
213    this.kdcAddress       = kdcAddress;
214    this.configFilePath   = configFilePath;
215
216    servicePrincipalProtocol   = "ldap";
217    enableGSSAPIDebugging      = false;
218    jaasClientName             = "GSSAPIBindRequest";
219    isInitiator                = null;
220    refreshKrb5Config          = false;
221    renewTGT                   = false;
222    useKeyTab                  = false;
223    useSubjectCredentialsOnly  = true;
224    useTicketCache             = true;
225    requireCachedCredentials   = false;
226    saslClientServerName       = null;
227    keyTabPath                 = null;
228    ticketCachePath            = null;
229    suppressedSystemProperties = Collections.emptySet();
230    allowedQoP                 = Collections.unmodifiableList(Arrays.asList(
231         SASLQualityOfProtection.AUTH));
232  }
233
234
235
236  /**
237   * Retrieves the authentication ID for the GSSAPI bind request, if defined.
238   *
239   * @return  The authentication ID for the GSSAPI bind request, or {@code null}
240   *          if an existing Kerberos session should be used.
241   */
242  public String getAuthenticationID()
243  {
244    return authenticationID;
245  }
246
247
248
249  /**
250   * Sets the authentication ID for the GSSAPI bind request.
251   *
252   * @param  authenticationID  The authentication ID for the GSSAPI bind
253   *                           request.  It may be {@code null} if an existing
254   *                           Kerberos session should be used.
255   */
256  public void setAuthenticationID(final String authenticationID)
257  {
258    this.authenticationID = authenticationID;
259  }
260
261
262
263  /**
264   * Retrieves the authorization ID for the GSSAPI bind request, if defined.
265   *
266   * @return  The authorizationID for the GSSAPI bind request, or {@code null}
267   *          if the authorization ID should be the same as the authentication
268   *          ID.
269   */
270  public String getAuthorizationID()
271  {
272    return authorizationID;
273  }
274
275
276
277  /**
278   * Specifies the authorization ID for the GSSAPI bind request.
279   *
280   * @param  authorizationID  The authorization ID for the GSSAPI bind request.
281   *                          It may be {@code null} if the authorization ID
282   *                          should be the same as the authentication ID.
283   */
284  public void setAuthorizationID(final String authorizationID)
285  {
286    this.authorizationID = authorizationID;
287  }
288
289
290
291  /**
292   * Retrieves the password that should be used for the GSSAPI bind request, if
293   * defined.
294   *
295   * @return  The password that should be used for the GSSAPI bind request, or
296   *          {@code null} if an existing Kerberos session should be used.
297   */
298  public ASN1OctetString getPassword()
299  {
300    return password;
301  }
302
303
304
305  /**
306   * Specifies the password that should be used for the GSSAPI bind request.
307   *
308   * @param  password  The password that should be used for the GSSAPI bind
309   *                   request.  It may be {@code null} if an existing
310   *                   Kerberos session should be used.
311   */
312  public void setPassword(final String password)
313  {
314    if (password == null)
315    {
316      this.password = null;
317    }
318    else
319    {
320      this.password = new ASN1OctetString(password);
321    }
322  }
323
324
325
326  /**
327   * Specifies the password that should be used for the GSSAPI bind request.
328   *
329   * @param  password  The password that should be used for the GSSAPI bind
330   *                   request.  It may be {@code null} if an existing
331   *                   Kerberos session should be used.
332   */
333  public void setPassword(final byte[] password)
334  {
335    if (password == null)
336    {
337      this.password = null;
338    }
339    else
340    {
341      this.password = new ASN1OctetString(password);
342    }
343  }
344
345
346
347  /**
348   * Specifies the password that should be used for the GSSAPI bind request.
349   *
350   * @param  password  The password that should be used for the GSSAPI bind
351   *                   request.  It may be {@code null} if an existing
352   *                   Kerberos session should be used.
353   */
354  public void setPassword(final ASN1OctetString password)
355  {
356    this.password = password;
357  }
358
359
360
361  /**
362   * Retrieves the realm to use for the GSSAPI bind request, if defined.
363   *
364   * @return  The realm to use for the GSSAPI bind request, or {@code null} if
365   *          the request should attempt to use the default realm from the
366   *          system configuration.
367   */
368  public String getRealm()
369  {
370    return realm;
371  }
372
373
374
375  /**
376   * Specifies the realm to use for the GSSAPI bind request.
377   *
378   * @param  realm  The realm to use for the GSSAPI bind request.  It may be
379   *                {@code null} if the request should attempt to use the
380   *                default realm from the system configuration.
381   */
382  public void setRealm(final String realm)
383  {
384    this.realm = realm;
385  }
386
387
388
389  /**
390   * Retrieves the list of allowed qualities of protection that may be used for
391   * communication that occurs on the connection after the authentication has
392   * completed, in order from most preferred to least preferred.
393   *
394   * @return  The list of allowed qualities of protection that may be used for
395   *          communication that occurs on the connection after the
396   *          authentication has completed, in order from most preferred to
397   *          least preferred.
398   */
399  public List<SASLQualityOfProtection> getAllowedQoP()
400  {
401    return allowedQoP;
402  }
403
404
405
406  /**
407   * Specifies the list of allowed qualities of protection that may be used for
408   * communication that occurs on the connection after the authentication has
409   * completed, in order from most preferred to least preferred.
410   *
411   * @param  allowedQoP  The list of allowed qualities of protection that may be
412   *                     used for communication that occurs on the connection
413   *                     after the authentication has completed, in order from
414   *                     most preferred to least preferred.  If this is
415   *                     {@code null} or empty, then a list containing only the
416   *                     {@link SASLQualityOfProtection#AUTH} quality of
417   *                     protection value will be used.
418   */
419  public void setAllowedQoP(final List<SASLQualityOfProtection> allowedQoP)
420  {
421    if ((allowedQoP == null) || allowedQoP.isEmpty())
422    {
423      this.allowedQoP = Collections.unmodifiableList(Arrays.asList(
424           SASLQualityOfProtection.AUTH));
425    }
426    else
427    {
428      this.allowedQoP = Collections.unmodifiableList(
429           new ArrayList<SASLQualityOfProtection>(allowedQoP));
430    }
431  }
432
433
434
435  /**
436   * Specifies the list of allowed qualities of protection that may be used for
437   * communication that occurs on the connection after the authentication has
438   * completed, in order from most preferred to least preferred.
439   *
440   * @param  allowedQoP  The list of allowed qualities of protection that may be
441   *                     used for communication that occurs on the connection
442   *                     after the authentication has completed, in order from
443   *                     most preferred to least preferred.  If this is
444   *                     {@code null} or empty, then a list containing only the
445   *                     {@link SASLQualityOfProtection#AUTH} quality of
446   *                     protection value will be used.
447   */
448  public void setAllowedQoP(final SASLQualityOfProtection... allowedQoP)
449  {
450    setAllowedQoP(StaticUtils.toList(allowedQoP));
451  }
452
453
454
455  /**
456   * Retrieves the address to use for the Kerberos key distribution center,
457   * if defined.
458   *
459   * @return  The address to use for the Kerberos key distribution center, or
460   *          {@code null} if request should attempt to determine the KDC
461   *          address from the system configuration.
462   */
463  public String getKDCAddress()
464  {
465    return kdcAddress;
466  }
467
468
469
470  /**
471   * Specifies the address to use for the Kerberos key distribution center.
472   *
473   * @param  kdcAddress  The address to use for the Kerberos key distribution
474   *                     center.  It may be {@code null} if the request should
475   *                     attempt to determine the KDC address from the system
476   *                     configuration.
477   */
478  public void setKDCAddress(final String kdcAddress)
479  {
480    this.kdcAddress = kdcAddress;
481  }
482
483
484
485  /**
486   * Retrieves the name that will be used to identify this client in the JAAS
487   * framework.
488   *
489   * @return  The name that will be used to identify this client in the JAAS
490   *          framework.
491   */
492  public String getJAASClientName()
493  {
494    return jaasClientName;
495  }
496
497
498
499  /**
500   * Specifies the name that will be used to identify this client in the JAAS
501   * framework.
502   *
503   * @param  jaasClientName  The name that will be used to identify this client
504   *                         in the JAAS framework.  It must not be
505   *                         {@code null} or empty.
506   */
507  public void setJAASClientName(final String jaasClientName)
508  {
509    Validator.ensureNotNull(jaasClientName);
510
511    this.jaasClientName = jaasClientName;
512  }
513
514
515
516  /**
517   * Retrieves the path to a JAAS configuration file that should be used when
518   * processing the GSSAPI bind request, if defined.
519   *
520   * @return  The path to a JAAS configuration file that should be used when
521   *          processing the GSSAPI bind request, or {@code null} if a JAAS
522   *          configuration file should be automatically constructed for the
523   *          bind request.
524   */
525  public String getConfigFilePath()
526  {
527    return configFilePath;
528  }
529
530
531
532  /**
533   * Specifies the path to a JAAS configuration file that should be used when
534   * processing the GSSAPI bind request.
535   *
536   * @param  configFilePath  The path to a JAAS configuration file that should
537   *                         be used when processing the GSSAPI bind request.
538   *                         It may be {@code null} if a configuration file
539   *                         should be automatically constructed for the bind
540   *                         request.
541   */
542  public void setConfigFilePath(final String configFilePath)
543  {
544    this.configFilePath = configFilePath;
545  }
546
547
548
549  /**
550   * Retrieves the server name that should be used when creating the Java
551   * {@code SaslClient}, if one is defined.
552   *
553   * @return  The server name that should be used when creating the Java
554   *          {@code SaslClient}, or {@code null} if none is defined and the
555   *          {@code SaslClient} should use the address specified when
556   *          establishing the connection.
557   */
558  public String getSASLClientServerName()
559  {
560    return saslClientServerName;
561  }
562
563
564
565  /**
566   * Specifies the server name that should be used when creating the Java
567   * {@code SaslClient}.
568   *
569   * @param  saslClientServerName  The server name that should be used when
570   *                               creating the Java {@code SaslClient}.  It may
571   *                               be {@code null} to indicate that the
572   *                               {@code SaslClient} should use the address
573   *                               specified when establishing the connection.
574   */
575  public void setSASLClientServerName(final String saslClientServerName)
576  {
577    this.saslClientServerName = saslClientServerName;
578  }
579
580
581
582  /**
583   * Retrieves the protocol specified in the service principal that the
584   * directory server uses for its communication with the KDC.  The service
585   * principal is usually something like "ldap/directory.example.com", where
586   * "ldap" is the protocol and "directory.example.com" is the fully-qualified
587   * address of the directory server system, but some servers may allow
588   * authentication with a service principal with a protocol other than "ldap".
589   *
590   * @return  The protocol specified in the service principal that the directory
591   *          server uses for its communication with the KDC.
592   */
593  public String getServicePrincipalProtocol()
594  {
595    return servicePrincipalProtocol;
596  }
597
598
599
600  /**
601   * Specifies the protocol specified in the service principal that the
602   * directory server uses for its communication with the KDC.  This should
603   * generally be "ldap", but some servers may allow a service principal with a
604   * protocol other than "ldap".
605   *
606   * @param  servicePrincipalProtocol  The protocol specified in the service
607   *                                   principal that the directory server uses
608   *                                   for its communication with the KDC.
609   */
610  public void setServicePrincipalProtocol(final String servicePrincipalProtocol)
611  {
612    Validator.ensureNotNull(servicePrincipalProtocol);
613
614    this.servicePrincipalProtocol = servicePrincipalProtocol;
615  }
616
617
618
619  /**
620   * Indicates whether to refresh the configuration before the JAAS
621   * {@code login} method is called.
622   *
623   * @return  {@code true} if the GSSAPI implementation should refresh the
624   *          configuration before the JAAS {@code login} method is called, or
625   *          {@code false} if not.
626   */
627  public boolean refreshKrb5Config()
628  {
629    return refreshKrb5Config;
630  }
631
632
633
634  /**
635   * Specifies whether to refresh the configuration before the JAAS
636   * {@code login} method is called.
637   *
638   * @param  refreshKrb5Config  Indicates whether to refresh the configuration
639   *                            before the JAAS {@code login} method is called.
640   */
641  public void setRefreshKrb5Config(final boolean refreshKrb5Config)
642  {
643    this.refreshKrb5Config = refreshKrb5Config;
644  }
645
646
647
648  /**
649   * Indicates whether to allow the client to use credentials that are outside
650   * of the current subject, obtained via some system-specific mechanism.
651   *
652   * @return  {@code true} if the client will only be allowed to use credentials
653   *          that are within the current subject, or {@code false} if the
654   *          client will be allowed to use credentials outside the current
655   *          subject.
656   */
657  public boolean useSubjectCredentialsOnly()
658  {
659    return useSubjectCredentialsOnly;
660  }
661
662
663
664  /**
665   * Specifies whether to allow the client to use credentials that are outside
666   * the current subject.  If this is {@code false}, then a system-specific
667   * mechanism may be used in an attempt to obtain credentials from an
668   * existing session.
669   *
670   * @param  useSubjectCredentialsOnly  Indicates whether to allow the client to
671   *                                    use credentials that are outside of the
672   *                                    current subject.
673   */
674  public void setUseSubjectCredentialsOnly(
675                   final boolean useSubjectCredentialsOnly)
676  {
677    this.useSubjectCredentialsOnly = useSubjectCredentialsOnly;
678  }
679
680
681
682  /**
683   * Indicates whether to use a keytab to obtain the user credentials.
684   *
685   * @return  {@code true} if the GSSAPI login attempt should use a keytab to
686   *          obtain the user credentials, or {@code false} if not.
687   */
688  public boolean useKeyTab()
689  {
690    return useKeyTab;
691  }
692
693
694
695  /**
696   * Specifies whether to use a keytab to obtain the user credentials.
697   *
698   * @param  useKeyTab  Indicates whether to use a keytab to obtain the user
699   *                    credentials.
700   */
701  public void setUseKeyTab(final boolean useKeyTab)
702  {
703    this.useKeyTab = useKeyTab;
704  }
705
706
707
708  /**
709   * Retrieves the path to the keytab file from which to obtain the user
710   * credentials.  This will only be used if {@link #useKeyTab} returns
711   * {@code true}.
712   *
713   * @return  The path to the keytab file from which to obtain the user
714   *          credentials, or {@code null} if the default keytab location should
715   *          be used.
716   */
717  public String getKeyTabPath()
718  {
719    return keyTabPath;
720  }
721
722
723
724  /**
725   * Specifies the path to the keytab file from which to obtain the user
726   * credentials.
727   *
728   * @param  keyTabPath  The path to the keytab file from which to obtain the
729   *                     user credentials.  It may be {@code null} if the
730   *                     default keytab location should be used.
731   */
732  public void setKeyTabPath(final String keyTabPath)
733  {
734    this.keyTabPath = keyTabPath;
735  }
736
737
738
739  /**
740   * Indicates whether to enable the use of a ticket cache to to avoid the need
741   * to supply credentials if the client already has an existing Kerberos
742   * session.
743   *
744   * @return  {@code true} if a ticket cache may be used to take advantage of an
745   *          existing Kerberos session, or {@code false} if Kerberos
746   *          credentials should always be provided.
747   */
748  public boolean useTicketCache()
749  {
750    return useTicketCache;
751  }
752
753
754
755  /**
756   * Specifies whether to enable the use of a ticket cache to to avoid the need
757   * to supply credentials if the client already has an existing Kerberos
758   * session.
759   *
760   * @param  useTicketCache  Indicates whether to enable the use of a ticket
761   *                         cache to to avoid the need to supply credentials if
762   *                         the client already has an existing Kerberos
763   *                         session.
764   */
765  public void setUseTicketCache(final boolean useTicketCache)
766  {
767    this.useTicketCache = useTicketCache;
768  }
769
770
771
772  /**
773   * Indicates whether GSSAPI authentication should only occur using an existing
774   * Kerberos session.
775   *
776   * @return  {@code true} if GSSAPI authentication should only use an existing
777   *          Kerberos session and should fail if the client does not have an
778   *          existing session, or {@code false} if the client will be allowed
779   *          to create a new session if one does not already exist.
780   */
781  public boolean requireCachedCredentials()
782  {
783    return requireCachedCredentials;
784  }
785
786
787
788  /**
789   * Specifies whether an GSSAPI authentication should only occur using an
790   * existing Kerberos session.
791   *
792   * @param  requireCachedCredentials  Indicates whether an existing Kerberos
793   *                                   session will be required for
794   *                                   authentication.  If {@code true}, then
795   *                                   authentication will fail if the client
796   *                                   does not already have an existing
797   *                                   Kerberos session.  This will be ignored
798   *                                   if {@code useTicketCache} is false.
799   */
800  public void setRequireCachedCredentials(
801                   final boolean requireCachedCredentials)
802  {
803    this.requireCachedCredentials = requireCachedCredentials;
804  }
805
806
807
808  /**
809   * Retrieves the path to the Kerberos ticket cache file that should be used
810   * during authentication, if defined.
811   *
812   * @return  The path to the Kerberos ticket cache file that should be used
813   *          during authentication, or {@code null} if the default ticket cache
814   *          file should be used.
815   */
816  public String getTicketCachePath()
817  {
818    return ticketCachePath;
819  }
820
821
822
823  /**
824   * Specifies the path to the Kerberos ticket cache file that should be used
825   * during authentication.
826   *
827   * @param  ticketCachePath  The path to the Kerberos ticket cache file that
828   *                          should be used during authentication.  It may be
829   *                          {@code null} if the default ticket cache file
830   *                          should be used.
831   */
832  public void setTicketCachePath(final String ticketCachePath)
833  {
834    this.ticketCachePath = ticketCachePath;
835  }
836
837
838
839  /**
840   * Indicates whether to attempt to renew the client's ticket-granting ticket
841   * (TGT) if an existing Kerberos session is used to authenticate.
842   *
843   * @return  {@code true} if the client should attempt to renew its
844   *          ticket-granting ticket if the authentication is processed using an
845   *          existing Kerberos session, or {@code false} if not.
846   */
847  public boolean renewTGT()
848  {
849    return renewTGT;
850  }
851
852
853
854  /**
855   * Specifies whether to attempt to renew the client's ticket-granting ticket
856   * (TGT) if an existing Kerberos session is used to authenticate.
857   *
858   * @param  renewTGT  Indicates whether to attempt to renew the client's
859   *                   ticket-granting ticket if an existing Kerberos session is
860   *                   used to authenticate.
861   */
862  public void setRenewTGT(final boolean renewTGT)
863  {
864    this.renewTGT = renewTGT;
865  }
866
867
868
869  /**
870   * Indicates whether the client should be configured so that it explicitly
871   * indicates whether it is the initiator or the acceptor.
872   *
873   * @return  {@code Boolean.TRUE} if the client should explicitly indicate that
874   *          it is the GSSAPI initiator, {@code Boolean.FALSE} if the client
875   *          should explicitly indicate that it is the GSSAPI acceptor, or
876   *          {@code null} if the client should not explicitly indicate either
877   *          state (which is the default if the {@link #setIsInitiator}  method
878   *          has not been called).
879   */
880  public Boolean getIsInitiator()
881  {
882    return isInitiator;
883  }
884
885
886
887  /**
888   * Specifies whether the client should explicitly indicate whether it is the
889   * GSSAPI initiator or acceptor.
890   *
891   * @param  isInitiator  Indicates whether the client should be considered the
892   *                      GSSAPI initiator.  A value of {@code Boolean.TRUE}
893   *                      means the client should explicitly indicate that it is
894   *                      the GSSAPI initiator.  A value of
895   *                      {@code Boolean.FALSE} means the client should
896   *                      explicitly indicate that it is the GSSAPI acceptor.  A
897   *                      value of  {@code null} means that the client will not
898   *                      explicitly indicate one way or the other (although
899   *                      this behavior will only apply to Sun/Oracle-based
900   *                      implementations; on the IBM implementation, the client
901   *                      will always be the initiator unless explicitly
902   *                      configured otherwise).
903   */
904  public void setIsInitiator(final Boolean isInitiator)
905  {
906    this.isInitiator = isInitiator;
907  }
908
909
910
911  /**
912   * Retrieves a set of system properties that will not be altered by GSSAPI
913   * processing.
914   *
915   * @return  A set of system properties that will not be altered by GSSAPI
916   *          processing.
917   */
918  public Set<String> getSuppressedSystemProperties()
919  {
920    return suppressedSystemProperties;
921  }
922
923
924
925  /**
926   * Specifies a set of system properties that will not be altered by GSSAPI
927   * processing.  This should generally only be used in cases in which the
928   * specified system properties are known to already be set correctly for the
929   * desired authentication processing.
930   *
931   * @param  suppressedSystemProperties  A set of system properties that will
932   *                                     not be altered by GSSAPI processing.
933   *                                     It may be {@code null} or empty to
934   *                                     indicate that no properties should be
935   *                                     suppressed.
936   */
937  public void setSuppressedSystemProperties(
938                   final Collection<String> suppressedSystemProperties)
939  {
940    if (suppressedSystemProperties == null)
941    {
942      this.suppressedSystemProperties = Collections.emptySet();
943    }
944    else
945    {
946      this.suppressedSystemProperties = Collections.unmodifiableSet(
947           new LinkedHashSet<String>(suppressedSystemProperties));
948    }
949  }
950
951
952
953  /**
954   * Indicates whether JVM-level debugging should be enabled for GSSAPI bind
955   * processing.  If this is enabled, then debug information may be written to
956   * standard error when performing GSSAPI processing that could be useful for
957   * debugging authentication problems.
958   *
959   * @return  {@code true} if JVM-level debugging should be enabled for GSSAPI
960   *          bind processing, or {@code false} if not.
961   */
962  public boolean enableGSSAPIDebugging()
963  {
964    return enableGSSAPIDebugging;
965  }
966
967
968
969  /**
970   * Specifies whether JVM-level debugging should be enabled for GSSAPI bind
971   * processing.  If this is enabled, then debug information may be written to
972   * standard error when performing GSSAPI processing that could be useful for
973   * debugging authentication problems.
974   *
975   * @param  enableGSSAPIDebugging  Specifies whether JVM-level debugging should
976   *                                be enabled for GSSAPI bind processing.
977   */
978  public void setEnableGSSAPIDebugging(final boolean enableGSSAPIDebugging)
979  {
980    this.enableGSSAPIDebugging = enableGSSAPIDebugging;
981  }
982
983
984
985  /**
986   * Retrieves a string representation of the GSSAPI bind request properties.
987   *
988   * @return  A string representation of the GSSAPI bind request properties.
989   */
990  @Override()
991  public String toString()
992  {
993    final StringBuilder buffer = new StringBuilder();
994    toString(buffer);
995    return buffer.toString();
996  }
997
998
999
1000  /**
1001   * Appends a string representation of the GSSAPI bind request properties to
1002   * the provided buffer.
1003   *
1004   * @param  buffer  The buffer to which the information should be appended.
1005   */
1006  public void toString(final StringBuilder buffer)
1007  {
1008    buffer.append("GSSAPIBindRequestProperties(");
1009    if (authenticationID != null)
1010    {
1011      buffer.append("authenticationID='");
1012      buffer.append(authenticationID);
1013      buffer.append("', ");
1014    }
1015
1016    if (authorizationID != null)
1017    {
1018      buffer.append("authorizationID='");
1019      buffer.append(authorizationID);
1020      buffer.append("', ");
1021    }
1022
1023    if (realm != null)
1024    {
1025      buffer.append("realm='");
1026      buffer.append(realm);
1027      buffer.append("', ");
1028    }
1029
1030    buffer.append("qop='");
1031    buffer.append(SASLQualityOfProtection.toString(allowedQoP));
1032    buffer.append("', ");
1033
1034    if (kdcAddress != null)
1035    {
1036      buffer.append("kdcAddress='");
1037      buffer.append(kdcAddress);
1038      buffer.append("', ");
1039    }
1040
1041    buffer.append(", refreshKrb5Config=");
1042    buffer.append(refreshKrb5Config);
1043    buffer.append(", useSubjectCredentialsOnly=");
1044    buffer.append(useSubjectCredentialsOnly);
1045    buffer.append(", useKeyTab=");
1046    buffer.append(useKeyTab);
1047    buffer.append(", ");
1048
1049    if (keyTabPath != null)
1050    {
1051      buffer.append("keyTabPath='");
1052      buffer.append(keyTabPath);
1053      buffer.append("', ");
1054    }
1055
1056    if (useTicketCache)
1057    {
1058      buffer.append("useTicketCache=true, requireCachedCredentials=");
1059      buffer.append(requireCachedCredentials);
1060      buffer.append(", renewTGT=");
1061      buffer.append(renewTGT);
1062      buffer.append(", ");
1063
1064      if (ticketCachePath != null)
1065      {
1066        buffer.append("ticketCachePath='");
1067        buffer.append(ticketCachePath);
1068        buffer.append("', ");
1069      }
1070    }
1071    else
1072    {
1073      buffer.append("useTicketCache=false, ");
1074    }
1075
1076    if (isInitiator != null)
1077    {
1078      buffer.append("isInitiator=");
1079      buffer.append(isInitiator);
1080      buffer.append(", ");
1081    }
1082
1083    buffer.append("jaasClientName='");
1084    buffer.append(jaasClientName);
1085    buffer.append("', ");
1086
1087    if (configFilePath != null)
1088    {
1089      buffer.append("configFilePath='");
1090      buffer.append(configFilePath);
1091      buffer.append("', ");
1092    }
1093
1094    if (saslClientServerName != null)
1095    {
1096      buffer.append("saslClientServerName='");
1097      buffer.append(saslClientServerName);
1098      buffer.append("', ");
1099    }
1100
1101    buffer.append("servicePrincipalProtocol='");
1102    buffer.append(servicePrincipalProtocol);
1103    buffer.append("', suppressedSystemProperties={");
1104
1105    final Iterator<String> propIterator = suppressedSystemProperties.iterator();
1106    while (propIterator.hasNext())
1107    {
1108      buffer.append('\'');
1109      buffer.append(propIterator.next());
1110      buffer.append('\'');
1111
1112      if (propIterator.hasNext())
1113      {
1114        buffer.append(", ");
1115      }
1116    }
1117
1118    buffer.append("}, enableGSSAPIDebugging=");
1119    buffer.append(enableGSSAPIDebugging);
1120    buffer.append(')');
1121  }
1122}