Commit 863b6a6b authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Sync with HEAD (need to update CHANGES)

parent 8a8991ed
......@@ -243,8 +243,21 @@ OL_ARG_ENABLE(sql,[ --enable-sql enable sql backend no|yes|mod],
dnl ----------------------------------------------------------------
dnl SLAPD Overlay Options
Overlays="accesslog denyop dyngroup dynlist glue lastmod ppolicy proxycache \
refint retcode rwm syncprov translucent unique"
Overlays="accesslog \
denyop \
dyngroup \
dynlist \
glue \
lastmod \
ppolicy \
proxycache \
refint \
retcode \
rwm \
syncprov \
translucent \
unique \
valsort"
AC_ARG_WITH(xxslapoverlays,[
SLAPD Overlay Options:])
......@@ -280,6 +293,8 @@ OL_ARG_ENABLE(translucent,[ --enable-translucent Translucent Proxy overlay n
${ol_dflt_overlays-no}, [no yes mod])
OL_ARG_ENABLE(unique,[ --enable-unique Attribute Uniqueness overlay no|yes|mod],
${ol_dflt_overlays-no}, [no yes mod])
OL_ARG_ENABLE(valsort,[ --enable-valsort Value Sorting overlay no|yes|mod],
${ol_dflt_overlays-no}, [no yes mod])
dnl ----------------------------------------------------------------
......@@ -521,6 +536,7 @@ BUILD_RWM=no
BUILD_SYNCPROV=no
BUILD_TRANSLUCENT=no
BUILD_UNIQUE=no
BUILD_VALSORT=no
SLAPD_STATIC_OVERLAYS=
SLAPD_DYNAMIC_OVERLAYS=
......@@ -2726,7 +2742,7 @@ if test "$ol_enable_relay" != no ; then
fi
if test "$ol_enable_shell" != no ; then
if test "$ol_link_thread" != no ; then
if test "$ol_link_threads" != no ; then
AC_MSG_WARN([Use of --without-threads is recommended with back-shell])
fi
BUILD_SLAPD=yes
......@@ -2923,6 +2939,18 @@ if test "$ol_enable_unique" != no ; then
AC_DEFINE_UNQUOTED(SLAPD_OVER_UNIQUE,$MFLAG,[define for Attribute Uniqueness overlay])
fi
if test "$ol_enable_valsort" != no ; then
BUILD_VALSORT=$ol_enable_valsort
if test "$ol_enable_valsort" = mod ; then
MFLAG=SLAPD_MOD_DYNAMIC
SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS valsort.la"
else
MFLAG=SLAPD_MOD_STATIC
SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS valsort.o"
fi
AC_DEFINE_UNQUOTED(SLAPD_OVER_VALSORT,$MFLAG,[define for Value Sorting overlay])
fi
if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \
$BUILD_SLAPD = yes ; then
BUILD_SLURPD=yes
......@@ -2993,6 +3021,7 @@ dnl overlays
AC_SUBST(BUILD_SYNCPROV)
AC_SUBST(BUILD_TRANSLUCENT)
AC_SUBST(BUILD_UNIQUE)
AC_SUBST(BUILD_VALSORT)
AC_SUBST(BUILD_SLURPD)
AC_SUBST(LDAP_LIBS)
......
......@@ -38,6 +38,7 @@ static int
pg_dynacl_parse(
const char *fname,
int lineno,
const char *opts,
slap_style_t style,
const char *pattern,
void **privp )
......@@ -75,6 +76,8 @@ pg_dynacl_parse(
goto cleanup;
}
/* TODO: use opts to allow the use of different
* group objects and member attributes */
if ( pg_posixGroup == NULL ) {
pg_posixGroup = oc_find( "posixGroup" );
if ( pg_posixGroup == NULL ) {
......
......@@ -255,7 +255,7 @@ It can have the forms
sasl_ssf=<n>
aci[=<attrname>]
dynacl/name[.<dynstyle>][=<pattern>]
dynacl/name[/<options>][.<dynstyle>][=<pattern>]
.fi
.LP
with
......@@ -633,7 +633,7 @@ operational attribute is used.
ACIs are experimental; they must be enabled at compile time.
.LP
The statement
.B dynacl/<name>[.<dynstyle>][=<pattern>]
.B dynacl/<name>[/<options>][.<dynstyle>][=<pattern>]
means that access checking is delegated to the admin-defined method
indicated by
.BR <name> ,
......@@ -641,6 +641,7 @@ which can be registered at run-time by means of the
.B moduleload
statement.
The fields
.BR <options> ,
.B <dynstyle>
and
.B <pattern>
......
......@@ -106,5 +106,6 @@ default slapd configuration file
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8).
.SH AUTHOR
Originally implemented by Pierangelo Masarati.
.SH ACKNOWLEDGEMENTS
.P
This module was written in 2004 by Pierangelo Masarati for SysNet s.n.c.
......@@ -517,6 +517,7 @@ policy rules will be enforced.
EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
SINGLE-VALUE
NO-USER-MODIFICATION
USAGE directoryOperation)
.RE
......@@ -537,6 +538,7 @@ does not exist, the user's password will not expire.
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SINGLE-VALUE
NO-USER-MODIFICATION
USAGE directoryOperation)
.RE
......@@ -557,6 +559,7 @@ and may only be unlocked by an administrator.
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SINGLE-VALUE
NO-USER-MODIFICATION
USAGE directoryOperation)
.RE
......@@ -590,6 +593,7 @@ will be cleansed of entries.
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
NO-USER-MODIFICATION
USAGE directoryOperation )
.RE
......@@ -643,6 +647,7 @@ field is in GMT format.
DESC 'The history of user passwords'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
EQUALITY octetStringMatch
NO-USER-MODIFICATION
USAGE directoryOperation)
.RE
......@@ -667,6 +672,7 @@ attribute.
DESC 'The timestamps of the grace login once the password has expired'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
EQUALITY generalizedTimeMatch
NO-USER-MODIFICATION
USAGE directoryOperation)
.RE
......@@ -712,7 +718,7 @@ ppolicy_default "cn=Standard,ou=Policies,dc=example,dc=com"
.LP
IETF LDAP password policy proposal by P. Behera, L. Poitou and J.
Sermersheim: documented in IETF document
"draft-behera-ldap-password-policy-08.txt".
"draft-behera-ldap-password-policy-09.txt".
.SH BUGS
The LDAP Password Policy specification is not yet an approved standard,
......@@ -731,8 +737,8 @@ IETF LDAP password policy proposal by P. Behera, L.
Poitou and J. Sermersheim.
The proposal is fully documented in
the
IETF document named draft-behera-ldap-password-policy-08.txt,
written in October of 2004.
IETF document named draft-behera-ldap-password-policy-09.txt,
written in July of 2005.
.P
.B OpenLDAP
is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
......
......@@ -28,13 +28,14 @@ Well-known response codes from standard track documents are provided
in \fBretcode.conf\fP, which can be included after instantiating
the overlay.
.LP
In the second case, objects of the \fBerrObject\fP class, when returned
as intermediate responses of a search request, are changed into
the response dictated by their content.
In the second case, objects of classes inherited from
the \fBerrAbsObject\fP, like \fBerrObject\fP or \fBerrAuxObject\fP,
when returned as intermediate responses of a search request, are changed
into the response dictated by their content.
.LP
A third mode causes objects to be looked up from the underlying database
to discover if their class is \fBerrObject\fP; in that case, their content
is used to compute the corresponding response.
to discover if their class inherits from \fBerrABsObject\fP;
in that case, their content is used to compute the corresponding response.
.LP
The behavior is disabled by using the \fBmanageDSAit\fP control (RFC 3296);
in that case, the resulting object, either present in the directory
......@@ -68,8 +69,8 @@ response code.
.RE
.TP
.B retcode\-indir
Enables exploitation of in-directory stored errObjects. May result
in lots of unnecessary overhead.
Enables exploitation of in-directory stored errAbsObject.
May result in a lot of unnecessary overhead.
.SH SCHEMA
The following schema items are created and used by the overlay:
......@@ -116,14 +117,28 @@ The sleep time before the response is actually returned to the client:
SINGLE-VALUE )
.RE
.LP
The objectclass:
The abstract class that triggers the overlay:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.3.1
NAME ( 'errObject' )
SUP top STRUCTURAL
( 1.3.6.1.4.1.4203.666.11.4.3.0
NAME ( 'errAbsObject' )
SUP top ABSTRACT
MUST ( errCode )
MAY ( cn $ description $ errOp $ errText $ errSleepTime ) )
.RE
.LP
The standalone structural objectclass for specifically created data:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.3.1
NAME ( 'errObject' )
SUP errAbsObject STRUCTURAL )
.RE
.LP
The auxiliary objectclass to alter the behavior of existing objects:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.3.2
NAME ( 'errAuxObject' )
SUP errAbsObject AUXILIARY )
.RE
.SH EXAMPLE
.LP
......@@ -149,5 +164,6 @@ default slapd configuration file
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8),
.SH AUTHOR
Pierangelo Masarati
.SH ACKNOWLEDGEMENTS
.P
This module was written in 2005 by Pierangelo Masarati for SysNet s.n.c.
......@@ -223,6 +223,7 @@ typedef struct ldapcontrol {
#define LDAP_CONTROL_NO_SUBORDINATES "1.3.6.1.4.1.4203.666.5.11"
#define LDAP_CONTROL_MANAGEDIT "1.3.6.1.4.1.4203.666.5.12"
#define LDAP_CONTROL_SLURP "1.3.6.1.4.1.4203.666.5.13"
#define LDAP_CONTROL_VALSORT "1.3.6.1.4.1.4203.666.5.14"
/* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */
#define LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1"
......@@ -244,7 +245,7 @@ typedef struct ldapcontrol {
#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10"
/* Password policy Controls *//* work in progress */
/* ITS#3458: released, but not to latest draft; disabled by default */
/* ITS#3458: released; disabled by default */
#define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1"
#define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1"
......
......@@ -208,6 +208,9 @@ ldap_pvt_thread_pool_purgekey LDAP_P(( void *key ));
LDAP_F( void *)
ldap_pvt_thread_pool_context LDAP_P(( void ));
LDAP_F( void )
ldap_pvt_thread_pool_context_reset LDAP_P(( void *key ));
LDAP_END_DECL
#endif /* _LDAP_THREAD_H */
......@@ -983,9 +983,10 @@ int ldap_pvt_sasl_secprops(
sprops[j].key.bv_len )) continue;
if ( sprops[j].ival ) {
int v;
if ( props[i][sprops[j].key.bv_len] != '=' ) continue;
if ( !isdigit( props[i][sprops[j].key.bv_len+1] )) continue;
v = atoi( props[i]+sprops[j].key.bv_len+1 );
char *next = NULL;
if ( !isdigit( props[i][sprops[j].key.bv_len] )) continue;
v = strtoul( &props[i][sprops[j].key.bv_len], &next, 10 );
if ( next == NULL || next[ 0 ] != '\0' ) continue;
switch( sprops[j].ival ) {
case GOT_MINSSF:
min_ssf = v; got_min_ssf++; break;
......
......@@ -407,7 +407,11 @@ try_read1msg(
* v3ref = flag for V3 referral / search reference
* 0 = not a ref, 1 = sucessfully chased ref, -1 = pass ref to application
*/
int v3ref;
enum {
V3REF_NOREF = 0,
V3REF_SUCCESS = 1,
V3REF_TOAPP = -1
} v3ref;
assert( ld != NULL );
assert( lcp != NULL );
......@@ -519,15 +523,16 @@ nextresp2:
* This code figures out if we are going to chase a
* referral / search reference, or pass it back to the application
*/
v3ref = 0; /* Assume not a V3 search reference or referral */
v3ref = V3REF_NOREF; /* Assume not a V3 search reference/referral */
if( (tag != LDAP_RES_SEARCH_ENTRY) && (ld->ld_version > LDAP_VERSION2) ) {
BerElement tmpber = *ber; /* struct copy */
char **refs = NULL;
if( tag == LDAP_RES_SEARCH_REFERENCE) {
if( tag == LDAP_RES_SEARCH_REFERENCE ) {
/* This is a V3 search reference */
/* Assume we do not chase the reference, but pass it to application */
v3ref = -1;
/* Assume we do not chase the reference,
* but pass it to application */
v3ref = V3REF_TOAPP;
if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
(lr->lr_parent != NULL) )
{
......@@ -535,18 +540,23 @@ nextresp2:
if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) {
rc = LDAP_DECODING_ERROR;
} else {
/* Note: refs arrary is freed by ldap_chase_v3referrals */
/* Note: refs array is freed by ldap_chase_v3referrals */
refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
1, &lr->lr_res_error, &hadref );
if ( refer_cnt > 0 ) { /* sucessfully chased reference */
if ( refer_cnt > 0 ) {
/* sucessfully chased reference */
/* If haven't got end search, set chasing referrals */
if( lr->lr_status != LDAP_REQST_COMPLETED) {
lr->lr_status = LDAP_REQST_CHASINGREFS;
Debug( LDAP_DEBUG_TRACE,
"read1msg: search ref chased, mark request chasing refs, id = %d\n",
lr->lr_msgid, 0, 0);
"read1msg: search ref chased, "
"mark request chasing refs, "
"id = %d\n",
lr->lr_msgid, 0, 0);
}
v3ref = 1; /* We sucessfully chased the reference */
/* We sucessfully chased the reference */
v3ref = V3REF_SUCCESS;
}
}
}
......@@ -572,11 +582,13 @@ nextresp2:
/* Check if V3 referral */
if ( ber_peek_tag( &tmpber, &len ) == LDAP_TAG_REFERRAL ) {
/* We have a V3 referral, assume we cannot chase it */
v3ref = -1;
v3ref = V3REF_TOAPP;
if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS)
|| (lr->lr_parent != NULL) )
{
v3ref = -1; /* Assume referral not chased and return it to app */
/* Assume referral not chased and return it to app */
v3ref = V3REF_TOAPP;
/* Get the referral list */
if( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) {
rc = LDAP_DECODING_ERROR;
......@@ -595,7 +607,8 @@ nextresp2:
"read1msg: referral chased, mark request completed, id = %d\n",
lr->lr_msgid, 0, 0);
if( refer_cnt > 0) {
v3ref = 1; /* Referral successfully chased */
/* Referral successfully chased */
v3ref = V3REF_SUCCESS;
}
}
}
......@@ -617,7 +630,7 @@ nextresp2:
* go through the following code. This code also chases V2 referrals
* and checks if all referrals have been chased.
*/
if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref > -1) &&
if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref != V3REF_TOAPP) &&
(tag != LDAP_RES_INTERMEDIATE ))
{
/* For a v3 search referral/reference, only come here if already chased it */
......@@ -628,7 +641,7 @@ nextresp2:
char *lr_res_error = NULL;
tmpber = *ber; /* struct copy */
if ( v3ref == 1 ) {
if ( v3ref == V3REF_SUCCESS ) {
/* V3 search reference or V3 referral
* sucessfully chased. If this message
* is a search result, then it has no more
......@@ -647,15 +660,31 @@ nextresp2:
} else {
lr->lr_res_error = lr_res_error;
}
lr_res_error = NULL;
}
if ( lderr != LDAP_SUCCESS ) {
switch ( lderr ) {
case LDAP_SUCCESS:
case LDAP_COMPARE_TRUE:
case LDAP_COMPARE_FALSE:
break;
default:
if ( lr->lr_res_error == NULL
|| lr->lr_res_error[ 0 ] == '\0' )
{
break;
}
/* referrals are in error string */
refer_cnt = ldap_chase_referrals( ld, lr,
&lr->lr_res_error, -1, &hadref );
lr->lr_status = LDAP_REQST_COMPLETED;
Debug( LDAP_DEBUG_TRACE,
"read1msg: V2 referral chased, mark request completed, id = %d\n", lr->lr_msgid, 0, 0);
"read1msg: V2 referral chased, "
"mark request completed, id = %d\n",
lr->lr_msgid, 0, 0 );
break;
}
/* save errno, message, and matched string */
......
......@@ -96,9 +96,15 @@ static ldap_pvt_thread_mutex_t ldap_pvt_thread_pool_mutex;
static void *ldap_int_thread_pool_wrapper( void *pool );
static ldap_pvt_thread_t ldap_int_main_tid;
static ldap_int_thread_key_t ldap_int_main_thrctx[LDAP_MAXTHR];
int
ldap_int_thread_pool_startup ( void )
{
ldap_int_main_tid = ldap_pvt_thread_self();
return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
}
......@@ -652,6 +658,8 @@ void *ldap_pvt_thread_pool_context( )
int i, hash;
tid = ldap_pvt_thread_self();
if ( TID_EQ( tid, ldap_int_main_tid ))
return ldap_int_main_thrctx;
TID_HASH( tid, hash );
for (i = hash & (LDAP_MAXTHR-1); !TID_EQ(thread_keys[i].id, tid_zero) &&
......@@ -660,4 +668,15 @@ void *ldap_pvt_thread_pool_context( )
return thread_keys[i].ctx;
}
void ldap_pvt_thread_pool_context_reset( void *vctx )
{
ldap_int_thread_key_t *ctx = vctx;
int i;
for ( i=0; i<MAXKEYS && ctx[i].ltk_key; i++) {
if ( ctx[i].ltk_free )
ctx[i].ltk_free( ctx[i].ltk_key, ctx[i].ltk_data );
ctx[i].ltk_key = NULL;
}
}
#endif /* LDAP_THREAD_HAVE_TPOOL */
......@@ -303,10 +303,15 @@ lutil_passwd(
}
#ifdef SLAPD_CLEARTEXT
/* Do we think there is a scheme specifier here that we
* didn't recognize? Assume a scheme name is at least 1 character.
*/
if (( passwd->bv_val[0] == '{' ) &&
( strchr( passwd->bv_val, '}' ) > passwd->bv_val+1 ))
return 1;
if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
return (( passwd->bv_len == cred->bv_len ) &&
( passwd->bv_val[0] != '{' /*'}'*/ ))
? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
return ( passwd->bv_len == cred->bv_len ) ?
memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
: 1;
}
#endif
......
......@@ -42,6 +42,34 @@
#define ACI_BUF_SIZE 1024 /* use most appropriate size */
#ifdef SLAP_DYNACL
static
#endif /* SLAP_DYNACL */
AttributeDescription *slap_ad_aci;
static int
OpenLDAPaciValidate(
Syntax *syntax,
struct berval *val );
static int
OpenLDAPaciPretty(
Syntax *syntax,
struct berval *val,
struct berval *out,
void *ctx );
static int
OpenLDAPaciNormalize(
slap_mask_t use,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *out,
void *ctx );
#define OpenLDAPaciMatch octetStringMatch
static int
aci_list_map_rights(
struct berval *list )
......@@ -57,6 +85,20 @@ aci_list_map_rights(
}
switch ( *bv.bv_val ) {
case 'x':
/* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt does not
* define any equivalent to the AUTH right, so I've just used
* 'x' for now.
*/
ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
break;
case 'd':
/* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt defines
* the right 'd' to mean "delete"; we hijack it to mean
* "disclose" for consistency wuith the rest of slapd.
*/
ACL_PRIV_SET(mask, ACL_PRIV_DISCLOSE);
break;
case 'c':
ACL_PRIV_SET(mask, ACL_PRIV_COMPARE);
break;
......@@ -74,13 +116,6 @@ aci_list_map_rights(
case 'w':
ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
break;
case 'x':
/* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt does not
* define any equivalent to the AUTH right, so I've just used
* 'x' for now.
*/
ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
break;
default:
break;
}
......@@ -239,7 +274,7 @@ aci_group_member (
const char *text;
int rc;
/* format of string is "group/objectClassValue/groupAttrName" */
/* format of string is "{group|role}/objectClassValue/groupAttrName" */
if ( acl_get_part( subj, 0, '/', &subjdn ) < 0 ) {
return 0;
}
......@@ -299,7 +334,12 @@ aci_mask(
slap_access_t *deny,
slap_aci_scope_t asserted_scope )
{
struct berval bv, scope, perms, type, sdn;
struct berval bv,
scope,
perms,
type,
opts,
sdn;
int rc;
......@@ -413,6 +453,15 @@ aci_mask(
sdn.bv_val = type.bv_val + type.bv_len + STRLENOF( "#" );
sdn.bv_len = aci->bv_len - ( sdn.bv_val - aci->bv_val );
/* get the type options, if any */
if ( acl_get_part( &type, 1, '/', &opts ) > 0 ) {
opts.bv_len = type.bv_len - ( opts.bv_val - type.bv_val );
type.bv_len = opts.bv_val - type.bv_val - 1;
} else {
BER_BVZERO( &opts );
}
if ( ber_bvcmp( &aci_bv[ ACI_BV_ACCESS_ID ], &type ) == 0 ) {
return dn_match( &op->o_ndn, &sdn );
......@@ -459,15 +508,47 @@ aci_mask(
return rc;
} else if ( ber_bvcmp( &aci_bv[ ACI_BV_GROUP ], &type ) == 0 ) {
if ( aci_group_member( &sdn, &aci_bv[ ACI_BV_GROUP_CLASS ],
&aci_bv[ ACI_BV_GROUP_ATTR ], op, e, nmatch, matches ) )
struct berval oc,
at;
if ( BER_BVISNULL( &opts ) ) {
oc = aci_bv[ ACI_BV_GROUP_CLASS ];
at = aci_bv[ ACI_BV_GROUP_ATTR ];
} else {
if ( acl_get_part( &opts, 0, '/', &oc ) < 0 ) {
assert( 0 );
}
if ( acl_get_part( &opts, 1, '/', &at ) < 0 ) {
at = aci_bv[ ACI_BV_GROUP_ATTR ];
}