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