diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 699b0696d7..8d92c31452 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -458,9 +458,10 @@ This option puts the database into "read-only" mode. Any attempts to modify the database will return an "unwilling to perform" error. By default, readonly is off. .HP -.B replica host=[:port] bindmethod=simple|sasl -.B [binddn=] [credentials=] -.B [saslmech=] [authcId=] +.B replica host=[:port] [tls=yes|critical] +.B bindmethod=simple|sasl [binddn=] [credentials=] +.B [saslmech=] [secopts=] [realm=] +.B [authcId=] [authcId=] .RS Specify a replication site for this database. Refer to the "OpenLDAP Administrator's Guide" for detailed information on setting up a replicated diff --git a/servers/slurpd/config.c b/servers/slurpd/config.c index e14a9e9f3c..9bde24e88f 100644 --- a/servers/slurpd/config.c +++ b/servers/slurpd/config.c @@ -345,6 +345,13 @@ parse_replica_line( } ri->ri_hostname = strdup( val ); gots |= GOT_HOST; + } else if ( !strncasecmp( cargv[ i ], TLSSTR, strlen( TLSSTR ))) { + val = cargv[ i ] + strlen( TLSSTR ) + 1; + if( !strcasecmp( val, TLSCRITICALSTR ) ) { + ri->ri_tls = TLS_CRITICAL; + } else { + ri->ri_tls = TLS_ON; + } } else if ( !strncasecmp( cargv[ i ], BINDDNSTR, strlen( BINDDNSTR ))) { val = cargv[ i ] + strlen( BINDDNSTR ) + 1; @@ -374,6 +381,12 @@ parse_replica_line( } else if ( !strncasecmp( cargv[ i ], CREDSTR, strlen( CREDSTR ))) { val = cargv[ i ] + strlen( CREDSTR ) + 1; ri->ri_password = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], SECPROPSSTR, strlen( SECPROPSSTR ))) { + val = cargv[ i ] + strlen( SECPROPSSTR ) + 1; + ri->ri_secprops = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], REALMSTR, strlen( REALMSTR ))) { + val = cargv[ i ] + strlen( REALMSTR ) + 1; + ri->ri_realm = strdup( val ); } else if ( !strncasecmp( cargv[ i ], AUTHCSTR, strlen( AUTHCSTR ))) { val = cargv[ i ] + strlen( AUTHCSTR ) + 1; ri->ri_authcId = strdup( val ); @@ -381,6 +394,9 @@ parse_replica_line( /* Old authcID is provided for some backwards compatibility */ val = cargv[ i ] + strlen( OLDAUTHCSTR ) + 1; ri->ri_authcId = strdup( val ); + } else if ( !strncasecmp( cargv[ i ], AUTHZSTR, strlen( AUTHZSTR ))) { + val = cargv[ i ] + strlen( AUTHZSTR ) + 1; + ri->ri_authzId = strdup( val ); } else if ( !strncasecmp( cargv[ i ], SRVTABSTR, strlen( SRVTABSTR ))) { val = cargv[ i ] + strlen( SRVTABSTR ) + 1; if ( ri->ri_srvtab != NULL ) { diff --git a/servers/slurpd/ldap_op.c b/servers/slurpd/ldap_op.c index 5607f6ec00..f55905ac6c 100644 --- a/servers/slurpd/ldap_op.c +++ b/servers/slurpd/ldap_op.c @@ -676,6 +676,24 @@ do_bind( } ldap_set_option(ri->ri_ldp, LDAP_OPT_RESTART, LDAP_OPT_ON); + if( ri->ri_tls ) { + int err; + err = ldap_start_tls_s(ri->ri_ldp, NULL, NULL); + + if( err != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "%s: ldap_start_tls failed: %s (%d)\n", + ri->ri_tls != TLS_CRITICAL ? "Warning" : "Error", + ldap_err2string( err ), err ); + + if( ri->ri_tls != TLS_CRITICAL ) { + ldap_unbind( ri->ri_ldp ); + ri->ri_ldp = NULL; + return BIND_ERR_TLS_FAILED; + } + } + } + switch ( ri->ri_bind_method ) { case AUTH_SIMPLE: /* @@ -701,8 +719,23 @@ do_bind( ri->ri_hostname, ri->ri_authcId, ri->ri_saslmech ); #ifdef HAVE_CYRUS_SASL + if( ri->ri_secprops != NULL ) { + int err; + err = ldap_set_option(ri->ri_ldp, LDAP_OPT_X_SASL_SECPROPS, + ri->ri_secprops); + + if( err != LDAP_OPT_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "Error: ldap_set_option(%s,SECPROPS,\"%s\") failed!\n", + ri->ri_hostname, ri->ri_secprops, NULL ); + ldap_unbind( ri->ri_ldp ); + ri->ri_ldp = NULL; + return BIND_ERR_SASL_FAILED; + } + } + defaults = lutil_sasl_defaults( ri->ri_ldp, ri->ri_saslmech, - NULL, ri->ri_authcId, NULL, NULL ); + ri->ri_realm, ri->ri_authcId, ri->ri_password, ri->ri_authzId ); ldrc = ldap_sasl_interactive_bind_s( ri->ri_ldp, ri->ri_bind_dn, ri->ri_saslmech, NULL, NULL, LDAP_SASL_QUIET, lutil_sasl_interact, defaults ); diff --git a/servers/slurpd/slurp.h b/servers/slurpd/slurp.h index 5b6b19138a..e0fe83fb64 100644 --- a/servers/slurpd/slurp.h +++ b/servers/slurpd/slurp.h @@ -66,6 +66,11 @@ /* Maximum line length we can read from replication log */ #define REPLBUFLEN 256 +/* TLS flags */ +#define TLS_OFF 0 +#define TLS_ON 1 +#define TLS_CRITICAL 2 + /* We support simple (plaintext password) and SASL authentication */ #define AUTH_SIMPLE 1 #define AUTH_KERBEROS 2 @@ -117,24 +122,30 @@ #define SASLSTR "sasl" #define CREDSTR "credentials" #define OLDAUTHCSTR "bindprincipal" -#define AUTHCSTR "authcID" +#define AUTHCSTR "authcID" +#define AUTHZSTR "authzID" #define SRVTABSTR "srvtab" #define SASLMECHSTR "saslmech" +#define REALMSTR "realm" +#define SECPROPSSTR "secprops" +#define TLSSTR "tls" +#define TLSCRITICALSTR "critical" #define REPLICA_SLEEP_TIME ( 10 ) /* Enumeration of various types of bind failures */ -#define BIND_OK 0 -#define BIND_ERR_BADLDP 1 -#define BIND_ERR_OPEN 2 -#define BIND_ERR_BAD_ATYPE 3 +#define BIND_OK 0 +#define BIND_ERR_BADLDP 1 +#define BIND_ERR_OPEN 2 +#define BIND_ERR_BAD_ATYPE 3 #define BIND_ERR_SIMPLE_FAILED 4 #define BIND_ERR_KERBEROS_FAILED 5 -#define BIND_ERR_BADRI 6 -#define BIND_ERR_VERSION 7 -#define BIND_ERR_REFERRALS 8 -#define BIND_ERR_MANAGEDSAIT 9 -#define BIND_ERR_SASL_FAILED 10 +#define BIND_ERR_BADRI 6 +#define BIND_ERR_VERSION 7 +#define BIND_ERR_REFERRALS 8 +#define BIND_ERR_MANAGEDSAIT 9 +#define BIND_ERR_SASL_FAILED 10 +#define BIND_ERR_TLS_FAILED 11 /* Return codes for do_ldap() */ #define DO_LDAP_OK 0 @@ -184,15 +195,18 @@ typedef struct rh { */ typedef struct ri Ri; struct ri { - /* Private data */ char *ri_hostname; /* canonical hostname of replica */ int ri_port; /* port where slave slapd running */ LDAP *ri_ldp; /* LDAP struct for this replica */ + int ri_tls; /* TLS: 0=no, 1=yes, 2=critical */ 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_password; /* Password for any method */ + char *ri_secprops; /* SASL security properties */ + char *ri_realm; /* realm for any mechanism */ char *ri_authcId; /* authentication ID for any mechanism */ + char *ri_authzId; /* authorization 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 */