modify the database will return an "unwilling to perform" error. By
default, readonly is off.
.HP
-.B replica host=<hostname>[:port] "binddn=<DN>" bindmethod=simple |\
- kerberos [credentials=<password>] [srvtab=<filename> ]
+.B replica host=<hostname>[:port] bindmethod=simple|sasl
+.B [binddn=<simple DN>] [credentials=<simple password>]
+.B [saslmech=<SASL mech>] [authcId=<authentication ID>]
.RS
-Specify a replication site for this database. Refer to "The SLAPD and
-SLURPD Administrator's Guide" for detailed information on setting up
-a replicated
+Specify a replication site for this database. Refer to "The OpenLDAP
+Administrator's Guide" for detailed information on setting up a replicated
.B slapd
-directory service.
+directory service. A
+.B bindmethod
+of
+.B simple
+requires the options
+.B binddn
+and
+.B credentials
+and should only be used when adequate security services
+(e.g TLS or IPSEC) are in place. A
+.B bindmethod
+of
+.B sasl
+requires the option
+.B saslmech.
+If the
+.B mechanism
+will use Kerberos, a kerberos instance should be given in
+.B authcId.
.RE
.TP
.B replogfile <filename>
#define GOT_DN 2
#define GOT_METHOD 4
#define GOT_ALL ( GOT_HOST | GOT_DN | GOT_METHOD )
+#define GOT_MECH 8
+
static int
parse_replica_line(
char **cargv,
} else if ( !strcasecmp( val, SIMPLESTR )) {
ri->ri_bind_method = AUTH_SIMPLE;
gots |= GOT_METHOD;
+ } else if ( !strcasecmp( val, SASLSTR )) {
+ ri->ri_bind_method = AUTH_SASL;
+ gots |= GOT_METHOD;
} else {
ri->ri_bind_method = -1;
}
+ } else if ( !strncasecmp( cargv[ i ], SASLMECHSTR, strlen( SASLMECHSTR ))) {
+ val = cargv[ i ] + strlen( SASLMECHSTR ) + 1;
+ gots |= GOT_MECH;
+ ri->ri_saslmech = strdup( val );
} else if ( !strncasecmp( cargv[ i ], CREDSTR, strlen( CREDSTR ))) {
val = cargv[ i ] + strlen( CREDSTR ) + 1;
ri->ri_password = strdup( val );
- } else if ( !strncasecmp( cargv[ i ], BINDPSTR, strlen( BINDPSTR ))) {
- val = cargv[ i ] + strlen( BINDPSTR ) + 1;
- ri->ri_principal = strdup( val );
+ } else if ( !strncasecmp( cargv[ i ], AUTHCSTR, strlen( AUTHCSTR ))) {
+ val = cargv[ i ] + strlen( AUTHCSTR ) + 1;
+ ri->ri_authcId = strdup( val );
+ } else if ( !strncasecmp( cargv[ i ], OLDAUTHCSTR, strlen( OLDAUTHCSTR ))) {
+ /* Old authcID is provided for some backwards compatibility */
+ val = cargv[ i ] + strlen( OLDAUTHCSTR ) + 1;
+ ri->ri_authcId = strdup( val );
} else if ( !strncasecmp( cargv[ i ], SRVTABSTR, strlen( SRVTABSTR ))) {
val = cargv[ i ] + strlen( SRVTABSTR ) + 1;
if ( ri->ri_srvtab != NULL ) {
cargv[ i ] );
}
}
- if ( gots != GOT_ALL ) {
- fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
- fprintf( stderr, "config file, line %d\n", lineno );
- return -1;
- }
+
+ if ( ri->ri_bind_method == AUTH_SASL) {
+ if ((gots & GOT_MECH) == 0) {
+ fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " );
+ fprintf( stderr, "slapd config file, line %d\n", lineno );
+ return -1;
+ }
+ }
+ else if ( gots != GOT_ALL ) {
+ fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
+ fprintf( stderr, "config file, line %d\n", lineno );
+ return -1;
+ }
return 0;
}
#include <ac/unistd.h>
#include <ldap.h>
-
+#include "lutil_ldap.h"
#include "slurp.h"
/* Forward references */
)
{
int ldrc;
+ void *defaults;
+
*lderr = 0;
return( BIND_ERR_SIMPLE_FAILED );
}
break;
+
+ case AUTH_SASL:
+ Debug( LDAP_DEBUG_ARGS, "bind to %s as %s via %s (SASL)\n",
+ ri->ri_hostname, ri->ri_authcId, ri->ri_saslmech );
+
+ defaults = lutil_sasl_defaults( ri->ri_ldp, ri->ri_saslmech,
+ NULL, ri->ri_authcId, NULL, NULL );
+ ldrc = ldap_sasl_interactive_bind_s( ri->ri_ldp, ri->ri_bind_dn,
+ ri->ri_saslmech, NULL, NULL,
+ LDAP_SASL_AUTOMATIC, lutil_sasl_interact, defaults );
+ if ( ldrc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "Error: LDAP SASL for %s:%d failed: %s\n",
+ ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
+ *lderr = ldrc;
+ ldap_unbind( ri->ri_ldp );
+ ri->ri_ldp = NULL;
+ return( BIND_ERR_SASL_FAILED );
+ }
+ break;
default:
Debug( LDAP_DEBUG_ANY,
"Error: do_bind: unknown auth type \"%d\" for %s:%d\n",
(*ri)->ri_bind_method = 0;
(*ri)->ri_bind_dn = NULL;
(*ri)->ri_password = NULL;
- (*ri)->ri_principal = NULL;
+ (*ri)->ri_authcId = NULL;
(*ri)->ri_srvtab = NULL;
(*ri)->ri_curr = NULL;
/* Maximum line length we can read from replication log */
#define REPLBUFLEN 256
-/* We support simple (plaintext password) and kerberos authentication */
+/* We support simple (plaintext password) and SASL authentication */
#define AUTH_SIMPLE 1
#define AUTH_KERBEROS 2
+#define AUTH_SASL 3
/* Rejection records are prefaced with this string */
#define ERROR_STR "ERROR"
#define BINDMETHSTR "bindmethod"
#define KERBEROSSTR "kerberos"
#define SIMPLESTR "simple"
+#define SASLSTR "sasl"
#define CREDSTR "credentials"
-#define BINDPSTR "bindprincipal"
+#define OLDAUTHCSTR "bindprincipal"
+#define AUTHCSTR "authcID"
#define SRVTABSTR "srvtab"
+#define SASLMECHSTR "saslmech"
#define REPLICA_SLEEP_TIME ( 10 )
#define BIND_ERR_VERSION 7
#define BIND_ERR_REFERRALS 8
#define BIND_ERR_MANAGEDSAIT 9
+#define BIND_ERR_SASL_FAILED 10
/* Return codes for do_ldap() */
#define DO_LDAP_OK 0
int ri_bind_method; /* AUTH_SIMPLE or AUTH_KERBEROS */
char *ri_bind_dn; /* DN to bind as when replicating */
char *ri_password; /* Password for AUTH_SIMPLE */
- char *ri_principal; /* principal for kerberos bind */
+ char *ri_authcId; /* authentication ID for any mechanism */
char *ri_srvtab; /* srvtab file for kerberos bind */
+ char *ri_saslmech; /* SASL mechanism to use */
struct re *ri_curr; /* current repl entry being processed */
struct stel *ri_stel; /* pointer to Stel for this replica */
unsigned long