[Date Prev][Date Next] [Chronological] [Thread] [Top]

Completed SASL canonicalization option patch



Here is the completed version of the patch (against 2.4.8) I initially
brought up a week or so ago. It makes the hostname canonicalization step for
SASL optional, both via ldap.conf and commandline arguments for the client
tools. I submit it for consideration into the mainline code, as I believe it
would provide a great benefit to a number of users such as myself.

I present the completed version after some of the comments on the initial
snapshot.  The majority of comments were, frankly, what I had expected -
"fix the DNS, that's the real problem."  I argue that such an approach is
somewhat narrow. While undoubtedly a best practice, it is not always
feasible. I'll share my thoughts and comments on some of the previous
responses. I hope to get some good feedback and reconsideration of the
knee-jerk reactions.

SASL authentication is not strictly dependent on hostname canonicalization
in any form. There are, however, certain common implementation schemes that
do require a canonical hostname determination in order to function properly.
This unfortunately seems to have led to an implicit edict that all DNS
configurations must be perfectly compliant in order for OpenLDAP to be able
to use SASL authentication. The emphasis is always to 'fix your DNS, then
we'll talk', rather than relaxing the overly strict requirement of the
canonicalization step - overly strict because it is *not* required from SASL
itself, only from OpenLDAP's usage of SASL.

There exist broken DNS setups for which a user/admin may not be in a
position to remedy the errors. Sorry Howard, saying "just use static
/etc/hosts files" or "run your own local authoritative DNS server" are not
very viable options. On my home server I have a dynamic IP. When I get a new
IP, the machine updates its own /etc/hosts file, and while it would be
possible to push the value to others, there are synchronization issues, not
the least of which is that the other machines are more than likely not
powered on when the update occurs. Running my own DNS server works great
when within that netwok, but what about the cases where I'm at
work/school/friend/in-laws/wherever and would like to connect? Or when I
give access to external users? They certainly aren't going to be using my
DNS server as a first line source. Anyway, why should I need any of that
additional overhead when alternative, perfectly viable solutions exist.

What benefit does the hostname canonicalization procedure provide? In a
nutshell, it is simply a method of determining the identity of the entity
with whom I'm communicating. When done using DNS it certainly has known
security issues, but aside from direct attacks is generally quite reliable
if properly configured. I believe that this is why it's not atypical to say
"fix your DNS" if something isn't working properly. But why must this be the
only option? There are at least two other cases to consider: 1) there are
cases where we may not really care one iota about server authentication, and
2) there are options other than DNS for providing, at the very least, the
same level of confidence in the identity of the peer.

As for the first case, it's not one I'm involved in nor all too familiar
with, but it certainly doesn't stretch the imagination to think of a case
where the data returned is self-validating or requires no validation.

With regard to the second case, alternative host identification, I'm
currently using TLS for this, requiring a minimal level of validation. Yes,
you can shoot yourself in the foot on this too (no self-signed certs,
minimally a cert signed by a self-signed "CA"), but it certainly provides an
option where there otherwise might not be one (as in my case).

RFC 4752 (SASL GSSAPI), Section 5 states:
    "When constructing the input_name_string, the client SHOULD NOT
     canonicalize the server's fully qualified domain name using an
     insecure or untrusted directory service."

I mentioned a similar quote from a less SASL-specific (more
Kerberos-specific) RFC before. The emphasis of this statement is to not use
improper directory services to perform canonicalization. However, this does
*not* imply that canonicalization must be performed, rather it states that
*if* the client decides to use it, then a trusted naming service should be
used to perform it. RFC 4422 (SASL) makes this explicit and confirms that
the canonicalization is at most optional for a client, directly stating that
"there is no requirement that the authorization identity string be
canonical" (Section 5).

Having said all of that, it is also noteworthy to note that canonicalization
will often be enforced server-side simply based on the authentication
configuration. In the specific case of using Kerberos, if the service
principal uses the canonical hostname, the client better be getting a ticket
using the canonical hostname as well.

As a wrap-up, DNS has issues - some technical and some non-technical. I'm
not in anyway suggesting that a proper setup should not be pursued, if such
an option is available. But the fact of the matter is that it is not always
possible. In such situations, the OpenLDAP software should not overtly
preclude the user from using it (or indirectly require large workarounds) to
the greatest extent in any situation, even if the configuration of a certain
system is not idyllic.

