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