Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37497907
en ru br
Репозитории ALT
S:2.6.4-alt1
5.1: 2.3.43-alt2.3
4.1: 2.3.41-alt3.M41.3
4.0: 2.3.35-alt1.M40.1
3.0: 2.2.27-alt1.1
www.altlinux.org/Changes

Группа :: Система/Серверы
Пакет: openldap

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: openldap-2.3.34-alt-meta-backend.patch
Скачать


diff -ruN openldap-2.3.34.orig/servers/slapd/back-meta/bind.c openldap-2.3.34/servers/slapd/back-meta/bind.c
--- openldap-2.3.34.orig/servers/slapd/back-meta/bind.c	2007-01-28 09:56:43 +1000
+++ openldap-2.3.34/servers/slapd/back-meta/bind.c	2007-03-18 04:28:07 +1000
@@ -1437,3 +1437,365 @@
 
 	return LDAP_BACK_CONN_ISBOUND( msc );
 }
+
+#define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ	"2.16.840.1.113730.3.4.12"
+/*
+ * ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control
+ * to existing server-side controls if required; if not,
+ * the existing server-side controls are placed in *pctrls.
+ * The caller, after using the controls in client API 
+ * operations, if ( *pctrls != op->o_ctrls ), should
+ * free( (*pctrls)[ 0 ] ) and free( *pctrls ).
+ * The function returns success if the control could
+ * be added if required, or if it did nothing; in the future,
+ * it might return some error if it failed.
+ * 
+ * if no bind took place yet, but the connection is bound
+ * and the "proxyauthzdn" is set, then bind as "proxyauthzdn" 
+ * and explicitly add proxyAuthz the control to every operation
+ * with the dn bound to the connection as control value.
+ *
+ * If no server-side controls are defined for the operation,
+ * simply add the proxyAuthz control; otherwise, if the
+ * proxyAuthz control is not already set, add it as
+ * the first one
+ *
+ * FIXME: is controls order significant for security?
+ * ANSWER: controls ordering and interoperability
+ * must be indicated by the specs of each control; if none
+ * is specified, the order is irrelevant.
+ */
+int
+ldap_back_proxy_authz_ctrl(
+		struct berval	*bound_ndn,
+		int		version,
+		slap_idassert_t	*si,
+		Operation	*op,
+		SlapReply	*rs,
+		LDAPControl	***pctrls )
+{
+	LDAPControl		**ctrls = NULL;
+	int			i = 0;
+	slap_idassert_mode_t	mode;
+	struct berval		assertedID,
+				ndn;
+	int			isroot = 0;
+
+	*pctrls = NULL;
+
+	rs->sr_err = LDAP_SUCCESS;
+
+	/* don't proxyAuthz if protocol is not LDAPv3 */
+	switch ( version ) {
+	case LDAP_VERSION3:
+		break;
+
+	case 0:
+		if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+			break;
+		}
+		/* fall thru */
+
+	default:
+		goto done;
+	}
+
+	/* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,
+	 * but if it is not set this test fails.  We need a different
+	 * means to detect if idassert is enabled */
+	if ( ( BER_BVISNULL( &si->si_bc.sb_authcId ) || BER_BVISEMPTY( &si->si_bc.sb_authcId ) )
+			&& ( BER_BVISNULL( &si->si_bc.sb_binddn ) || BER_BVISEMPTY( &si->si_bc.sb_binddn ) ) )
+	{
+		goto done;
+	}
+
+	if ( !op->o_conn || op->o_do_not_cache || ( isroot = be_isroot( op ) ) ) {
+		goto done;
+	}
+
+	if ( op->o_tag == LDAP_REQ_BIND ) {
+		ndn = op->o_req_ndn;
+
+	} else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+		ndn = op->o_conn->c_ndn;
+
+	} else {
+		ndn = op->o_ndn;
+	}
+
+	if ( si->si_mode == LDAP_BACK_IDASSERT_LEGACY ) {
+		if ( op->o_proxy_authz ) {
+			/*
+			 * FIXME: we do not want to perform proxyAuthz
+			 * on behalf of the client, because this would
+			 * be performed with "proxyauthzdn" privileges.
+			 *
+			 * This might actually be too strict, since
+			 * the "proxyauthzdn" authzTo, and each entry's
+			 * authzFrom attributes may be crafted
+			 * to avoid unwanted proxyAuthz to take place.
+			 */
+#if 0
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rs->sr_text = "proxyAuthz not allowed within namingContext";
+#endif
+			goto done;
+		}
+
+		if ( !BER_BVISNULL( bound_ndn ) ) {
+			goto done;
+		}
+
+		if ( BER_BVISNULL( &ndn ) ) {
+			goto done;
+		}
+
+		if ( BER_BVISNULL( &si->si_bc.sb_binddn ) ) {
+			goto done;
+		}
+
+	} else if ( si->si_bc.sb_method == LDAP_AUTH_SASL ) {
+		if ( ( si->si_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
+		{
+			/* already asserted in SASL via native authz */
+			goto done;
+		}
+
+	} else if ( si->si_authz && !isroot ) {
+		int		rc;
+		struct berval authcDN;
+
+		if ( BER_BVISNULL( &ndn ) ) {
+			authcDN = slap_empty_bv;
+		} else {
+			authcDN = ndn;
+		}
+		rc = slap_sasl_matches( op, si->si_authz,
+				&authcDN, & authcDN );
+		if ( rc != LDAP_SUCCESS ) {
+			if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+				/* ndn is not authorized
+				 * to use idassert */
+				rs->sr_err = rc;
+			}
+			goto done;
+		}
+	}
+
+	if ( op->o_proxy_authz ) {
+		/*
+		 * FIXME: we can:
+		 * 1) ignore the already set proxyAuthz control
+		 * 2) leave it in place, and don't set ours
+		 * 3) add both
+		 * 4) reject the operation
+		 *
+		 * option (4) is very drastic
+		 * option (3) will make the remote server reject
+		 * the operation, thus being equivalent to (4)
+		 * option (2) will likely break the idassert
+		 * assumptions, so we cannot accept it;
+		 * option (1) means that we are contradicting
+		 * the client's reques.
+		 *
+		 * I think (4) is the only correct choice.
+		 */
+		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+		rs->sr_text = "proxyAuthz not allowed within namingContext";
+	}
+
+	if ( op->o_is_auth_check ) {
+		mode = LDAP_BACK_IDASSERT_NOASSERT;
+
+	} else {
+		mode = si->si_mode;
+	}
+
+	switch ( mode ) {
+	case LDAP_BACK_IDASSERT_LEGACY:
+		/* original behavior:
+		 * assert the client's identity */
+	case LDAP_BACK_IDASSERT_SELF:
+		assertedID = ndn;
+		break;
+
+	case LDAP_BACK_IDASSERT_ANONYMOUS:
+		/* assert "anonymous" */
+		assertedID = slap_empty_bv;
+		break;
+
+	case LDAP_BACK_IDASSERT_NOASSERT:
+		/* don't assert; bind as proxyauthzdn */
+		goto done;
+
+	case LDAP_BACK_IDASSERT_OTHERID:
+	case LDAP_BACK_IDASSERT_OTHERDN:
+		/* assert idassert DN */
+		assertedID = si->si_bc.sb_authzId;
+		break;
+
+	default:
+		assert( 0 );
+	}
+
+	/* if we got here, "" is allowed to proxyAuthz */
+	if ( BER_BVISNULL( &assertedID ) ) {
+		assertedID = slap_empty_bv;
+	}
+
+	/* don't idassert the bound DN (ITS#4497) */
+	if ( dn_match( &assertedID, bound_ndn ) ) {
+		goto done;
+	}
+
+	if ( op->o_ctrls ) {
+		for ( i = 0; op->o_ctrls[ i ]; i++ )
+			/* just count ctrls */ ;
+	}
+
+	ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + 2) + sizeof( LDAPControl ),
+			op->o_tmpmemctx );
+	ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + 2 ];
+	
+	ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+	ctrls[ 0 ]->ldctl_iscritical = 1;
+
+	switch ( si->si_mode ) {
+	/* already in u:ID or dn:DN form */
+	case LDAP_BACK_IDASSERT_OTHERID:
+	case LDAP_BACK_IDASSERT_OTHERDN:
+		ber_dupbv_x( &ctrls[ 0 ]->ldctl_value, &assertedID, op->o_tmpmemctx );
+		break;
+
+	/* needs the dn: prefix */
+	default:
+		ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );
+		ctrls[ 0 ]->ldctl_value.bv_val = op->o_tmpalloc( ctrls[ 0 ]->ldctl_value.bv_len + 1,
+				op->o_tmpmemctx );
+		AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
+		AC_MEMCPY( &ctrls[ 0 ]->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],
+				assertedID.bv_val, assertedID.bv_len + 1 );
+		break;
+	}
+
+	/* Older versions of <draft-weltman-ldapv3-proxy> required
+	 * to encode the value of the authzID (and called it proxyDN);
+	 * this hack provides compatibility with those DSAs that
+	 * implement it this way */
+	if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+		struct berval		authzID = ctrls[ 0 ]->ldctl_value;
+		BerElementBuffer	berbuf;
+		BerElement		*ber = (BerElement *)&berbuf;
+		ber_tag_t		tag;
+
+		ber_init2( ber, 0, LBER_USE_DER );
+		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
+
+		tag = ber_printf( ber, "O", &authzID );
+		if ( tag == LBER_ERROR ) {
+			rs->sr_err = LDAP_OTHER;
+			goto free_ber;
+		}
+
+		if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+			rs->sr_err = LDAP_OTHER;
+			goto free_ber;
+		}
+
+free_ber:;
+		op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx );
+		ber_free_buf( ber );
+
+		if ( rs->sr_err != LDAP_SUCCESS ) {
+			op->o_tmpfree( ctrls, op->o_tmpmemctx );
+			ctrls = NULL;
+			goto done;
+		}
+
+	} else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+		struct berval		authzID = ctrls[ 0 ]->ldctl_value,
+					tmp;
+		BerElementBuffer	berbuf;
+		BerElement		*ber = (BerElement *)&berbuf;
+		ber_tag_t		tag;
+
+		if ( strncasecmp( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ) != 0 ) {
+			op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
+			op->o_tmpfree( ctrls, op->o_tmpmemctx );
+			ctrls = NULL;
+			rs->sr_err = LDAP_PROTOCOL_ERROR;
+			goto done;
+		}
+
+		tmp = authzID;
+		tmp.bv_val += STRLENOF( "dn:" );
+		tmp.bv_len -= STRLENOF( "dn:" );
+
+		ber_init2( ber, 0, LBER_USE_DER );
+		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
+
+		/* apparently, Mozilla API encodes this
+		 * as "SEQUENCE { LDAPDN }" */
+		tag = ber_printf( ber, "{O}", &tmp );
+		if ( tag == LBER_ERROR ) {
+			rs->sr_err = LDAP_OTHER;
+			goto free_ber2;
+		}
+
+		if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+			rs->sr_err = LDAP_OTHER;
+			goto free_ber2;
+		}
+
+free_ber2:;
+		op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx );
+		ber_free_buf( ber );
+
+		if ( rs->sr_err != LDAP_SUCCESS ) {
+			op->o_tmpfree( ctrls, op->o_tmpmemctx );
+			ctrls = NULL;
+			goto done;
+		}
+
+		ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
+	}
+
+	if ( op->o_ctrls ) {
+		for ( i = 0; op->o_ctrls[ i ]; i++ ) {
+			ctrls[ i + 1 ] = op->o_ctrls[ i ];
+		}
+	}
+	ctrls[ i + 1 ] = NULL;
+
+done:;
+	if ( ctrls == NULL ) {
+		ctrls = op->o_ctrls;
+	}
+
+	*pctrls = ctrls;
+	
+	return rs->sr_err;
+}
+
+int
+ldap_back_proxy_authz_ctrl_free( Operation *op, LDAPControl ***pctrls )
+{
+	LDAPControl	**ctrls = *pctrls;
+
+	/* we assume that the first control is the proxyAuthz
+	 * added by back-ldap, so it's the only one we explicitly 
+	 * free */
+	if ( ctrls && ctrls != op->o_ctrls ) {
+		assert( ctrls[ 0 ] != NULL );
+
+		if ( !BER_BVISNULL( &ctrls[ 0 ]->ldctl_value ) ) {
+			op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
+		}
+
+		op->o_tmpfree( ctrls, op->o_tmpmemctx );
+	} 
+
+	*pctrls = NULL;
+
+	return 0;
+}
diff -ruN openldap-2.3.34.orig/servers/slapd/back-meta/config.c openldap-2.3.34/servers/slapd/back-meta/config.c
--- openldap-2.3.34.orig/servers/slapd/back-meta/config.c	2007-01-28 09:56:43 +1000
+++ openldap-2.3.34/servers/slapd/back-meta/config.c	2007-03-18 04:27:08 +1000
@@ -28,12 +28,232 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "config.h"
 #include "lutil.h"
 #include "../back-ldap/back-ldap.h"
 #undef ldap_debug       /* silence a warning in ldap-int.h */
 #include "../../../libraries/libldap/ldap-int.h"
 #include "back-meta.h"
 
