+ /* If name is too big, just truncate. We don't care, we're
+ * using DNs, not the usernames.
+ */
+ if ( inlen > out_max )
+ inlen = out_max-1;
+
+ /* See if we need to add request, can only do it once */
+ prop_getnames( props, slap_propnames, auxvals );
+ if ( !auxvals[0].name )
+ prop_request( props, slap_propnames );
+
+ if ( flags & SASL_CU_AUTHID )
+ which = PROP_AUTHC;
+ else
+ which = PROP_AUTHZ;
+
+ /* Need to store the Connection for auxprop_lookup */
+ if ( !auxvals[PROP_CONN].values ) {
+ names[0] = slap_propnames[PROP_CONN];
+ names[1] = NULL;
+ prop_set( props, names[0], (char *)&conn, sizeof( conn ) );
+ }
+
+ /* Already been here? */
+ if ( auxvals[which].values )
+ goto done;
+
+ /* Normally we require an authzID to have a u: or dn: prefix.
+ * However, SASL frequently gives us an authzID that is just
+ * an exact copy of the authcID, without a prefix. We need to
+ * detect and allow this condition. If SASL calls canonicalize
+ * with SASL_CU_AUTHID|SASL_CU_AUTHZID this is a no-brainer.
+ * But if it's broken into two calls, we need to remember the
+ * authcID so that we can compare the authzID later. We store
+ * the authcID temporarily in conn->c_sasl_dn. We necessarily
+ * finish Canonicalizing before Authorizing, so there is no
+ * conflict with slap_sasl_authorize's use of this temp var.
+ *
+ * The SASL EXTERNAL mech is backwards from all the other mechs,
+ * it does authzID before the authcID. If we see that authzID
+ * has already been done, don't do anything special with authcID.
+ */
+ if ( flags == SASL_CU_AUTHID && !auxvals[PROP_AUTHZ].values ) {
+ conn->c_sasl_dn.bv_val = (char *) in;
+ } else if ( flags == SASL_CU_AUTHZID && conn->c_sasl_dn.bv_val ) {
+ rc = strcmp( in, conn->c_sasl_dn.bv_val );
+ conn->c_sasl_dn.bv_val = NULL;
+ /* They were equal, no work needed */
+ if ( !rc ) goto done;
+ }
+
+ rc = slap_sasl_getdn( conn, NULL, (char *)in, inlen, (char *)user_realm, &dn,
+ (flags & SASL_CU_AUTHID) ? SLAP_GETDN_AUTHCID : SLAP_GETDN_AUTHZID );