A few (or more) thoughts for consideration - Thanks,
Joel Johnson
Provide a runtime configuration directive to allow selection of hostname
canonicalization for SASL connections.

Author: Joel Johnson <mrjoel@lixil.net>
Version: 1.0

This patch file is derived from OpenLDAP Software. All of the modifications to
OpenLDAP Software represented in the following patch(es) were developed by
the above named author.

The attached modifications to OpenLDAP Software are subject to the following notice:

Copyright 2008, Joel Johnson
Redistribution and use in source and binary forms, with or without modification,
are permitted only as authorized by the OpenLDAP Public License.


diff -ru ./clients/tools/common.c ../openldap-2.4.8.new/clients/tools/common.c
--- ./clients/tools/common.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/common.c	2008-03-08 04:48:43.000000000 +0000
@@ -88,6 +88,7 @@
 char		*sasl_authz_id = NULL;
 char		*sasl_mech = NULL;
 char		*sasl_secprops = NULL;
+int		sasl_canonicalize = 1;
 #endif
 
 /* controls */
@@ -275,6 +276,7 @@
 N_("  -h host    LDAP server\n"),
 N_("  -H URI     LDAP Uniform Resource Identifier(s)\n"),
 N_("  -I         use SASL Interactive mode\n"),
+N_("  -j         don't use reverse DNS for canonicalization\n"),
 N_("  -M         enable Manage DSA IT control (-MM to make critical)\n"),
 N_("  -n         show what would be done but don't actually do it\n"),
 N_("  -O props   SASL security properties\n"),
@@ -678,6 +680,10 @@
 				prog );
 			exit( EXIT_FAILURE );
 #endif
+		case 'j':
+			/* Disable using reverse DNS for hostname canonicalizaion */
+			sasl_canonicalize = 0;
+			break;
 		case 'M':
 			/* enable Manage DSA IT */
 			manageDSAit++;
@@ -1326,6 +1332,17 @@
 			}
 		}
 
+		if (!sasl_canonicalize) {
+			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_CANONICALIZE,
+				LDAP_OPT_OFF );
+		
+			if (rc != LDAP_OPT_SUCCESS) {
+				fprintf( stderr, "Could not set LDAP_OPT_X_SASL_CANONICALIZE %s\n",
+					sasl_canonicalize ? "on" : "off" );
+				exit( EXIT_FAILURE );
+			}
+		}
+
 		defaults = lutil_sasl_defaults( ld,
 			sasl_mech,
 			sasl_realm,
diff -ru ./clients/tools/common.h ../openldap-2.4.8.new/clients/tools/common.h
--- ./clients/tools/common.h	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/common.h	2008-03-07 02:50:17.000000000 +0000
@@ -78,6 +78,7 @@
 extern char		*sasl_authz_id;
 extern char		*sasl_mech;
 extern char		*sasl_secprops;
+extern int		sasl_canonicalize;
 #endif
 
 /* controls */
diff -ru ./clients/tools/ldapcompare.c ../openldap-2.4.8.new/clients/tools/ldapcompare.c
--- ./clients/tools/ldapcompare.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapcompare.c	2008-03-07 05:11:18.000000000 +0000
@@ -102,7 +102,7 @@
 
 
 const char options[] = "z"
-	"Cd:D:e:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
+	"Cd:D:e:h:H:IjMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
 
 #ifdef LDAP_CONTROL_DONTUSECOPY
 int dontUseCopy = 0;
diff -ru ./clients/tools/ldapdelete.c ../openldap-2.4.8.new/clients/tools/ldapdelete.c
--- ./clients/tools/ldapdelete.c	2008-02-12 00:32:01.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapdelete.c	2008-03-07 05:11:45.000000000 +0000
@@ -78,7 +78,7 @@
 
 
 const char options[] = "r"
-	"cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:z:Z";
+	"cd:D:e:f:h:H:IjMnO:o:p:P:QR:U:vVw:WxX:y:Y:z:Z";
 
 int
 handle_private_option( int i )
diff -ru ./clients/tools/ldapexop.c ../openldap-2.4.8.new/clients/tools/ldapexop.c
--- ./clients/tools/ldapexop.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapexop.c	2008-03-07 05:11:58.000000000 +0000
@@ -49,7 +49,7 @@
 
 
 const char options[] = ""
-	"d:D:e:h:H:InO:o:p:QR:U:vVw:WxX:y:Y:Z";
+	"d:D:e:h:H:IjnO:o:p:QR:U:vVw:WxX:y:Y:Z";
 
 int
 handle_private_option( int i )
diff -ru ./clients/tools/ldapmodify.c ../openldap-2.4.8.new/clients/tools/ldapmodify.c
--- ./clients/tools/ldapmodify.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapmodify.c	2008-03-07 05:12:09.000000000 +0000
@@ -151,7 +151,7 @@
 
 
 const char options[] = "aE:rS:"
-	"cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
+	"cd:D:e:f:h:H:IjMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
 
 int
 handle_private_option( int i )
diff -ru ./clients/tools/ldapmodrdn.c ../openldap-2.4.8.new/clients/tools/ldapmodrdn.c
--- ./clients/tools/ldapmodrdn.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapmodrdn.c	2008-03-07 05:12:18.000000000 +0000
@@ -91,7 +91,7 @@
 
 
 const char options[] = "rs:"
-	"cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
+	"cd:D:e:f:h:H:IjMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
 
 int
 handle_private_option( int i )
diff -ru ./clients/tools/ldappasswd.c ../openldap-2.4.8.new/clients/tools/ldappasswd.c
--- ./clients/tools/ldappasswd.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldappasswd.c	2008-03-07 05:12:26.000000000 +0000
@@ -81,7 +81,7 @@
 
 
 const char options[] = "a:As:St:T:"
-	"d:D:e:h:H:InO:o:p:QR:U:vVw:WxX:y:Y:Z";
+	"d:D:e:h:H:IjnO:o:p:QR:U:vVw:WxX:y:Y:Z";
 
 int
 handle_private_option( int i )
diff -ru ./clients/tools/ldapsearch.c ../openldap-2.4.8.new/clients/tools/ldapsearch.c
--- ./clients/tools/ldapsearch.c	2008-02-12 19:59:52.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapsearch.c	2008-03-07 05:12:50.000000000 +0000
@@ -251,7 +251,7 @@
 
 
 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:"
-	"Cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
+	"Cd:D:e:f:h:H:IjMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
 
 int
 handle_private_option( int i )
diff -ru ./clients/tools/ldapwhoami.c ../openldap-2.4.8.new/clients/tools/ldapwhoami.c
--- ./clients/tools/ldapwhoami.c	2008-02-11 23:26:38.000000000 +0000
+++ ../openldap-2.4.8.new/clients/tools/ldapwhoami.c	2008-03-07 05:13:06.000000000 +0000
@@ -62,7 +62,7 @@
 
 
 const char options[] = ""
-	"d:D:e:h:H:InO:o:p:QR:U:vVw:WxX:y:Y:Z";
+	"d:D:e:h:H:IjnO:o:p:QR:U:vVw:WxX:y:Y:Z";
 
 int
 handle_private_option( int i )
diff -ru ./doc/man/man1/ldapcompare.1 ../openldap-2.4.8.new/doc/man/man1/ldapcompare.1
--- ./doc/man/man1/ldapcompare.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldapcompare.1	2008-03-07 03:29:59.000000000 +0000
@@ -39,6 +39,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -147,6 +149,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the ID
 depends on the actual SASL mechanism used.
diff -ru ./doc/man/man1/ldapdelete.1 ../openldap-2.4.8.new/doc/man/man1/ldapdelete.1
--- ./doc/man/man1/ldapdelete.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldapdelete.1	2008-03-07 03:30:22.000000000 +0000
@@ -49,6 +49,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-X \ authzid\fR]
 [\c
 .BI \-Y \ mech\fR]
@@ -155,6 +157,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the identity depends on the
 actual SASL mechanism used.
diff -ru ./doc/man/man1/ldapmodify.1 ../openldap-2.4.8.new/doc/man/man1/ldapmodify.1
--- ./doc/man/man1/ldapmodify.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldapmodify.1	2008-03-07 03:31:25.000000000 +0000
@@ -43,6 +43,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -93,6 +95,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -208,6 +212,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the ID
 depends on the actual SASL mechanism used.
diff -ru ./doc/man/man1/ldapmodrdn.1 ../openldap-2.4.8.new/doc/man/man1/ldapmodrdn.1
--- ./doc/man/man1/ldapmodrdn.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldapmodrdn.1	2008-03-07 03:31:45.000000000 +0000
@@ -43,6 +43,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -150,6 +152,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the ID
 depends on the actual SASL mechanism used.
diff -ru ./doc/man/man1/ldappasswd.1 ../openldap-2.4.8.new/doc/man/man1/ldappasswd.1
--- ./doc/man/man1/ldappasswd.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldappasswd.1	2008-03-07 03:32:07.000000000 +0000
@@ -45,6 +45,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -152,6 +154,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the ID
 depends on the actual SASL mechanism used.
diff -ru ./doc/man/man1/ldapsearch.1 ../openldap-2.4.8.new/doc/man/man1/ldapsearch.1
--- ./doc/man/man1/ldapsearch.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldapsearch.1	2008-03-07 03:29:27.000000000 +0000
@@ -71,6 +71,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -315,6 +317,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the ID
 depends on the actual SASL mechanism used.
diff -ru ./doc/man/man1/ldapwhoami.1 ../openldap-2.4.8.new/doc/man/man1/ldapwhoami.1
--- ./doc/man/man1/ldapwhoami.1	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man1/ldapwhoami.1	2008-03-07 03:32:33.000000000 +0000
@@ -35,6 +35,8 @@
 [\c
 .BR \-Q ]
 [\c
+.BR \-j ]
+[\c
 .BI \-U \ authcid\fR]
 [\c
 .BI \-R \ realm\fR]
@@ -111,6 +113,9 @@
 .B \-Q
 Enable SASL Quiet mode.  Never prompt.
 .TP
+.B \-j
+Disable SASL using reverse DNS for hostname canonicalization.
+.TP
 .BI \-U \ authcid
 Specify the authentication ID for SASL bind. The form of the ID
 depends on the actual SASL mechanism used.
diff -ru ./doc/man/man5/ldap.conf.5 ../openldap-2.4.8.new/doc/man/man5/ldap.conf.5
--- ./doc/man/man5/ldap.conf.5	2008-02-11 23:26:39.000000000 +0000
+++ ../openldap-2.4.8.new/doc/man/man5/ldap.conf.5	2008-03-08 17:38:41.000000000 +0000
@@ -211,6 +211,12 @@
 Specifies the proxy authorization identity.
 .B This is a user\-only option.
 .TP
+.B SASL_CANONICALIZE <on/true/yes/off/false/no>
+Specifies whether to use a reverse DNS lookup to determine the canonical
+name for the host.  Care should be used when disabling this option, and
+some other form of host authentication is highly recommended (e.g.,
+"security ssf=1").  The default is enabled.
+.TP
 .B SASL_SECPROPS <properties>
 Specifies Cyrus SASL security properties. The 
 .B <properties>
diff -ru ./include/ldap.h ../openldap-2.4.8.new/include/ldap.h
--- ./include/ldap.h	2008-02-11 23:26:40.000000000 +0000
+++ ../openldap-2.4.8.new/include/ldap.h	2008-03-04 01:43:07.000000000 +0000
@@ -164,6 +164,7 @@
 #define LDAP_OPT_X_SASL_SSF_MIN			0x6107
 #define LDAP_OPT_X_SASL_SSF_MAX			0x6108
 #define	LDAP_OPT_X_SASL_MAXBUFSIZE		0x6109
+#define	LDAP_OPT_X_SASL_CANONICALIZE		0x610a
 
 /* Private API Extensions -- reserved for application use */
 #define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x7000  /* Private API inclusive */
diff -ru ./libraries/libldap/cyrus.c ../openldap-2.4.8.new/libraries/libldap/cyrus.c
--- ./libraries/libldap/cyrus.c	2008-02-11 23:26:41.000000000 +0000
+++ ../openldap-2.4.8.new/libraries/libldap/cyrus.c	2008-03-08 17:28:17.000000000 +0000
@@ -638,11 +638,15 @@
 		ld->ld_defconn->lconn_sasl_authctx = NULL;
 	}
 
+	if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_SASL_CANONICALIZE) )
 	{
 		char *saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb,
 			"localhost" );
 		rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost );
 		LDAP_FREE( saslhost );
+	} else {
+		rc = ldap_int_sasl_open( ld, ld->ld_defconn,
+			ld->ld_defconn->lconn_server->lud_host );
 	}
 
 	if ( rc != LDAP_SUCCESS ) return rc;
@@ -1144,6 +1148,11 @@
 				? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authzid ) : NULL;
 		} break;
 