+static slap_verbmasks idassert_mode[] = {
+	{ BER_BVC("self"),		LDAP_BACK_IDASSERT_SELF },
+	{ BER_BVC("anonymous"),		LDAP_BACK_IDASSERT_ANONYMOUS },
+	{ BER_BVC("none"),		LDAP_BACK_IDASSERT_NOASSERT },
+	{ BER_BVC("legacy"),		LDAP_BACK_IDASSERT_LEGACY },
+	{ BER_BVNULL,			0 }
+};
+
+
+
+static int
+slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si )
+{
+	struct berval	bv;
+
+ 	if ( strcmp( c->argv[ 1 ], "*" ) == 0
+ 		|| strcmp( c->argv[ 1 ], "dn:*" ) == 0
+ 		|| strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 )
+ 	{
+ 		if ( si->si_authz != NULL ) {
+ 			snprintf( c->msg, sizeof( c->msg ),
+ 				"\"idassert-authzFrom <authz>\": "
+ 				"\"%s\" conflicts with existing authz rules",
+ 				c->argv[ 1 ] );
+ 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ 			return 1;
+ 		}
+ 
+ 		si->si_flags |= LDAP_BACK_AUTH_AUTHZ_ALL;
+ 
+ 		return 0;
+ 
+ 	} else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) {
+  		snprintf( c->msg, sizeof( c->msg ),
+  			"\"idassert-authzFrom <authz>\": "
+ 			"\"<authz>\" conflicts with \"*\"" );
+  		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+  		return 1;
+  	}
+
+#ifdef SLAP_AUTHZ_SYNTAX
+	{
+		struct berval	in;
+		int		rc;
+
+		ber_str2bv( c->argv[ 1 ], 0, 0, &in );
+		rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
+		if ( rc != LDAP_SUCCESS ) {
+			snprintf( c->msg, sizeof( c->msg ),
+				"\"idassert-authzFrom <authz>\": "
+				"invalid syntax" );
+			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+			return 1;
+		}
+	}
+#else /* !SLAP_AUTHZ_SYNTAX */
+	ber_str2bv( c->argv[ 1 ], 0, 1, &bv );
+#endif /* !SLAP_AUTHZ_SYNTAX */
+
+	ber_bvarray_add( &si->si_authz, &bv );
+
+	return 0;
+}
+
+
+static int
+slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
+{
+	int		i;
+
+	for ( i = 1; i < c->argc; i++ ) {
+		if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
+			char	*argvi = c->argv[ i ] + STRLENOF( "mode=" );
+			int	j;
+
+			j = verb_to_mask( argvi, idassert_mode );
+			if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
+				snprintf( c->msg, sizeof( c->msg ),
+					"\"idassert-bind <args>\": "
+					"unknown mode \"%s\"",
+					argvi );
+				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+				return 1;
+			}
+
+			si->si_mode = idassert_mode[ j ].mask;
+
+		} else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
+			char	*argvi = c->argv[ i ] + STRLENOF( "authz=" );
+
+			if ( strcasecmp( argvi, "native" ) == 0 ) {
+				if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) {
+					snprintf( c->msg, sizeof( c->msg ),
+						"\"idassert-bind <args>\": "
+						"authz=\"native\" incompatible "
+						"with auth method" );
+					Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+					return 1;
+				}
+				si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
+
+			} else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
+				si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
+
+			} else {
+				snprintf( c->msg, sizeof( c->msg ),
+					"\"idassert-bind <args>\": "
+					"unknown authz \"%s\"",
+					argvi );
+				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+				return 1;
+			}
+
+		} else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
+			char	*argvi = c->argv[ i ] + STRLENOF( "flags=" );
+			char	**flags = ldap_str2charray( argvi, "," );
+			int	j, err = 0;
+
+			if ( flags == NULL ) {
+				snprintf( c->msg, sizeof( c->msg ),
+					"\"idassert-bind <args>\": "
+					"unable to parse flags \"%s\"",
+					argvi );
+				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+				return 1;
+			}
+
+			for ( j = 0; flags[ j ] != NULL; j++ ) {
+
+				if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
+					si->si_flags |= LDAP_BACK_AUTH_OVERRIDE;
+
+				} else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
+					si->si_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
+
+				} else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
+					si->si_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
+
+				} else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
+					if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+						Debug( LDAP_DEBUG_ANY,
+                                      		 		"%s: \"obsolete-proxy-authz\" flag "
+                                      		 		"in \"idassert-mode <args>\" "
+                                      		 		"incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
+                                      	 			c->log, 0, 0 );
+						err = 1;
+						break;
+
+					} else {
+						si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
+					}
+
+				} else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
+					if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+						Debug( LDAP_DEBUG_ANY,
+                                      	 			"%s: \"obsolete-encoding-workaround\" flag "
+                                       			"in \"idassert-mode <args>\" "
+                                       			"incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
+                                       			c->log, 0, 0 );
+						err = 1;
+						break;
+
+					} else {
+						si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
+					}
+
+				} else {
+					snprintf( c->msg, sizeof( c->msg ),
+						"\"idassert-bind <args>\": "
+						"unknown flag \"%s\"",
+						flags[ j ] );
+					Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+					err = 1;
+					break;
+				}
+			}
+
+			ldap_charray_free( flags );
+			if ( err ) {
+				return 1;
+			}
+
+		} else if ( bindconf_parse( c->argv[ i ], &si->si_bc ) ) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/* NOTE: temporary, until back-meta is ported to back-config */
+int
+slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si )
+{
+	ConfigArgs	c = { 0 };
+	char		*argv[ 3 ];
+
+	snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
+	c.argc = 2;
+	c.argv = argv;
+	argv[ 0 ] = "idassert-authzFrom";
+	argv[ 1 ] = (char *)arg;
+	argv[ 2 ] = NULL;
+
+	return slap_idassert_authzfrom_parse( &c, si );
+}
+int
+slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si )
+{
+	ConfigArgs	c = { 0 };
+
+	snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
+	c.argc = argc;
+	c.argv = argv;
+
+	return slap_idassert_parse( &c, si );
+}
+
+
 static int
 meta_back_new_target( 
 	metatarget_t	**mtp )
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin