001    /*
002     * Copyright 2011-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2011-2015 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     */
021    package com.unboundid.ldap.sdk;
022    
023    
024    
025    import java.io.Serializable;
026    import java.util.ArrayList;
027    import java.util.Arrays;
028    import java.util.Collection;
029    import java.util.Collections;
030    import java.util.Iterator;
031    import java.util.LinkedHashSet;
032    import java.util.List;
033    import java.util.Set;
034    
035    import com.unboundid.asn1.ASN1OctetString;
036    import com.unboundid.util.Mutable;
037    import com.unboundid.util.StaticUtils;
038    import com.unboundid.util.ThreadSafety;
039    import com.unboundid.util.ThreadSafetyLevel;
040    import 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)
051    public 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 to attempt to renew the client's existing ticket-granting
068      // ticket if authentication uses an existing Kerberos session.
069      private boolean renewTGT;
070    
071      // Indicates whether to require that the credentials be obtained from the
072      // ticket cache such that authentication will fail if the client does not have
073      // an existing Kerberos session.
074      private boolean requireCachedCredentials;
075    
076      // Indicates whether to allow the client to use credentials that are outside
077      // of the current subject.
078      private boolean useSubjectCredentialsOnly;
079    
080      // Indicates whether to enable the use of a ticket cache.
081      private boolean useTicketCache;
082    
083      // The SASL quality of protection value(s) allowed for the DIGEST-MD5 bind
084      // request.
085      private List<SASLQualityOfProtection> allowedQoP;
086    
087      // The names of any system properties that should not be altered by GSSAPI
088      // processing.
089      private Set<String> suppressedSystemProperties;
090    
091      // The authentication ID string for the GSSAPI bind request.
092      private String authenticationID;
093    
094      // The authorization ID string for the GSSAPI bind request, if available.
095      private String authorizationID;
096    
097      // The path to the JAAS configuration file to use for bind processing.
098      private String configFilePath;
099    
100      // The name that will be used to identify this client in the JAAS framework.
101      private String jaasClientName;
102    
103      // The KDC address for the GSSAPI bind request, if available.
104      private String kdcAddress;
105    
106      // The realm for the GSSAPI bind request, if available.
107      private String realm;
108    
109      // The server name to use when creating the SASL client.
110      private String saslClientServerName;
111    
112      // The protocol that should be used in the Kerberos service principal for
113      // the server system.
114      private String servicePrincipalProtocol;
115    
116      // The path to the Kerberos ticket cache to use.
117      private String ticketCachePath;
118    
119    
120    
121      /**
122       * Creates a new set of GSSAPI bind request properties with the provided
123       * information.
124       *
125       * @param  authenticationID  The authentication ID for the GSSAPI bind
126       *                           request.  It may be {@code null} if an existing
127       *                           Kerberos session should be used.
128       * @param  password          The password for the GSSAPI bind request.  It may
129       *                           be {@code null} if an existing Kerberos session
130       *                           should be used.
131       */
132      public GSSAPIBindRequestProperties(final String authenticationID,
133                                         final String password)
134      {
135        this(authenticationID, null,
136             (password == null ? null : new ASN1OctetString(password)), null, null,
137             null);
138      }
139    
140    
141    
142      /**
143       * Creates a new set of GSSAPI bind request properties with the provided
144       * information.
145       *
146       * @param  authenticationID  The authentication ID for the GSSAPI bind
147       *                           request.  It may be {@code null} if an existing
148       *                           Kerberos session should be used.
149       * @param  password          The password for the GSSAPI bind request.  It may
150       *                           be {@code null} if an existing Kerberos session
151       *                           should be used.
152       */
153      public GSSAPIBindRequestProperties(final String authenticationID,
154                                         final byte[] password)
155      {
156        this(authenticationID, null,
157             (password == null ? null : new ASN1OctetString(password)), null, null,
158             null);
159      }
160    
161    
162    
163      /**
164       * Creates a new set of GSSAPI bind request properties with the provided
165       * information.
166       *
167       * @param  authenticationID  The authentication ID for the GSSAPI bind
168       *                           request.  It may be {@code null} if an existing
169       *                           Kerberos session should be used.
170       * @param  authorizationID   The authorization ID for the GSSAPI bind request.
171       *                           It may be {@code null} if the authorization ID
172       *                           should be the same as the authentication ID.
173       * @param  password          The password for the GSSAPI bind request.  It may
174       *                           be {@code null} if an existing Kerberos session
175       *                           should be used.
176       * @param  realm             The realm to use for the authentication.  It may
177       *                           be {@code null} to attempt to use the default
178       *                           realm from the system configuration.
179       * @param  kdcAddress        The address of the Kerberos key distribution
180       *                           center.  It may be {@code null} to attempt to use
181       *                           the default KDC from the system configuration.
182       * @param  configFilePath    The path to the JAAS configuration file to use
183       *                           for the authentication processing.  It may be
184       *                           {@code null} to use the default JAAS
185       *                           configuration.
186       */
187      GSSAPIBindRequestProperties(final String authenticationID,
188                                  final String authorizationID,
189                                  final ASN1OctetString password,
190                                  final String realm,
191                                  final String kdcAddress,
192                                  final String configFilePath)
193      {
194        this.authenticationID = authenticationID;
195        this.authorizationID  = authorizationID;
196        this.password         = password;
197        this.realm            = realm;
198        this.kdcAddress       = kdcAddress;
199        this.configFilePath   = configFilePath;
200    
201        servicePrincipalProtocol   = "ldap";
202        enableGSSAPIDebugging      = false;
203        jaasClientName             = "GSSAPIBindRequest";
204        renewTGT                   = false;
205        useSubjectCredentialsOnly  = true;
206        useTicketCache             = true;
207        requireCachedCredentials   = false;
208        saslClientServerName       = null;
209        ticketCachePath            = null;
210        suppressedSystemProperties = Collections.emptySet();
211        allowedQoP                 = Collections.unmodifiableList(Arrays.asList(
212             SASLQualityOfProtection.AUTH));
213      }
214    
215    
216    
217      /**
218       * Retrieves the authentication ID for the GSSAPI bind request, if defined.
219       *
220       * @return  The authentication ID for the GSSAPI bind request, or {@code null}
221       *          if an existing Kerberos session should be used.
222       */
223      public String getAuthenticationID()
224      {
225        return authenticationID;
226      }
227    
228    
229    
230      /**
231       * Sets the authentication ID for the GSSAPI bind request.
232       *
233       * @param  authenticationID  The authentication ID for the GSSAPI bind
234       *                           request.  It may be {@code null} if an existing
235       *                           Kerberos session should be used.
236       */
237      public void setAuthenticationID(final String authenticationID)
238      {
239        this.authenticationID = authenticationID;
240      }
241    
242    
243    
244      /**
245       * Retrieves the authorization ID for the GSSAPI bind request, if defined.
246       *
247       * @return  The authorizationID for the GSSAPI bind request, or {@code null}
248       *          if the authorization ID should be the same as the authentication
249       *          ID.
250       */
251      public String getAuthorizationID()
252      {
253        return authorizationID;
254      }
255    
256    
257    
258      /**
259       * Specifies the authorization ID for the GSSAPI bind request.
260       *
261       * @param  authorizationID  The authorization ID for the GSSAPI bind request.
262       *                          It may be {@code null} if the authorization ID
263       *                          should be the same as the authentication ID.
264       */
265      public void setAuthorizationID(final String authorizationID)
266      {
267        this.authorizationID = authorizationID;
268      }
269    
270    
271    
272      /**
273       * Retrieves the password that should be used for the GSSAPI bind request, if
274       * defined.
275       *
276       * @return  The password that should be used for the GSSAPI bind request, or
277       *          {@code null} if an existing Kerberos session should be used.
278       */
279      public ASN1OctetString getPassword()
280      {
281        return password;
282      }
283    
284    
285    
286      /**
287       * Specifies the password that should be used for the GSSAPI bind request.
288       *
289       * @param  password  The password that should be used for the GSSAPI bind
290       *                   request.  It may be {@code null} if an existing
291       *                   Kerberos session should be used.
292       */
293      public void setPassword(final String password)
294      {
295        if (password == null)
296        {
297          this.password = null;
298        }
299        else
300        {
301          this.password = new ASN1OctetString(password);
302        }
303      }
304    
305    
306    
307      /**
308       * Specifies the password that should be used for the GSSAPI bind request.
309       *
310       * @param  password  The password that should be used for the GSSAPI bind
311       *                   request.  It may be {@code null} if an existing
312       *                   Kerberos session should be used.
313       */
314      public void setPassword(final byte[] password)
315      {
316        if (password == null)
317        {
318          this.password = null;
319        }
320        else
321        {
322          this.password = new ASN1OctetString(password);
323        }
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(final ASN1OctetString password)
336      {
337        this.password = password;
338      }
339    
340    
341    
342      /**
343       * Retrieves the realm to use for the GSSAPI bind request, if defined.
344       *
345       * @return  The realm to use for the GSSAPI bind request, or {@code null} if
346       *          the request should attempt to use the default realm from the
347       *          system configuration.
348       */
349      public String getRealm()
350      {
351        return realm;
352      }
353    
354    
355    
356      /**
357       * Specifies the realm to use for the GSSAPI bind request.
358       *
359       * @param  realm  The realm to use for the GSSAPI bind request.  It may be
360       *                {@code null} if the request should attempt to use the
361       *                default realm from the system configuration.
362       */
363      public void setRealm(final String realm)
364      {
365        this.realm = realm;
366      }
367    
368    
369    
370      /**
371       * Retrieves the list of allowed qualities of protection that may be used for
372       * communication that occurs on the connection after the authentication has
373       * completed, in order from most preferred to least preferred.
374       *
375       * @return  The list of allowed qualities of protection that may be used for
376       *          communication that occurs on the connection after the
377       *          authentication has completed, in order from most preferred to
378       *          least preferred.
379       */
380      public List<SASLQualityOfProtection> getAllowedQoP()
381      {
382        return allowedQoP;
383      }
384    
385    
386    
387      /**
388       * Specifies the list of allowed qualities of protection that may be used for
389       * communication that occurs on the connection after the authentication has
390       * completed, in order from most preferred to least preferred.
391       *
392       * @param  allowedQoP  The list of allowed qualities of protection that may be
393       *                     used for communication that occurs on the connection
394       *                     after the authentication has completed, in order from
395       *                     most preferred to least preferred.  If this is
396       *                     {@code null} or empty, then a list containing only the
397       *                     {@link SASLQualityOfProtection#AUTH} quality of
398       *                     protection value will be used.
399       */
400      public void setAllowedQoP(final List<SASLQualityOfProtection> allowedQoP)
401      {
402        if ((allowedQoP == null) || allowedQoP.isEmpty())
403        {
404          this.allowedQoP = Collections.unmodifiableList(Arrays.asList(
405               SASLQualityOfProtection.AUTH));
406        }
407        else
408        {
409          this.allowedQoP = Collections.unmodifiableList(
410               new ArrayList<SASLQualityOfProtection>(allowedQoP));
411        }
412      }
413    
414    
415    
416      /**
417       * Specifies the list of allowed qualities of protection that may be used for
418       * communication that occurs on the connection after the authentication has
419       * completed, in order from most preferred to least preferred.
420       *
421       * @param  allowedQoP  The list of allowed qualities of protection that may be
422       *                     used for communication that occurs on the connection
423       *                     after the authentication has completed, in order from
424       *                     most preferred to least preferred.  If this is
425       *                     {@code null} or empty, then a list containing only the
426       *                     {@link SASLQualityOfProtection#AUTH} quality of
427       *                     protection value will be used.
428       */
429      public void setAllowedQoP(final SASLQualityOfProtection... allowedQoP)
430      {
431        setAllowedQoP(StaticUtils.toList(allowedQoP));
432      }
433    
434    
435    
436      /**
437       * Retrieves the address to use for the Kerberos key distribution center,
438       * if defined.
439       *
440       * @return  The address to use for the Kerberos key distribution center, or
441       *          {@code null} if request should attempt to determine the KDC
442       *          address from the system configuration.
443       */
444      public String getKDCAddress()
445      {
446        return kdcAddress;
447      }
448    
449    
450    
451      /**
452       * Specifies the address to use for the Kerberos key distribution center.
453       *
454       * @param  kdcAddress  The address to use for the Kerberos key distribution
455       *                     center.  It may be {@code null} if the request should
456       *                     attempt to determine the KDC address from the system
457       *                     configuration.
458       */
459      public void setKDCAddress(final String kdcAddress)
460      {
461        this.kdcAddress = kdcAddress;
462      }
463    
464    
465    
466      /**
467       * Retrieves the name that will be used to identify this client in the JAAS
468       * framework.
469       *
470       * @return  The name that will be used to identify this client in the JAAS
471       *          framework.
472       */
473      public String getJAASClientName()
474      {
475        return jaasClientName;
476      }
477    
478    
479    
480      /**
481       * Specifies the name that will be used to identify this client in the JAAS
482       * framework.
483       *
484       * @param  jaasClientName  The name that will be used to identify this client
485       *                         in the JAAS framework.  It must not be
486       *                         {@code null} or empty.
487       */
488      public void setJAASClientName(final String jaasClientName)
489      {
490        Validator.ensureNotNull(jaasClientName);
491    
492        this.jaasClientName = jaasClientName;
493      }
494    
495    
496    
497      /**
498       * Retrieves the path to a JAAS configuration file that should be used when
499       * processing the GSSAPI bind request, if defined.
500       *
501       * @return  The path to a JAAS configuration file that should be used when
502       *          processing the GSSAPI bind request, or {@code null} if a JAAS
503       *          configuration file should be automatically constructed for the
504       *          bind request.
505       */
506      public String getConfigFilePath()
507      {
508        return configFilePath;
509      }
510    
511    
512    
513      /**
514       * Specifies the path to a JAAS configuration file that should be used when
515       * processing the GSSAPI bind request.
516       *
517       * @param  configFilePath  The path to a JAAS configuration file that should
518       *                         be used when processing the GSSAPI bind request.
519       *                         It may be {@code null} if a configuration file
520       *                         should be automatically constructed for the bind
521       *                         request.
522       */
523      public void setConfigFilePath(final String configFilePath)
524      {
525        this.configFilePath = configFilePath;
526      }
527    
528    
529    
530      /**
531       * Retrieves the server name that should be used when creating the Java
532       * {@code SaslClient}, if one is defined.
533       *
534       * @return  The server name that should be used when creating the Java
535       *          {@code SaslClient}, or {@code null} if none is defined and the
536       *          {@code SaslClient} should use the address specified when
537       *          establishing the connection.
538       */
539      public String getSASLClientServerName()
540      {
541        return saslClientServerName;
542      }
543    
544    
545    
546      /**
547       * Specifies the server name that should be used when creating the Java
548       * {@code SaslClient}.
549       *
550       * @param  saslClientServerName  The server name that should be used when
551       *                               creating the Java {@code SaslClient}.  It may
552       *                               be {@code null} to indicate that the
553       *                               {@code SaslClient} should be created with the
554       *
555       */
556      public void setSASLClientServerName(final String saslClientServerName)
557      {
558        this.saslClientServerName = saslClientServerName;
559      }
560    
561    
562    
563      /**
564       * Retrieves the protocol specified in the service principal that the
565       * directory server uses for its communication with the KDC.  The service
566       * principal is usually something like "ldap/directory.example.com", where
567       * "ldap" is the protocol and "directory.example.com" is the fully-qualified
568       * address of the directory server system, but some servers may allow
569       * authentication with a service principal with a protocol other than "ldap".
570       *
571       * @return  The protocol specified in the service principal that the directory
572       *          server uses for its communication with the KDC.
573       */
574      public String getServicePrincipalProtocol()
575      {
576        return servicePrincipalProtocol;
577      }
578    
579    
580    
581      /**
582       * Specifies the protocol specified in the service principal that the
583       * directory server uses for its communication with the KDC.  This should
584       * generally be "ldap", but some servers may allow a service principal with a
585       * protocol other than "ldap".
586       *
587       * @param  servicePrincipalProtocol  The protocol specified in the service
588       *                                   principal that the directory server uses
589       *                                   for its communication with the KDC.
590       */
591      public void setServicePrincipalProtocol(final String servicePrincipalProtocol)
592      {
593        Validator.ensureNotNull(servicePrincipalProtocol);
594    
595        this.servicePrincipalProtocol = servicePrincipalProtocol;
596      }
597    
598    
599    
600      /**
601       * Indicates whether to allow the client to use credentials that are outside
602       * of the current subject, obtained via some system-specific mechanism.
603       *
604       * @return  {@code true} if the client will only be allowed to use credentials
605       *          that are within the current subject, or {@code false} if the
606       *          client will be allowed to use credentials outside the current
607       *          subject.
608       */
609      public boolean useSubjectCredentialsOnly()
610      {
611        return useSubjectCredentialsOnly;
612      }
613    
614    
615    
616      /**
617       * Specifies whether to allow the client to use credentials that are outside
618       * the current subject.  If this is {@code false}, then a system-specific
619       * mechanism may be used in an attempt to obtain credentials from an
620       * existing session.
621       *
622       * @param  useSubjectCredentialsOnly  Indicates whether to allow the client to
623       *                                    use credentials that are outside of the
624       *                                    current subject.
625       */
626      public void setUseSubjectCredentialsOnly(
627                       final boolean useSubjectCredentialsOnly)
628      {
629        this.useSubjectCredentialsOnly = useSubjectCredentialsOnly;
630      }
631    
632    
633    
634      /**
635       * Indicates whether to enable the use of a ticket cache to to avoid the need
636       * to supply credentials if the client already has an existing Kerberos
637       * session.
638       *
639       * @return  {@code true} if a ticket cache may be used to take advantage of an
640       *          existing Kerberos session, or {@code false} if Kerberos
641       *          credentials should always be provided.
642       */
643      public boolean useTicketCache()
644      {
645        return useTicketCache;
646      }
647    
648    
649    
650      /**
651       * Specifies whether to enable the use of a ticket cache to to avoid the need
652       * to supply credentials if the client already has an existing Kerberos
653       * session.
654       *
655       * @param  useTicketCache  Indicates whether to enable the use of a ticket
656       *                         cache to to avoid the need to supply credentials if
657       *                         the client already has an existing Kerberos
658       *                         session.
659       */
660      public void setUseTicketCache(final boolean useTicketCache)
661      {
662        this.useTicketCache = useTicketCache;
663      }
664    
665    
666    
667      /**
668       * Indicates whether GSSAPI authentication should only occur using an existing
669       * Kerberos session.
670       *
671       * @return  {@code true} if GSSAPI authentication should only use an existing
672       *          Kerberos session and should fail if the client does not have an
673       *          existing session, or {@code false} if the client will be allowed
674       *          to create a new session if one does not already exist.
675       */
676      public boolean requireCachedCredentials()
677      {
678        return requireCachedCredentials;
679      }
680    
681    
682    
683      /**
684       * Specifies whether an GSSAPI authentication should only occur using an
685       * existing Kerberos session.
686       *
687       * @param  requireCachedCredentials  Indicates whether an existing Kerberos
688       *                                   session will be required for
689       *                                   authentication.  If {@code true}, then
690       *                                   authentication will fail if the client
691       *                                   does not already have an existing
692       *                                   Kerberos session.  This will be ignored
693       *                                   if {@code useTicketCache} is false.
694       */
695      public void setRequireCachedCredentials(
696                       final boolean requireCachedCredentials)
697      {
698        this.requireCachedCredentials = requireCachedCredentials;
699      }
700    
701    
702    
703      /**
704       * Retrieves the path to the Kerberos ticket cache file that should be used
705       * during authentication, if defined.
706       *
707       * @return  The path to the Kerberos ticket cache file that should be used
708       *          during authentication, or {@code null} if the default ticket cache
709       *          file should be used.
710       */
711      public String getTicketCachePath()
712      {
713        return ticketCachePath;
714      }
715    
716    
717    
718      /**
719       * Specifies the path to the Kerberos ticket cache file that should be used
720       * during authentication.
721       *
722       * @param  ticketCachePath  The path to the Kerberos ticket cache file that
723       *                          should be used during authentication.  It may be
724       *                          {@code null} if the default ticket cache file
725       *                          should be used.
726       */
727      public void setTicketCachePath(final String ticketCachePath)
728      {
729        this.ticketCachePath = ticketCachePath;
730      }
731    
732    
733    
734      /**
735       * Indicates whether to attempt to renew the client's ticket-granting ticket
736       * (TGT) if an existing Kerberos session is used to authenticate.
737       *
738       * @return  {@code true} if the client should attempt to renew its
739       *          ticket-granting ticket if the authentication is processed using an
740       *          existing Kerberos session, or {@code false} if not.
741       */
742      public boolean renewTGT()
743      {
744        return renewTGT;
745      }
746    
747    
748    
749      /**
750       * Specifies whether to attempt to renew the client's ticket-granting ticket
751       * (TGT) if an existing Kerberos session is used to authenticate.
752       *
753       * @param  renewTGT  Indicates whether to attempt to renew the client's
754       *                   ticket-granting ticket if an existing Kerberos session is
755       *                   used to authenticate.
756       */
757      public void setRenewTGT(final boolean renewTGT)
758      {
759        this.renewTGT = renewTGT;
760      }
761    
762    
763    
764      /**
765       * Retrieves a set of system properties that will not be altered by GSSAPI
766       * processing.
767       *
768       * @return  A set of system properties that will not be altered by GSSAPI
769       *          processing.
770       */
771      public Set<String> getSuppressedSystemProperties()
772      {
773        return suppressedSystemProperties;
774      }
775    
776    
777    
778      /**
779       * Specifies a set of system properties that will not be altered by GSSAPI
780       * processing.  This should generally only be used in cases in which the
781       * specified system properties are known to already be set correctly for the
782       * desired authentication processing.
783       *
784       * @param  suppressedSystemProperties  A set of system properties that will
785       *                                     not be altered by GSSAPI processing.
786       *                                     It may be {@code null} or empty to
787       *                                     indicate that no properties should be
788       *                                     suppressed.
789       */
790      public void setSuppressedSystemProperties(
791                       final Collection<String> suppressedSystemProperties)
792      {
793        if (suppressedSystemProperties == null)
794        {
795          this.suppressedSystemProperties = Collections.emptySet();
796        }
797        else
798        {
799          this.suppressedSystemProperties = Collections.unmodifiableSet(
800               new LinkedHashSet<String>(suppressedSystemProperties));
801        }
802      }
803    
804    
805    
806      /**
807       * Indicates whether JVM-level debugging should be enabled for GSSAPI bind
808       * processing.  If this is enabled, then debug information may be written to
809       * standard error when performing GSSAPI processing that could be useful for
810       * debugging authentication problems.
811       *
812       * @return  {@code true} if JVM-level debugging should be enabled for GSSAPI
813       *          bind processing, or {@code false} if not.
814       */
815      public boolean enableGSSAPIDebugging()
816      {
817        return enableGSSAPIDebugging;
818      }
819    
820    
821    
822      /**
823       * Specifies whether JVM-level debugging should be enabled for GSSAPI bind
824       * processing.  If this is enabled, then debug information may be written to
825       * standard error when performing GSSAPI processing that could be useful for
826       * debugging authentication problems.
827       *
828       * @param  enableGSSAPIDebugging  Specifies whether JVM-level debugging should
829       *                                be enabled for GSSAPI bind processing.
830       */
831      public void setEnableGSSAPIDebugging(final boolean enableGSSAPIDebugging)
832      {
833        this.enableGSSAPIDebugging = enableGSSAPIDebugging;
834      }
835    
836    
837    
838      /**
839       * Retrieves a string representation of the GSSAPI bind request properties.
840       *
841       * @return  A string representation of the GSSAPI bind request properties.
842       */
843      @Override()
844      public String toString()
845      {
846        final StringBuilder buffer = new StringBuilder();
847        toString(buffer);
848        return buffer.toString();
849      }
850    
851    
852    
853      /**
854       * Appends a string representation of the GSSAPI bind request properties to
855       * the provided buffer.
856       *
857       * @param  buffer  The buffer to which the information should be appended.
858       */
859      public void toString(final StringBuilder buffer)
860      {
861        buffer.append("GSSAPIBindRequestProperties(");
862        if (authenticationID != null)
863        {
864          buffer.append("authenticationID='");
865          buffer.append(authenticationID);
866          buffer.append("', ");
867        }
868    
869        if (authorizationID != null)
870        {
871          buffer.append("authorizationID='");
872          buffer.append(authorizationID);
873          buffer.append("', ");
874        }
875    
876        if (realm != null)
877        {
878          buffer.append("realm='");
879          buffer.append(realm);
880          buffer.append("', ");
881        }
882    
883        buffer.append("qop='");
884        buffer.append(SASLQualityOfProtection.toString(allowedQoP));
885        buffer.append("', ");
886    
887        if (kdcAddress != null)
888        {
889          buffer.append("kdcAddress='");
890          buffer.append(kdcAddress);
891          buffer.append("', ");
892        }
893    
894        buffer.append("useSubjectCredentialsOnly=");
895        buffer.append(useSubjectCredentialsOnly);
896        buffer.append(", ");
897    
898        if (useTicketCache)
899        {
900          buffer.append("useTicketCache=true, requireCachedCredentials=");
901          buffer.append(requireCachedCredentials);
902          buffer.append(", renewTGT=");
903          buffer.append(renewTGT);
904          buffer.append(", ");
905    
906          if (ticketCachePath != null)
907          {
908            buffer.append("ticketCachePath='");
909            buffer.append(ticketCachePath);
910            buffer.append("', ");
911          }
912        }
913        else
914        {
915          buffer.append("useTicketCache=false, ");
916        }
917    
918        buffer.append("jaasClientName='");
919        buffer.append(jaasClientName);
920        buffer.append("', ");
921    
922        if (configFilePath != null)
923        {
924          buffer.append("configFilePath='");
925          buffer.append(configFilePath);
926          buffer.append("', ");
927        }
928    
929        if (saslClientServerName != null)
930        {
931          buffer.append("saslClientServerName='");
932          buffer.append(saslClientServerName);
933          buffer.append("', ");
934        }
935    
936        buffer.append("servicePrincipalProtocol='");
937        buffer.append(servicePrincipalProtocol);
938        buffer.append("', suppressedSystemProperties={");
939    
940        final Iterator<String> propIterator = suppressedSystemProperties.iterator();
941        while (propIterator.hasNext())
942        {
943          buffer.append('\'');
944          buffer.append(propIterator.next());
945          buffer.append('\'');
946    
947          if (propIterator.hasNext())
948          {
949            buffer.append(", ");
950          }
951        }
952    
953        buffer.append("}, enableGSSAPIDebugging=");
954        buffer.append(enableGSSAPIDebugging);
955        buffer.append(')');
956      }
957    }