+		case LDAP_OPT_X_SASL_CANONICALIZE: {
+			* (int *)arg = (int) LDAP_BOOL_GET(&ld->ld_options,
+				LDAP_BOOL_SASL_CANONICALIZE);
+		} break;
+
 		case LDAP_OPT_X_SASL_SSF: {
 			int sc;
 			sasl_ssf_t	*ssf;
@@ -1196,7 +1205,7 @@
 int
 ldap_int_sasl_set_option( LDAP *ld, int option, void *arg )
 {
-	if ( ld == NULL || arg == NULL )
+	if ( ld == NULL )
 		return -1;
 
 	switch ( option ) {
@@ -1205,6 +1214,8 @@
 		return -1;
 
 	case LDAP_OPT_X_SASL_SSF_EXTERNAL: {
+		if ( arg == NULL )
+			return -1;
 		int sc;
 #if SASL_VERSION_MAJOR < 2
 		sasl_external_properties_t extprops;
@@ -1241,16 +1252,32 @@
 		} break;
 
 	case LDAP_OPT_X_SASL_SSF_MIN:
+		if ( arg == NULL )
+			return -1;
 		ld->ld_options.ldo_sasl_secprops.min_ssf = *(ber_len_t *)arg;
 		break;
 	case LDAP_OPT_X_SASL_SSF_MAX:
+		if ( arg == NULL )
+			return -1;
 		ld->ld_options.ldo_sasl_secprops.max_ssf = *(ber_len_t *)arg;
 		break;
 	case LDAP_OPT_X_SASL_MAXBUFSIZE:
+		if ( arg == NULL )
+			return -1;
 		ld->ld_options.ldo_sasl_secprops.maxbufsize = *(ber_len_t *)arg;
 		break;
 
+	case LDAP_OPT_X_SASL_CANONICALIZE:
+		if(arg == LDAP_OPT_OFF) {
+			LDAP_BOOL_CLR(&ld->ld_options, LDAP_BOOL_SASL_CANONICALIZE);
+		} else {
+			LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_SASL_CANONICALIZE);
+		}
+		break;
+
 	case LDAP_OPT_X_SASL_SECPROPS: {
+		if ( arg == NULL )
+			return -1;
 		int sc;
 		sc = ldap_pvt_sasl_secprops( (char *) arg,
 			&ld->ld_options.ldo_sasl_secprops );
diff -ru ./libraries/libldap/init.c ../openldap-2.4.8.new/libraries/libldap/init.c
--- ./libraries/libldap/init.c	2008-02-11 23:26:41.000000000 +0000
+++ ../openldap-2.4.8.new/libraries/libldap/init.c	2008-03-04 03:39:12.000000000 +0000
@@ -100,6 +100,7 @@
 	{1, ATTR_STRING,	"SASL_AUTHZID",		NULL,
 		offsetof(struct ldapoptions, ldo_def_sasl_authzid)},
 	{0, ATTR_SASL,		"SASL_SECPROPS",	NULL,	LDAP_OPT_X_SASL_SECPROPS},
+	{0, ATTR_BOOL,		"SASL_CANONICALIZE",	NULL,	LDAP_BOOL_SASL_CANONICALIZE},
 #endif
 
 #ifdef HAVE_TLS
@@ -511,6 +512,7 @@
 	gopts->ldo_def_sasl_realm = NULL;
 	gopts->ldo_def_sasl_authcid = NULL;
 	gopts->ldo_def_sasl_authzid = NULL;
+	LDAP_BOOL_SET(gopts, LDAP_BOOL_SASL_CANONICALIZE);
 
 	memset( &gopts->ldo_sasl_secprops,
 		'\0', sizeof(gopts->ldo_sasl_secprops) );
diff -ru ./libraries/libldap/ldap-int.h ../openldap-2.4.8.new/libraries/libldap/ldap-int.h
--- ./libraries/libldap/ldap-int.h	2008-02-11 23:26:41.000000000 +0000
+++ ../openldap-2.4.8.new/libraries/libldap/ldap-int.h	2008-03-04 03:09:13.000000000 +0000
@@ -121,6 +121,7 @@
 #define LDAP_BOOL_RESTART		1
 #define LDAP_BOOL_TLS			3
 #define	LDAP_BOOL_CONNECT_ASYNC		4
+#define LDAP_BOOL_SASL_CANONICALIZE	5
 
 #define LDAP_BOOLEANS	unsigned long
 #define LDAP_BOOL(n)	((LDAP_BOOLEANS)1 << (n))