Beispiel #1
0
/* pw_string64 function taken from libraries/liblutil/passwd.c */
static int pw_string64(
	const struct berval *sc,
	const struct berval *hash,
	struct berval *b64,
	const struct berval *salt )
{
	int rc;
	struct berval string;
	size_t b64len;

	if( salt ) {
		/* need to base64 combined string */
		string.bv_len = hash->bv_len + salt->bv_len;
		string.bv_val = ber_memalloc( string.bv_len + 1 );

		if( string.bv_val == NULL ) {
			return LUTIL_PASSWD_ERR;
		}

		AC_MEMCPY( string.bv_val, hash->bv_val,
			hash->bv_len );
		AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
			salt->bv_len );
		string.bv_val[string.bv_len] = '\0';

	} else {
		string = *hash;
	}

	b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
	b64->bv_len = b64len + sc->bv_len;
	b64->bv_val = ber_memalloc( b64->bv_len + 1 );

	if( b64->bv_val == NULL ) {
		if( salt ) ber_memfree( string.bv_val );
		return LUTIL_PASSWD_ERR;
	}

	AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);

	rc = lutil_b64_ntop(
		(unsigned char *) string.bv_val, string.bv_len,
		&b64->bv_val[sc->bv_len], b64len );

	if( salt ) ber_memfree( string.bv_val );
	
	if( rc < 0 ) {
		return LUTIL_PASSWD_ERR;
	}

	/* recompute length */
	b64->bv_len = sc->bv_len + rc;
	assert( strlen(b64->bv_val) == b64->bv_len );
	return LUTIL_PASSWD_OK;
}
Beispiel #2
0
static krb5_error_code
LDAP_addmod(LDAPMod *** modlist, int modop, const char *attribute,
	    const char *value)
{
    int cMods, i = 0;
    krb5_error_code ret;

    ret = LDAP__setmod(modlist, modop, attribute, &cMods);
    if (ret)
	return ret;

    if (value != NULL) {
	char **bv;

	bv = (*modlist)[cMods]->mod_values;
	if (bv != NULL) {
	    for (i = 0; bv[i] != NULL; i++)
		;
	    bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv));
	} else
	    bv = ber_memalloc(2 * sizeof(*bv));
	if (bv == NULL)
	    return ENOMEM;

	(*modlist)[cMods]->mod_values = bv;

	bv[i] = ber_strdup(value);
	if (bv[i] == NULL)
	    return ENOMEM;

	bv[i + 1] = NULL;
    }

    return 0;
}
Beispiel #3
0
void *
create_sasl_defaults(LDAP *ld, char *mech, char *realm, char *authcid, char *passwd, char *authzid) {
	lutilSASLdefaults *defaults;

	defaults = ber_memalloc(sizeof(lutilSASLdefaults));
	if(defaults == NULL) return (void *)PyErr_NoMemory();

	defaults->mech = mech ? ber_strdup(mech) : NULL;
	defaults->realm = realm ? ber_strdup(realm) : NULL;
	defaults->authcid = authcid ? ber_strdup(authcid) : NULL;
	defaults->passwd = passwd ? ber_strdup(passwd) : NULL;
	defaults->authzid = authzid ? ber_strdup(authzid) : NULL;

	if (defaults->mech == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &defaults->mech);
	}
	if (defaults->realm == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &defaults->realm);
	}
	if (defaults->authcid == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid);
	}
	if (defaults->authzid == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid);
	}
	defaults->resps = NULL;
	defaults->nresps = 0;

	return defaults;
}
Beispiel #4
0
static RLDAP_BICTX *_rldap_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *sasl_authc_id, char *passwd, char *sasl_authz_id)
{
	RLDAP_BICTX *ctx;
	
	ctx = ber_memalloc(sizeof(RLDAP_BICTX));	
	ctx->mech    = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
	ctx->realm   = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
	ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
	ctx->passwd  = (passwd) ? ber_strdup(passwd) : NULL;
	ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;

	if (ctx->mech == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
	}
	if (ctx->realm == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
	}
	if (ctx->authcid == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
	}
	if (ctx->authzid == NULL) {
		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
	}

	return ctx;
}
char* chomp(char *s)
{
  char* t = ber_memalloc(strlen(s)+1);
  strncpy (t,s,strlen(s)+1);

  if ( t[strlen(t)-1] == '\n' ) {
    t[strlen(t)-1] = '\0';
  }

  return t;
}
Beispiel #6
0
static krb5_error_code
LDAP__setmod(LDAPMod *** modlist, int modop, const char *attribute,
	     int *pIndex)
{
    int cMods;

    if (*modlist == NULL) {
	*modlist = (LDAPMod **)ber_memcalloc(1, sizeof(LDAPMod *));
	if (*modlist == NULL)
	    return ENOMEM;
    }

    for (cMods = 0; (*modlist)[cMods] != NULL; cMods++) {
	if ((*modlist)[cMods]->mod_op == modop &&
	    strcasecmp((*modlist)[cMods]->mod_type, attribute) == 0) {
	    break;
	}
    }

    *pIndex = cMods;

    if ((*modlist)[cMods] == NULL) {
	LDAPMod *mod;

	*modlist = (LDAPMod **)ber_memrealloc(*modlist,
					      (cMods + 2) * sizeof(LDAPMod *));
	if (*modlist == NULL)
	    return ENOMEM;

	(*modlist)[cMods] = (LDAPMod *)ber_memalloc(sizeof(LDAPMod));
	if ((*modlist)[cMods] == NULL)
	    return ENOMEM;

	mod = (*modlist)[cMods];
	mod->mod_op = modop;
	mod->mod_type = ber_strdup(attribute);
	if (mod->mod_type == NULL) {
	    ber_memfree(mod);
	    (*modlist)[cMods] = NULL;
	    return ENOMEM;
	}

	if (modop & LDAP_MOD_BVALUES) {
	    mod->mod_bvalues = NULL;
	} else {
	    mod->mod_values = NULL;
	}

	(*modlist)[cMods + 1] = NULL;
    }

    return 0;
}
Beispiel #7
0
static krb5_error_code
LDAP_addmod_len(LDAPMod *** modlist, int modop, const char *attribute,
		unsigned char *value, size_t len)
{
    krb5_error_code ret;
    int cMods, i = 0;

    ret = LDAP__setmod(modlist, modop | LDAP_MOD_BVALUES, attribute, &cMods);
    if (ret)
	return ret;

    if (value != NULL) {
	struct berval **bv;

	bv = (*modlist)[cMods]->mod_bvalues;
	if (bv != NULL) {
	    for (i = 0; bv[i] != NULL; i++)
		;
	    bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv));
	} else
	    bv = ber_memalloc(2 * sizeof(*bv));
	if (bv == NULL)
	    return ENOMEM;

	(*modlist)[cMods]->mod_bvalues = bv;

	bv[i] = ber_memalloc(sizeof(**bv));;
	if (bv[i] == NULL)
	    return ENOMEM;

	bv[i]->bv_val = (void *)value;
	bv[i]->bv_len = len;

	bv[i + 1] = NULL;
    }

    return 0;
}
static int realloc_error_message (char ** target, int curlen, int nextlen)
{
	if (curlen < nextlen + MEMORY_MARGIN) {
#if defined(DEBUG)
		syslog(LOG_WARNING, "check_password: Reallocating szErrStr from %d to %d",
				curlen, nextlen + MEMORY_MARGIN);
#endif
#if defined(LDEBUG)
  printf("check_password: Reallocating szErrStr from %d to %d\n",
				curlen, nextlen + MEMORY_MARGIN);
#endif
		ber_memfree(*target);
		curlen = nextlen + MEMORY_MARGIN;
		*target = (char *) ber_memalloc(curlen);
	}

	return curlen;
}
Beispiel #9
0
static int chk_sha512(
	const struct berval *scheme, /* Scheme of hashed reference password */
	const struct berval *passwd, /* Hashed reference password to check against */
	const struct berval *cred, /* user-supplied password to check */
	const char **text )
{
	SHA512_CTX SHAcontext;
	unsigned char SHAdigest[SHA512_DIGEST_LENGTH];
	int rc;
	unsigned char *orig_pass = NULL;
	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);

	/* safety check */
	if (decode_len < sizeof(SHAdigest)) {
		return LUTIL_PASSWD_ERR;
	}

	/* base64 un-encode password */
	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);

	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;

	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);

	if( rc != sizeof(SHAdigest) ) {
		ber_memfree(orig_pass);
		return LUTIL_PASSWD_ERR;
	}

	/* hash credentials with salt */
	SHA512_Init(&SHAcontext);
	SHA512_Update(&SHAcontext,
		(const unsigned char *) cred->bv_val, cred->bv_len);
	SHA512_Final(SHAdigest, &SHAcontext);

	/* compare */
	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
#ifdef SLAPD_SHA2_DEBUG
	chk_sha_debug(scheme, passwd, cred, (char *)SHAdigest, sizeof(SHAdigest), rc);
#endif
	ber_memfree(orig_pass);
	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
}
Beispiel #10
0
/* ARGSUSED */
static int
avl_buildlist( void* data, void* arg )
{
	static int	slots;

	if ( avl_list == (void* *) 0 ) {
		avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*));
		slots = AVL_GRABSIZE;
		avl_maxlist = 0;
	} else if ( avl_maxlist == slots ) {
		slots += AVL_GRABSIZE;
		avl_list = (void* *) ber_memrealloc( (char *) avl_list,
		    (unsigned) slots * sizeof(void*));
	}

	avl_list[ avl_maxlist++ ] = data;

	return( 0 );
}
Beispiel #11
0
static int chk_phk(
	const struct berval *magic,
	const struct berval *passwd,
	const struct berval *cred,
	const char **text)
{
	unsigned char digest[LUTIL_MD5_BYTES];
	unsigned char *orig_pass;
	int rc, n;
	struct berval salt;

	/* safety check */
	n = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
	if (n <= sizeof(digest))
		return LUTIL_PASSWD_ERR;

	/* base64 un-encode password hash */
	orig_pass = (unsigned char *) ber_memalloc((size_t) (n + 1));

	if (orig_pass == NULL)
		return LUTIL_PASSWD_ERR;

	rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);

	if (rc <= (int) sizeof(digest)) {
		ber_memfree(orig_pass);
		return LUTIL_PASSWD_ERR;
	}

	salt.bv_val = (char *) &orig_pass[sizeof(digest)];
	salt.bv_len = rc - sizeof(digest);

	do_phk_hash(cred, magic, &salt, digest);

	if (text)
		*text = NULL;

	/* compare */
	rc = memcmp((char *) orig_pass, (char *) digest, sizeof(digest));
	ber_memfree(orig_pass);
	return rc ?  LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
}
Beispiel #12
0
static void chk_sha_debug(
	const struct berval *scheme,
	const struct berval *passwd,
	const struct berval *cred,
	const char *cred_hash,
	size_t cred_len,
	int cmp_rc)
{
	int rc;
	struct berval cred_b64;

	cred_b64.bv_len = LUTIL_BASE64_ENCODE_LEN(cred_len) + 1;
	cred_b64.bv_val = ber_memalloc(cred_b64.bv_len + 1);

	if( cred_b64.bv_val == NULL ) {
		return;
	}

	rc = lutil_b64_ntop(
		(unsigned char *) cred_hash, cred_len,
		cred_b64.bv_val, cred_b64.bv_len );

	if( rc < 0 ) {
		ber_memfree(cred_b64.bv_val);
		return;
	}

	fprintf(stderr, "Validating password\n");
	fprintf(stderr, "  Hash scheme:\t\t%s\n", scheme->bv_val);
	fprintf(stderr, "  Password to validate: %s\n", cred->bv_val);
	fprintf(stderr, "  Password hash:\t%s\n", cred_b64.bv_val);
	fprintf(stderr, "  Stored password hash:\t%s\n", passwd->bv_val);
	fprintf(stderr, "  Result:\t\t%s\n", cmp_rc ?  "do not match" : "match");

	ber_memfree(cred_b64.bv_val);
}
Beispiel #13
0
/* Parse an LDIF control line of the form
      control:  oid  [true/false]  [: value]              or
      control:  oid  [true/false]  [:: base64-value]      or
      control:  oid  [true/false]  [:< url]
   The control is added to the list of controls in *ppctrls.
*/      
static int
parse_ldif_control(
	struct berval *bval,
	LDAPControl ***ppctrls )
{
	char *oid = NULL;
	int criticality = 0;   /* Default is false if not present */
	int i, rc=0;
	char *s, *oidStart;
	LDAPControl *newctrl = NULL;
	LDAPControl **pctrls = NULL;
	struct berval type, bv;
	int freeval;

	if (ppctrls) pctrls = *ppctrls;
	/* OID should come first. Validate and extract it. */
	s = bval->bv_val;
	if (*s == 0) return ( LDAP_PARAM_ERROR );
	oidStart = s;
	while (isdigit((unsigned char)*s) || *s == '.') {
		s++;                           /* OID should be digits or . */
	}
	if (s == oidStart) { 
		return ( LDAP_PARAM_ERROR );   /* OID was not present */
	}
	if (*s) {                          /* End of OID should be space or NULL */
		if (!isspace((unsigned char)*s)) {
			return ( LDAP_PARAM_ERROR ); /* else OID contained invalid chars */
		}
		*s++ = 0;                    /* Replace space with null to terminate */
	}

	oid = ber_strdup(oidStart);
	if (oid == NULL) return ( LDAP_NO_MEMORY );

	/* Optional Criticality field is next. */
	while (*s && isspace((unsigned char)*s)) {
		s++;                         /* Skip white space before criticality */
	}
	if (strncasecmp(s, "true", 4) == 0) {
		criticality = 1;
		s += 4;
	} 
	else if (strncasecmp(s, "false", 5) == 0) {
		criticality = 0;
		s += 5;
	}

	/* Optional value field is next */
	while (*s && isspace((unsigned char)*s)) {
		s++;                         /* Skip white space before value */
	}
	if (*s) {
		if (*s != ':') {           /* If value is present, must start with : */
			rc = LDAP_PARAM_ERROR;
			goto cleanup;
		}

		/* Back up so value is in the form
		     a: value
		     a:: base64-value
		     a:< url
		   Then we can use ldif_parse_line2 to extract and decode the value
		*/
		s--;
		*s = 'a';

		rc = ldif_parse_line2(s, &type, &bv, &freeval);
		if (rc < 0) {
			rc = LDAP_PARAM_ERROR;
			goto cleanup;
		}
    }

	/* Create a new LDAPControl structure. */
	newctrl = (LDAPControl *)ber_memalloc(sizeof(LDAPControl));
	if ( newctrl == NULL ) {
		rc = LDAP_NO_MEMORY;
		goto cleanup;
	}
	newctrl->ldctl_oid = oid;
	oid = NULL;
	newctrl->ldctl_iscritical = criticality;
	if ( freeval )
		newctrl->ldctl_value = bv;
	else
		ber_dupbv( &newctrl->ldctl_value, &bv );

	/* Add the new control to the passed-in list of controls. */
	i = 0;
	if (pctrls) {
		while ( pctrls[i] ) {    /* Count the # of controls passed in */
			i++;
		}
	}
	/* Allocate 1 more slot for the new control and 1 for the NULL. */
	pctrls = (LDAPControl **) ber_memrealloc(pctrls,
		(i+2)*(sizeof(LDAPControl *)));
	if (pctrls == NULL) {
		rc = LDAP_NO_MEMORY;
		goto cleanup;
	}
	pctrls[i] = newctrl;
	newctrl = NULL;
	pctrls[i+1] = NULL;
	*ppctrls = pctrls;

cleanup:
	if (newctrl) {
		if (newctrl->ldctl_oid) ber_memfree(newctrl->ldctl_oid);
		if (newctrl->ldctl_value.bv_val) {
			ber_memfree(newctrl->ldctl_value.bv_val);
		}
		ber_memfree(newctrl);
	}
	if (oid) ber_memfree(oid);

	return( rc );
}
Beispiel #14
0
static int
process_ldif_rec( char *rbuf, int linenum )
{
	char	*line, *dn, *newrdn, *newsup;
	int		rc, modop;
	int		expect_modop, expect_sep;
	int		deleteoldrdn;
	int		new_entry, delete_entry, got_all;
	LDAPMod	**pmods, *lm = NULL;
	int version;
	LDAPControl **pctrls;
	int i, j, k, lines, idn, nmods;
	struct berval *btype, *vals, **bvl, bv;
	char *freeval;
	unsigned char *mops = NULL;

	new_entry = ldapadd;

	rc = got_all = delete_entry = modop = expect_modop = 0;
	expect_sep = 0;
	version = 0;
	deleteoldrdn = 1;
	pmods = NULL;
	pctrls = NULL;
	dn = newrdn = newsup = NULL;

	lines = ldif_countlines( rbuf );
	btype = ber_memcalloc( 1, (lines+1)*2*sizeof(struct berval)+lines );
	if ( !btype )
		return LDAP_NO_MEMORY;

	vals = btype+lines+1;
	freeval = (char *)(vals+lines+1);
	i = -1;

	while ( rc == 0 && ( line = ldif_getline( &rbuf )) != NULL ) {
		int freev;

		if ( *line == '\n' || *line == '\0' ) {
			break;
		}

		++i;

		if ( line[0] == '-' && !line[1] ) {
			BER_BVZERO( btype+i );
			freeval[i] = 0;
			continue;
		}
	
		if ( ( rc = ldif_parse_line2( line, btype+i, vals+i, &freev ) ) < 0 ) {
			fprintf( stderr, _("%s: invalid format (line %d) entry: \"%s\"\n"),
				prog, linenum+i, dn == NULL ? "" : dn );
			rc = LDAP_PARAM_ERROR;
			break;
		}
		freeval[i] = freev;

		if ( dn == NULL ) {
			if ( linenum+i == 1 && BV_CASEMATCH( btype+i, &BV_VERSION )) {
				int	v;
				if( vals[i].bv_len == 0 || lutil_atoi( &v, vals[i].bv_val) != 0 || v != 1 ) {
					fprintf( stderr,
						_("%s: invalid version %s, line %d (ignored)\n"),
						prog, vals[i].bv_val, linenum );
				}
				version++;

			} else if ( BV_CASEMATCH( btype+i, &BV_DN )) {
				dn = vals[i].bv_val;
				idn = i;
			}
			/* skip all lines until we see "dn:" */
		}
	}

	/* check to make sure there was a dn: line */
	if ( !dn ) {
		rc = 0;
		goto leave;
	}

	lines = i+1;

	if( lines == 0 ) {
		rc = 0;
		goto leave;
	}

	if( version && lines == 1 ) {
		rc = 0;
		goto leave;
	}

	i = idn+1;
	/* Check for "control" tag after dn and before changetype. */
	if ( BV_CASEMATCH( btype+i, &BV_CONTROL )) {
		/* Parse and add it to the list of controls */
		rc = parse_ldif_control( vals+i, &pctrls );
		if (rc != 0) {
			fprintf( stderr,
				_("%s: Error processing %s line, line %d: %s\n"),
				prog, BV_CONTROL.bv_val, linenum+i, ldap_err2string(rc) );
		}
		i++;
		if ( i>= lines ) {
short_input:
			fprintf( stderr,
				_("%s: Expecting more input after %s line, line %d\n"),
				prog, btype[i-1].bv_val, linenum+i );

			rc = LDAP_PARAM_ERROR;
			goto leave;
		}
	}

	/* Check for changetype */
	if ( BV_CASEMATCH( btype+i, &BV_CHANGETYPE )) {
#ifdef LIBERAL_CHANGETYPE_MODOP
		/* trim trailing spaces (and log warning ...) */
		int icnt;
		for ( icnt = vals[i].bv_len; --icnt > 0; ) {
			if ( !isspace( (unsigned char) vals[i].bv_val[icnt] ) ) {
				break;
			}
		}

		if ( ++icnt != vals[i].bv_len ) {
			fprintf( stderr, _("%s: illegal trailing space after"
				" \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
				prog, BV_CHANGETYPE.bv_val, vals[i].bv_val, linenum+i, dn );
			vals[i].bv_val[icnt] = '\0';
		}
#endif /* LIBERAL_CHANGETYPE_MODOP */

		if ( BV_CASEMATCH( vals+i, &BV_MODIFYCT )) {
			new_entry = 0;
			expect_modop = 1;
		} else if ( BV_CASEMATCH( vals+i, &BV_ADDCT )) {
			new_entry = 1;
			modop = LDAP_MOD_ADD;
		} else if ( BV_CASEMATCH( vals+i, &BV_MODRDNCT )
			|| BV_CASEMATCH( vals+i, &BV_MODDNCT )
			|| BV_CASEMATCH( vals+i, &BV_RENAMECT ))
		{
			i++;
			if ( i >= lines )
				goto short_input;
			if ( !BV_CASEMATCH( btype+i, &BV_NEWRDN )) {
				fprintf( stderr, _("%s: expecting \"%s:\" but saw"
					" \"%s:\" (line %d, entry \"%s\")\n"),
					prog, BV_NEWRDN.bv_val, btype[i].bv_val, linenum+i, dn );
				rc = LDAP_PARAM_ERROR;
				goto leave;
			}
			newrdn = vals[i].bv_val;
			i++;
			if ( i >= lines )
				goto short_input;
			if ( !BV_CASEMATCH( btype+i, &BV_DELETEOLDRDN )) {
				fprintf( stderr, _("%s: expecting \"%s:\" but saw"
					" \"%s:\" (line %d, entry \"%s\")\n"),
					prog, BV_DELETEOLDRDN.bv_val, btype[i].bv_val, linenum+i, dn );
				rc = LDAP_PARAM_ERROR;
				goto leave;
			}
			deleteoldrdn = ( vals[i].bv_val[0] == '0' ) ? 0 : 1;
			i++;
			if ( i < lines ) {
				if ( !BV_CASEMATCH( btype+i, &BV_NEWSUP )) {
					fprintf( stderr, _("%s: expecting \"%s:\" but saw"
						" \"%s:\" (line %d, entry \"%s\")\n"),
						prog, BV_NEWSUP.bv_val, btype[i].bv_val, linenum+i, dn );
					rc = LDAP_PARAM_ERROR;
					goto leave;
				}
				newsup = vals[i].bv_val;
				i++;
			}
			got_all = 1;
		} else if ( BV_CASEMATCH( vals+i, &BV_DELETECT )) {
			got_all = delete_entry = 1;
		} else {
			fprintf( stderr,
				_("%s:  unknown %s \"%s\" (line %d, entry \"%s\")\n"),
				prog, BV_CHANGETYPE.bv_val, vals[i].bv_val, linenum+i, dn );
			rc = LDAP_PARAM_ERROR;
			goto leave;
		}
		i++;
	} else if ( ldapadd ) {		/*  missing changetype => add */
		new_entry = 1;
		modop = LDAP_MOD_ADD;
	} else {
		expect_modop = 1;	/* missing changetype => modify */
	}

	if ( got_all ) {
		if ( i < lines ) {
			fprintf( stderr,
				_("%s: extra lines at end (line %d, entry \"%s\")\n"),
				prog, linenum+i, dn );
			rc = LDAP_PARAM_ERROR;
			goto leave;
		}
		goto doit;
	}

	nmods = lines - i;
	idn = i;

	if ( new_entry ) {
		int fv;

		/* Make sure all attributes with multiple values are contiguous */
		for (; i<lines; i++) {
			for (j=i+1; j<lines; j++) {
				if ( BV_CASEMATCH( btype+i, btype+j )) {
					nmods--;
					/* out of order, move intervening attributes down */
					if ( j != i+1 ) {
						bv = vals[j];
						fv = freeval[j];
						for (k=j; k>i; k--) {
							btype[k] = btype[k-1];
							vals[k] = vals[k-1];
							freeval[k] = freeval[k-1];
						}
						k++;
						btype[k] = btype[i];
						vals[k] = bv;
						freeval[k] = fv;
					}
					i++;
				}
			}
		}
		/* Allocate space for array of mods, array of pointers to mods,
		 * and array of pointers to values, allowing for NULL terminators
		 * for the pointer arrays...
		 */
		lm = ber_memalloc( nmods * sizeof(LDAPMod) +
			(nmods+1) * sizeof(LDAPMod*) +
			(lines + nmods - idn) * sizeof(struct berval *));
		pmods = (LDAPMod **)(lm+nmods);
		bvl = (struct berval **)(pmods+nmods+1);

		j = 0;
		k = -1;
		BER_BVZERO(&bv);
		for (i=idn; i<lines; i++) {
			if ( BV_CASEMATCH( btype+i, &BV_DN )) {
				fprintf( stderr, _("%s: attributeDescription \"%s\":"
					" (possible missing newline"
						" after line %d, entry \"%s\"?)\n"),
					prog, btype[i].bv_val, linenum+i - 1, dn );
			}
			if ( !BV_CASEMATCH( btype+i, &bv )) {
				bvl[k++] = NULL;
				bv = btype[i];
				lm[j].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
				lm[j].mod_type = bv.bv_val;
				lm[j].mod_bvalues = bvl+k;
				pmods[j] = lm+j;
				j++;
			}
			bvl[k++] = vals+i;
		}
		bvl[k] = NULL;
		pmods[j] = NULL;
		goto doit;
	}

	mops = ber_memalloc( lines+1 );
	mops[lines] = M_SEP;
	mops[i-1] = M_SEP;

	for ( ; i<lines; i++ ) {
		if ( expect_modop ) {
#ifdef LIBERAL_CHANGETYPE_MODOP
			/* trim trailing spaces (and log warning ...) */
		    int icnt;
		    for ( icnt = vals[i].bv_len; --icnt > 0; ) {
				if ( !isspace( (unsigned char) vals[i].bv_val[icnt] ) ) break;
			}
    
			if ( ++icnt != vals[i].bv_len ) {
				fprintf( stderr, _("%s: illegal trailing space after"
					" \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
					prog, type, vals[i].bv_val, linenum+i, dn );
				vals[i].bv_val[icnt] = '\0';
			}
#endif /* LIBERAL_CHANGETYPE_MODOP */

			expect_modop = 0;
			expect_sep = 1;
			if ( BV_CASEMATCH( btype+i, &BV_MODOPADD )) {
				modop = LDAP_MOD_ADD;
				mops[i] = M_SEP;
				nmods--;
			} else if ( BV_CASEMATCH( btype+i, &BV_MODOPREPLACE )) {
			/* defer handling these since they might have no values.
			 * Use the BVALUES flag to signal that these were
			 * deferred. If values are provided later, this
			 * flag will be switched off.
			 */
				modop = LDAP_MOD_REPLACE;
				mops[i] = modop | LDAP_MOD_BVALUES;
				btype[i] = vals[i];
			} else if ( BV_CASEMATCH( btype+i, &BV_MODOPDELETE )) {
				modop = LDAP_MOD_DELETE;
				mops[i] = modop | LDAP_MOD_BVALUES;
				btype[i] = vals[i];
			} else if ( BV_CASEMATCH( btype+i, &BV_MODOPINCREMENT )) {
				modop = LDAP_MOD_INCREMENT;
				mops[i] = M_SEP;
				nmods--;
			} else {	/* no modify op: invalid LDIF */
				fprintf( stderr, _("%s: modify operation type is missing at"
					" line %d, entry \"%s\"\n"),
					prog, linenum+i, dn );
				rc = LDAP_PARAM_ERROR;
				goto leave;
			}
			bv = vals[i];
		} else if ( expect_sep && BER_BVISEMPTY( btype+i )) {
			mops[i] = M_SEP;
			expect_sep = 0;
			expect_modop = 1;
			nmods--;
		} else {
			if ( !BV_CASEMATCH( btype+i, &bv )) {
				fprintf( stderr, _("%s: wrong attributeType at"
					" line %d, entry \"%s\"\n"),
					prog, linenum+i, dn );
				rc = LDAP_PARAM_ERROR;
				goto leave;
			}
			mops[i] = modop;
			/* If prev op was deferred and matches this type,
			 * clear the flag
			 */
			if ( (mops[i-1] & LDAP_MOD_BVALUES)
				&& BV_CASEMATCH( btype+i, btype+i-1 ))
			{
				mops[i-1] = M_SEP;
				nmods--;
			}
		}
	}

#if 0	/* we should faithfully encode the LDIF, not combine */
	/* Make sure all modops with multiple values are contiguous */
	for (i=idn; i<lines; i++) {
		if ( mops[i] == M_SEP )
			continue;
		for (j=i+1; j<lines; j++) {
			if ( mops[j] == M_SEP || mops[i] != mops[j] )
				continue;
			if ( BV_CASEMATCH( btype+i, btype+j )) {
				nmods--;
				/* out of order, move intervening attributes down */
				if ( j != i+1 ) {
					int c;
					struct berval bv;
					char fv;

					c = mops[j];
					bv = vals[j];
					fv = freeval[j];
					for (k=j; k>i; k--) {
						btype[k] = btype[k-1];
						vals[k] = vals[k-1];
						freeval[k] = freeval[k-1];
						mops[k] = mops[k-1];
					}
					k++;
					btype[k] = btype[i];
					vals[k] = bv;
					freeval[k] = fv;
					mops[k] = c;
				}
				i++;
			}
		}
	}
#endif

	/* Allocate space for array of mods, array of pointers to mods,
	 * and array of pointers to values, allowing for NULL terminators
	 * for the pointer arrays...
	 */
	lm = ber_memalloc( nmods * sizeof(LDAPMod) +
		(nmods+1) * sizeof(LDAPMod*) +
		(lines + nmods - idn) * sizeof(struct berval *));
	pmods = (LDAPMod **)(lm+nmods);
	bvl = (struct berval **)(pmods+nmods+1);

	j = 0;
	k = -1;
	BER_BVZERO(&bv);
	mops[idn-1] = M_SEP;
	for (i=idn; i<lines; i++) {
		if ( mops[i] == M_SEP )
			continue;
		if ( mops[i] != mops[i-1] || !BV_CASEMATCH( btype+i, &bv )) {
			bvl[k++] = NULL;
			bv = btype[i];
			lm[j].mod_op = mops[i] | LDAP_MOD_BVALUES;
			lm[j].mod_type = bv.bv_val;
			if ( mops[i] & LDAP_MOD_BVALUES ) {
				lm[j].mod_bvalues = NULL;
			} else {
				lm[j].mod_bvalues = bvl+k;
			}
			pmods[j] = lm+j;
			j++;
		}
		bvl[k++] = vals+i;
	}
	bvl[k] = NULL;
	pmods[j] = NULL;

doit:
	/* If default controls are set (as with -M option) and controls are
	   specified in the LDIF file, we must add the default controls to
	   the list of controls sent with the ldap operation.
	*/
	if ( rc == 0 ) {
		if (pctrls) {
			LDAPControl **defctrls = NULL;   /* Default server controls */
			LDAPControl **newctrls = NULL;
			ldap_get_option(ld, LDAP_OPT_SERVER_CONTROLS, &defctrls);
			if (defctrls) {
				int npc=0;                       /* Num of LDIF controls */
				int ndefc=0;                     /* Num of default controls */
				while (pctrls[npc]) npc++;       /* Count LDIF controls */
				while (defctrls[ndefc]) ndefc++; /* Count default controls */
				newctrls = ber_memrealloc(pctrls,
					(npc+ndefc+1)*sizeof(LDAPControl*));

				if (newctrls == NULL) {
					rc = LDAP_NO_MEMORY;
				} else {
					int i;
					pctrls = newctrls;
					for (i=npc; i<npc+ndefc; i++) {
						pctrls[i] = ldap_control_dup(defctrls[i-npc]);
						if (pctrls[i] == NULL) {
							rc = LDAP_NO_MEMORY;
							break;
						}
					}
					pctrls[npc+ndefc] = NULL;
				}
				ldap_controls_free(defctrls);  /* Must be freed by library */
			}
		}
	}

	if ( rc == 0 ) {
		if ( delete_entry ) {
			rc = dodelete( dn, pctrls );
		} else if ( newrdn != NULL ) {
			rc = dorename( dn, newrdn, newsup, deleteoldrdn, pctrls );
		} else {
			rc = domodify( dn, pmods, pctrls, new_entry );
		}

		if ( rc == LDAP_SUCCESS ) {
			rc = 0;
		}
	}

leave:
    if (pctrls != NULL) {
    	ldap_controls_free( pctrls );
	}
	if ( lm != NULL ) {
		ber_memfree( lm );
	}
	if ( mops != NULL ) {
		ber_memfree( mops );
	}
	for (i=lines-1; i>=0; i--)
		if ( freeval[i] ) ber_memfree( vals[i].bv_val );
	ber_memfree( btype );

	return( rc );
}
Beispiel #15
0
int
main( int argc, char **argv )
{
	char		*rbuf = NULL, *rejbuf = NULL;
	FILE		*rejfp;
	struct LDIFFP *ldiffp, ldifdummy = {0};
	char		*matched_msg, *error_msg;
	int		rc, retval;
	int		len;
	int		i = 0;
	int		lineno, nextline = 0, lmax = 0;
	LDAPControl	c[1];

	prog = lutil_progname( "ldapmodify", argc, argv );

	/* strncmp instead of strcmp since NT binaries carry .exe extension */
	ldapadd = ( strncasecmp( prog, "ldapadd", sizeof("ldapadd")-1 ) == 0 );

	tool_init( ldapadd ? TOOL_ADD : TOOL_MODIFY );

	tool_args( argc, argv );

	if ( argc != optind ) usage();

	if ( rejfile != NULL ) {
		if (( rejfp = fopen( rejfile, "w" )) == NULL ) {
			perror( rejfile );
			return( EXIT_FAILURE );
		}
	} else {
		rejfp = NULL;
	}

	if ( infile != NULL ) {
		if (( ldiffp = ldif_open( infile, "r" )) == NULL ) {
			perror( infile );
			return( EXIT_FAILURE );
		}
	} else {
		ldifdummy.fp = stdin;
		ldiffp = &ldifdummy;
	}

	if ( debug ) ldif_debug = debug;

	ld = tool_conn_setup( dont, 0 );

	if ( !dont ) {
		if ( pw_file || want_bindpw ) {
			if ( pw_file ) {
				rc = lutil_get_filed_password( pw_file, &passwd );
				if( rc ) return EXIT_FAILURE;
			} else {
				passwd.bv_val = getpassphrase( _("Enter LDAP Password: "******"ldap_txn_start_s", rc, NULL, NULL, NULL, NULL );
			if( txn > 1 ) return EXIT_FAILURE;
			txn = 0;
		}
	}
#endif

	if ( 0
#ifdef LDAP_X_TXN
		|| txn
#endif
		)
	{
#ifdef LDAP_X_TXN
		if( txn ) {
			c[i].ldctl_oid = LDAP_CONTROL_X_TXN_SPEC;
			c[i].ldctl_value = *txn_id;
			c[i].ldctl_iscritical = 1;
			i++;
		}
#endif
	}

	tool_server_controls( ld, c, i );

	rc = 0;
	retval = 0;
	lineno = 1;
	while (( rc == 0 || contoper ) && ldif_read_record( ldiffp, &nextline,
		&rbuf, &lmax ))
	{
		if ( rejfp ) {
			len = strlen( rbuf );
			if (( rejbuf = (char *)ber_memalloc( len+1 )) == NULL ) {
				perror( "malloc" );
				exit( EXIT_FAILURE );
			}
			memcpy( rejbuf, rbuf, len+1 );
		}

		rc = process_ldif_rec( rbuf, lineno );
		lineno = nextline+1;

		if ( rc ) retval = rc;
		if ( rc && rejfp ) {
			fprintf(rejfp, _("# Error: %s (%d)"), ldap_err2string(rc), rc);

			matched_msg = NULL;
			ldap_get_option(ld, LDAP_OPT_MATCHED_DN, &matched_msg);
			if ( matched_msg != NULL ) {
				if ( *matched_msg != '\0' ) {
					fprintf( rejfp, _(", matched DN: %s"), matched_msg );
				}
				ldap_memfree( matched_msg );
			}

			error_msg = NULL;
			ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &error_msg);
			if ( error_msg != NULL ) {
				if ( *error_msg != '\0' ) {
					fprintf( rejfp, _(", additional info: %s"), error_msg );
				}
				ldap_memfree( error_msg );
			}
			fprintf( rejfp, "\n%s\n", rejbuf );
		}

		if (rejfp) ber_memfree( rejbuf );
	}
	ber_memfree( rbuf );

#ifdef LDAP_X_TXN
	if( retval == 0 && txn ) {
		rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL );
		if ( rc != LDAP_OPT_SUCCESS ) {
			fprintf( stderr, "Could not unset controls for ldap_txn_end\n");
		}

		/* create transaction */
		rc = ldap_txn_end_s( ld, !txnabort, txn_id, NULL, NULL, NULL );
		if( rc != LDAP_SUCCESS ) {
			tool_perror( "ldap_txn_end_s", rc, NULL, NULL, NULL, NULL );
			retval = rc;
		}
	}
#endif

	if ( !dont ) {
		tool_unbind( ld );
	}

	if ( rejfp != NULL ) {
		fclose( rejfp );
	}

	tool_destroy();
	return( retval );
}
Beispiel #16
0
/*
 * avl_insert -- insert a node containing data data into the avl tree
 * with root root.  fcmp is a function to call to compare the data portion
 * of two nodes.  it should take two arguments and return <, >, or == 0,
 * depending on whether its first argument is <, >, or == its second
 * argument (like strcmp, e.g.).  fdup is a function to call when a duplicate
 * node is inserted.  it should return 0, or -1 and its return value
 * will be the return value from avl_insert in the case of a duplicate node.
 * the function will be called with the original node's data as its first
 * argument and with the incoming duplicate node's data as its second
 * argument.  this could be used, for example, to keep a count with each
 * node.
 *
 * NOTE: this routine may malloc memory
 */
int
avl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup )
{
    Avlnode *t, *p, *s, *q, *r;
    int a, cmp, ncmp;

	if ( *root == NULL ) {
		if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
			return( -1 );
		}
		r->avl_link[0] = r->avl_link[1] = NULL;
		r->avl_data = data;
		r->avl_bf = EH;
		*root = r;

		return( 0 );
	}

    t = NULL;
    s = p = *root;

	/* find insertion point */
    while (1) {
		cmp = fcmp( data, p->avl_data );
		if ( cmp == 0 )
			return (*fdup)( p->avl_data, data );

		cmp = (cmp > 0);
		q = p->avl_link[cmp];
		if (q == NULL) {
			/* insert */
			if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
				return( -1 );
			}
			q->avl_link[0] = q->avl_link[1] = NULL;
			q->avl_data = data;
			q->avl_bf = EH;

			p->avl_link[cmp] = q;
			break;
		} else if ( q->avl_bf ) {
			t = p;
			s = q;
		}
		p = q;
    }

    /* adjust balance factors */
    cmp = fcmp( data, s->avl_data ) > 0;
	r = p = s->avl_link[cmp];
	a = avl_bfs[cmp];

	while ( p != q ) {
		cmp = fcmp( data, p->avl_data ) > 0;
		p->avl_bf = avl_bfs[cmp];
		p = p->avl_link[cmp];
	}

	/* checks and balances */

	if ( s->avl_bf == EH ) {
		s->avl_bf = a;
		return 0;
	} else if ( s->avl_bf == -a ) {
		s->avl_bf = EH;
		return 0;
    } else if ( s->avl_bf == a ) {
		cmp = (a > 0);
		ncmp = !cmp;
		if ( r->avl_bf == a ) {
			/* single rotation */
			p = r;
			s->avl_link[cmp] = r->avl_link[ncmp];
			r->avl_link[ncmp] = s;
			s->avl_bf = 0;
			r->avl_bf = 0;
		} else if ( r->avl_bf == -a ) {
			/* double rotation */
			p = r->avl_link[ncmp];
			r->avl_link[ncmp] = p->avl_link[cmp];
			p->avl_link[cmp] = r;
			s->avl_link[cmp] = p->avl_link[ncmp];
			p->avl_link[ncmp] = s;

			if ( p->avl_bf == a ) {
				s->avl_bf = -a;
				r->avl_bf = 0;
			} else if ( p->avl_bf == -a ) {
				s->avl_bf = 0;
				r->avl_bf = a;
			} else {
				s->avl_bf = 0;
				r->avl_bf = 0;
			}
			p->avl_bf = 0;
		}
		/* Update parent */
		if ( t == NULL )
			*root = p;
		else if ( s == t->avl_right )
			t->avl_right = p;
		else
			t->avl_left = p;
    }

  return 0;
}
Beispiel #17
0
static int
aa_operational( Operation *op, SlapReply *rs )
{
	Attribute		*a, **ap;
	AccessControlState	acl_state = ACL_STATE_INIT;
	struct berval		*v;
	AttributeType		**atp = NULL;
	ObjectClass		**ocp = NULL;

#define	GOT_NONE	(0x0U)
#define	GOT_C		(0x1U)
#define	GOT_CE		(0x2U)
#define	GOT_A		(0x4U)
#define	GOT_AE		(0x8U)
#define	GOT_ALL		(GOT_C|GOT_CE|GOT_A|GOT_AE)
	int		got = GOT_NONE;

	/* only add if requested */
	if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) {
		got = GOT_ALL;

	} else {
		if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) {
			got |= GOT_C;
		}

		if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) {
			got |= GOT_CE;
		}

		if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) {
			got |= GOT_A;
		}

		if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) {
			got |= GOT_AE;
		}
	}

	if ( got == GOT_NONE ) {
		return SLAP_CB_CONTINUE;
	}

	/* shouldn't be called without an entry; please check */
	assert( rs->sr_entry != NULL );

	for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next )
		/* go to last */ ;

	/* see caveats; this is not guaranteed for all backends */
	a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
	if ( a == NULL ) {
		goto do_oc;
	}

	/* if client has no access to objectClass attribute; don't compute */
	if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass,
				NULL, ACL_READ, &acl_state ) )
	{
		return SLAP_CB_CONTINUE;
	}

	for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) {
		ObjectClass	*oc = oc_bvfind( v );

		assert( oc != NULL );

		/* if client has no access to specific value, don't compute */
		if ( !access_allowed( op, rs->sr_entry,
			slap_schema.si_ad_objectClass,
			&oc->soc_cname, ACL_READ, &acl_state ) )
		{
			continue;
		}

		aa_add_oc( oc, &ocp, &atp );

		if ( oc->soc_sups ) {
			int i;

			for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) {
				aa_add_oc( oc->soc_sups[ i ], &ocp, &atp );
			}
		}
	}

	ch_free( ocp );

	if ( atp != NULL ) {
		BerVarray	bv_allowed = NULL,
				bv_effective = NULL;
		int		i, ja = 0, je = 0;

		for ( i = 0; atp[ i ] != NULL; i++ )
			/* just count */ ;
	
		if ( got & GOT_A ) {
			bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}
		if ( got & GOT_AE ) {
			bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}

		for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) {
			if ( got & GOT_A ) {
				ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname );
				ja++;
			}

			if ( got & GOT_AE ) {
				AttributeDescription	*ad = NULL;
				const char		*text = NULL;
	
				if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) {
					/* log? */
					continue;
				}

				if ( access_allowed( op, rs->sr_entry,
					ad, NULL, ACL_WRITE, NULL ) )
				{
					ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname );
					je++;
				}
			}
		}

		ch_free( atp );

		if ( ( got & GOT_A ) && ja > 0 ) {
			BER_BVZERO( &bv_allowed[ ja ] );
			*ap = attr_alloc( ad_allowedAttributes );
			(*ap)->a_vals = bv_allowed;
			(*ap)->a_nvals = bv_allowed;
			(*ap)->a_numvals = ja;
			ap = &(*ap)->a_next;
		}

		if ( ( got & GOT_AE ) && je > 0 ) {
			BER_BVZERO( &bv_effective[ je ] );
			*ap = attr_alloc( ad_allowedAttributesEffective );
			(*ap)->a_vals = bv_effective;
			(*ap)->a_nvals = bv_effective;
			(*ap)->a_numvals = je;
			ap = &(*ap)->a_next;
		}

		*ap = NULL;
	}

do_oc:;
	if ( ( got & GOT_C ) || ( got & GOT_CE ) ) {
		BerVarray	bv_allowed = NULL,
				bv_effective = NULL;
		int		i, ja = 0, je = 0;

		ObjectClass	*oc;

		for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) {
			/* we can only add AUXILIARY objectClasses */
			if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
				continue;
			}

			i++;
		}

		if ( got & GOT_C ) {
			bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}
		if ( got & GOT_CE ) {
			bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}

		for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) {
			/* we can only add AUXILIARY objectClasses */
			if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
				continue;
			}

			if ( got & GOT_C ) {
				ber_dupbv( &bv_allowed[ ja ], &oc->soc_cname );
				ja++;
			}

			if ( got & GOT_CE ) {
				if ( !access_allowed( op, rs->sr_entry,
					slap_schema.si_ad_objectClass,
					&oc->soc_cname, ACL_WRITE, NULL ) )
				{
					goto done_ce;
				}

				if ( oc->soc_required ) {
					for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) {
						AttributeDescription	*ad = NULL;
						const char		*text = NULL;
	
						if ( slap_bv2ad( &oc->soc_required[ i ]->sat_cname, &ad, &text ) ) {
							/* log? */
							continue;
						}

						if ( !access_allowed( op, rs->sr_entry,
							ad, NULL, ACL_WRITE, NULL ) )
						{
							goto done_ce;
						}
					}
				}

				ber_dupbv( &bv_effective[ je ], &oc->soc_cname );
				je++;
			}
done_ce:;
		}

		if ( ( got & GOT_C ) && ja > 0 ) {
			BER_BVZERO( &bv_allowed[ ja ] );
			*ap = attr_alloc( ad_allowedChildClasses );
			(*ap)->a_vals = bv_allowed;
			(*ap)->a_nvals = bv_allowed;
			(*ap)->a_numvals = ja;
			ap = &(*ap)->a_next;
		}

		if ( ( got & GOT_CE ) && je > 0 ) {
			BER_BVZERO( &bv_effective[ je ] );
			*ap = attr_alloc( ad_allowedChildClassesEffective );
			(*ap)->a_vals = bv_effective;
			(*ap)->a_nvals = bv_effective;
			(*ap)->a_numvals = je;
			ap = &(*ap)->a_next;
		}

		*ap = NULL;
	}

	return SLAP_CB_CONTINUE;
}
Beispiel #18
0
/* Get a password from a file. */
int
lutil_get_filed_password(
	const char *filename,
	struct berval *passwd )
{
	size_t nread, nleft, nr;
	FILE *f = fopen( filename, "r" );

	if( f == NULL ) {
		perror( filename );
		return -1;
	}

	passwd->bv_val = NULL;
	passwd->bv_len = 4096;

#ifdef HAVE_FSTAT
	{
		struct stat sb;
		if ( fstat( fileno( f ), &sb ) == 0 ) {
			if( sb.st_mode & 006 ) {
				fprintf( stderr, _("Warning: Password file %s"
					" is publicly readable/writeable\n"),
					filename );
			}

			if ( sb.st_size )
				passwd->bv_len = sb.st_size;
		}
	}
#endif /* HAVE_FSTAT */

	passwd->bv_val = (char *) ber_memalloc( passwd->bv_len + 1 );
	if( passwd->bv_val == NULL ) {
		perror( filename );
		return -1;
	}

	nread = 0;
	nleft = passwd->bv_len;
	do {
		if( nleft == 0 ) {
			/* double the buffer size */
			char *p = (char *) ber_memrealloc( passwd->bv_val,
				2 * passwd->bv_len + 1 );
			if( p == NULL ) {
				ber_memfree( passwd->bv_val );
				passwd->bv_val = NULL;
				passwd->bv_len = 0;
				return -1;
			}
			nleft = passwd->bv_len;
			passwd->bv_len *= 2;
			passwd->bv_val = p;
		}

		nr = fread( &passwd->bv_val[nread], 1, nleft, f );

		if( nr < nleft && ferror( f ) ) {
			ber_memfree( passwd->bv_val );
			passwd->bv_val = NULL;
			passwd->bv_len = 0;
			return -1;
		}

		nread += nr;
		nleft -= nr;
	} while ( !feof(f) );

	passwd->bv_len = nread;
	passwd->bv_val[nread] = '\0';

	fclose( f );
	return 0;
}
	int
check_password (char *pPasswd, char **ppErrStr, Entry *pEntry)
{

	char *szErrStr = (char *) ber_memalloc(MEM_INIT_SZ);
	int  mem_len = MEM_INIT_SZ;

	int nLen;
	int nLower = 0;
	int nUpper = 0;
	int nDigit = 0;
	int nPunct = 0;
	int min_lower = 0;
	int min_upper = 0;
	int min_digit = 0;
	int min_punct = 0;
  int max_consecutive_per_class = 0;
	int nQuality = 0;
	int i;

	/* Set a sensible default to keep original behaviour. */
	int min_quality = DEFAULT_QUALITY;
	int use_cracklib = DEFAULT_CRACKLIB;

	nLen = strlen (pPasswd);

  if (read_config_file() == -1) {
    syslog(LOG_ERR, "Warning: Could not read values from config file %s. Using defaults.", CONFIG_FILE);
#if defined(LDEBUG)
    printf("Error: Could not read values from config file %s\n", CONFIG_FILE);
#endif
  }

#if defined(LDEBUG) || defined(DEBUG) 
  print_config_entries();
#endif

	min_quality = get_config_entry_int("min_points");
	use_cracklib = get_config_entry_int("use_cracklib");
	min_upper = get_config_entry_int("min_upper");
	min_lower = get_config_entry_int("min_lower");
	min_digit = get_config_entry_int("min_digit");
	min_punct = get_config_entry_int("min_punct");
  max_consecutive_per_class = get_config_entry_int("max_consecutive_per_class");

  /* Check Max Consecutive Per Class first since this has the most likelihood
   * of being wrong.
   */

  if ( max_consecutive_per_class != 0 ) {
    char prev_type = '\0';
    char this_type = ' ';
    i = 0;
    int consec_chars = 0;
    for ( i = 0; i < nLen; i++ ) {
      if ( islower(pPasswd[i]) ) {
        this_type = 'l';
      }
      else if ( isupper(pPasswd[i]) ) {
        this_type = 'u';
      }
      else if ( isdigit(pPasswd[i]) ) {
        this_type = 'd';
      }
      else if ( ispunct(pPasswd[i]) ) {
        this_type = 'p';
      }
      else {
        this_type = ' ';
      }
      if (this_type == prev_type) {
        ++consec_chars;
      } else if (i > 0) {
        consec_chars = 0;
      }
      prev_type = this_type;
      if ( consec_chars >= max_consecutive_per_class ) {
        mem_len = realloc_error_message(&szErrStr, mem_len,
          strlen(CONSEC_FAIL_SZ) +
          strlen(pEntry->e_name.bv_val));
        sprintf (szErrStr, CONSEC_FAIL_SZ, pEntry->e_name.bv_val);
        goto fail;
      }
    }
  }

	/** The password must have at least min_quality strength points with one
	 * point for the first occurrance of a lower, upper, digit and
	 * punctuation character
	 */

	for ( i = 0; i < nLen; i++ ) {

		//if ( nQuality >= min_quality ) break;

		if ( islower (pPasswd[i]) ) {
			min_lower--;
			if ( !nLower && (min_lower < 1)) {
				nLower = 1; nQuality++;
#if defined(DEBUG)
				syslog(LOG_NOTICE, "check_password: Found lower character - quality raise %d", nQuality);
#endif
#if defined(LDEBUG)
  printf("check_password: Found lower character - quality raise %d\n", nQuality);
#endif
			}
			continue;
		}

		if ( isupper (pPasswd[i]) ) {
			min_upper--;
			if ( !nUpper && (min_upper < 1)) {
				nUpper = 1; nQuality++;
#if defined(DEBUG)
				syslog(LOG_NOTICE, "check_password: Found upper character - quality raise %d", nQuality);
#endif
#if defined(LDEBUG)
  printf("check_password: Found upper character - quality raise %d\n", nQuality);
#endif
			}
			continue;
		}

		if ( isdigit (pPasswd[i]) ) {
			min_digit--;
			if ( !nDigit && (min_digit < 1)) {
				nDigit = 1; nQuality++;
#if defined(DEBUG)
				syslog(LOG_NOTICE, "check_password: Found digit character - quality raise %d", nQuality);
#endif
#if defined(LDEBUG)
  printf("check_password: Found digit character - quality raise %d\n", nQuality);
#endif
			}
			continue;
		}

		if ( ispunct (pPasswd[i]) ) {
			min_punct--;
			if ( !nPunct && (min_punct < 1)) {
				nPunct = 1; nQuality++;
#if defined(DEBUG)
				syslog(LOG_NOTICE, "check_password: Found punctuation character - quality raise %d", nQuality);
#endif
#if defined(LDEBUG)
  printf("check_password: Found punctuation character - quality raise %d\n", nQuality);
#endif
			}
			continue;
		}
	}

  /*
   * If you have a required field, then it should be required in the strength
   * checks. 
   */

  if ( 
        (min_lower > 0 ) || 
        (min_upper > 0 ) ||
        (min_digit > 0 ) ||
        (min_punct > 0 ) ||
        (nQuality < min_quality) 
    ) {
		mem_len = realloc_error_message(&szErrStr, mem_len,
				strlen(PASSWORD_QUALITY_SZ) +
				strlen(pEntry->e_name.bv_val) + 2);
		sprintf (szErrStr, PASSWORD_QUALITY_SZ, pEntry->e_name.bv_val,
				nQuality, min_quality);
		goto fail;
	}

#ifdef HAVE_CRACKLIB

	/** Check password with cracklib */

	if ( use_cracklib > 0 ) {
		int   j = 0;
		FILE* fp;
		char  filename[FILENAME_MAXLEN];
		char  const* ext[] = { "hwm", "pwd", "pwi" };
		int   nErr = 0;

		/**
		 * Silently fail when cracklib wordlist is not found
		 */

		for ( j = 0; j < 3; j++ ) {

			snprintf (filename, FILENAME_MAXLEN - 1, "%s.%s", \
					CRACKLIB_DICTPATH, ext[j]);

			if (( fp = fopen ( filename, "r")) == NULL ) {

				nErr = 1;
				break;

			} else {

				fclose (fp);

			}
		}

		char *r;
		if ( nErr  == 0) {

			r = (char *) FascistCheck (pPasswd, CRACKLIB_DICTPATH);
			if ( r != NULL ) {
				mem_len = realloc_error_message(&szErrStr, mem_len,
						strlen(BAD_PASSWORD_SZ) +
						strlen(pEntry->e_name.bv_val) +
						strlen(r));
				sprintf (szErrStr, BAD_PASSWORD_SZ, pEntry->e_name.bv_val, r);
				goto fail;
			}
		}
	}

	else {
#if defined(DEBUG)
		syslog(LOG_NOTICE, "check_password: Cracklib verification disabled by configuration");
#endif
#if defined(LDEBUG)
		printf("check_password: Cracklib verification disabled by configuration");
#endif
	}

#endif

#if defined(LDEBUG) || defined(DEBUG) 
  print_config_entries();
#endif
  dealloc_config_entries();
	*ppErrStr = strdup ("");
	ber_memfree(szErrStr);
	return (LDAP_SUCCESS);

fail:
  dealloc_config_entries();
	*ppErrStr = strdup (szErrStr);
	ber_memfree(szErrStr);
	return (EXIT_FAILURE);

}
Beispiel #20
0
static int slap_open_listener(
	const char* url,
	int *listeners,
	int *cur
	)
{
	int	num, tmp, rc;
	Listener l;
	Listener *li;
	LDAPURLDesc *lud;
	unsigned short port;
	int err, addrlen = 0;
	struct sockaddr **sal, **psal;
	int socktype = SOCK_STREAM;	/* default to COTS */

#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
	/*
	 * use safe defaults
	 */
	int	crit = 1;
#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */

	rc = ldap_url_parse( url, &lud );

	if( rc != LDAP_URL_SUCCESS ) {
#ifdef NEW_LOGGING
		LDAP_LOG( CONNECTION, ERR, 
			"slap_open_listener: listen URL \"%s\" parse error %d\n",
			url, rc , 0 );
#else
		Debug( LDAP_DEBUG_ANY,
			"daemon: listen URL \"%s\" parse error=%d\n",
			url, rc, 0 );
#endif
		return rc;
	}

	l.sl_url.bv_val = NULL;
	l.sl_is_mute = 0;

#ifndef HAVE_TLS
	if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
#ifdef NEW_LOGGING
		LDAP_LOG( CONNECTION, INFO, 
			   "slap_open_listener: TLS is not supported (%s)\n", url, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY,
			"daemon: TLS not supported (%s)\n",
			url, 0, 0 );
#endif
		ldap_free_urldesc( lud );
		return -1;
	}

	if(! lud->lud_port ) {
		lud->lud_port = LDAP_PORT;
	}

#else
	l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );

	if(! lud->lud_port ) {
		lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT;
	}
#endif

	port = (unsigned short) lud->lud_port;

	tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme);
	if ( tmp == LDAP_PROTO_IPC ) {
#ifdef LDAP_PF_LOCAL
		if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
			err = slap_get_listener_addresses(LDAPI_SOCK, 0, &sal);
		} else {
			err = slap_get_listener_addresses(lud->lud_host, 0, &sal);
		}
#else

#ifdef NEW_LOGGING
		LDAP_LOG( CONNECTION, INFO, 
			"slap_open_listener: URL scheme is not supported: %s\n", url, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s",
			url, 0, 0);
#endif
		ldap_free_urldesc( lud );
		return -1;
#endif
	} else {
		if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
			|| strcmp(lud->lud_host, "*") == 0 )
		{
			err = slap_get_listener_addresses(NULL, port, &sal);
		} else {
			err = slap_get_listener_addresses(lud->lud_host, port, &sal);
		}
	}
#ifdef LDAP_CONNECTIONLESS
	l.sl_is_udp = ( tmp == LDAP_PROTO_UDP );
#endif

#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
	if ( lud->lud_exts ) {
		err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit );
	} else {
		l.sl_perms = S_IRWXU;
	}
#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */

	ldap_free_urldesc( lud );
	if ( err ) {
		return -1;
	}

	/* If we got more than one address returned, we need to make space
	 * for it in the slap_listeners array.
	 */
	for ( num=0; sal[num]; num++ );
	if ( num > 1 ) {
		*listeners += num-1;
		slap_listeners = ch_realloc( slap_listeners, (*listeners + 1) * sizeof(Listener *) );
	}

	psal = sal;
	while ( *sal != NULL ) {
		switch( (*sal)->sa_family ) {
		case AF_INET:
#ifdef LDAP_PF_INET6
		case AF_INET6:
#endif
#ifdef LDAP_PF_LOCAL
		case AF_LOCAL:
#endif
			break;
		default:
			sal++;
			continue;
		}
#ifdef LDAP_CONNECTIONLESS
		if( l.sl_is_udp ) socktype = SOCK_DGRAM;
#endif
		l.sl_sd = socket( (*sal)->sa_family, socktype, 0);
		if ( l.sl_sd == AC_SOCKET_INVALID ) {
			int err = sock_errno();
#ifdef NEW_LOGGING
			LDAP_LOG( CONNECTION, ERR, 
				"slap_open_listener: socket() failed errno=%d (%s)\n",
				err, sock_errstr(err), 0 );
#else
			Debug( LDAP_DEBUG_ANY,
				"daemon: socket() failed errno=%d (%s)\n", err,
				sock_errstr(err), 0 );
#endif
			sal++;
			continue;
		}
#ifndef HAVE_WINSOCK
		if ( l.sl_sd >= dtblsize ) {
#ifdef NEW_LOGGING
			LDAP_LOG( CONNECTION, ERR, 
				"slap_open_listener: listener descriptor %ld is too "
				"great %ld\n", (long)l.sl_sd, (long)dtblsize, 0 );
#else
			Debug( LDAP_DEBUG_ANY,
			       "daemon: listener descriptor %ld is too great %ld\n",
			       (long) l.sl_sd, (long) dtblsize, 0 );
#endif
			tcp_close( l.sl_sd );
			sal++;
			continue;
		}
#endif
#ifdef LDAP_PF_LOCAL
		if ( (*sal)->sa_family == AF_LOCAL ) {
			unlink ( ((struct sockaddr_un *)*sal)->sun_path );
		} else
#endif
		{
#ifdef SO_REUSEADDR
			/* enable address reuse */
			tmp = 1;
			rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
					 (char *) &tmp, sizeof(tmp) );
			if ( rc == AC_SOCKET_ERROR ) {
				int err = sock_errno();
#ifdef NEW_LOGGING
				LDAP_LOG( CONNECTION, INFO, 
					"slap_open_listener: setsockopt( %ld, SO_REUSEADDR ) "
					"failed errno %d (%s)\n", (long)l.sl_sd, err, 
					sock_errstr(err) );
#else
				Debug( LDAP_DEBUG_ANY,
				       "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
				       (long) l.sl_sd, err, sock_errstr(err) );
#endif
			}
#endif
		}

		switch( (*sal)->sa_family ) {
		case AF_INET:
			addrlen = sizeof(struct sockaddr_in);
			break;
#ifdef LDAP_PF_INET6
		case AF_INET6:
#ifdef IPV6_V6ONLY
			/* Try to use IPv6 sockets for IPv6 only */
			tmp = 1;
			rc = setsockopt( l.sl_sd, IPPROTO_IPV6, IPV6_V6ONLY,
					 (char *) &tmp, sizeof(tmp) );
			if ( rc == AC_SOCKET_ERROR ) {
				int err = sock_errno();
#ifdef NEW_LOGGING
				LDAP_LOG( CONNECTION, INFO,
					   "slap_open_listener: setsockopt( %ld, IPV6_V6ONLY ) failed errno %d (%s)\n",
					   (long)l.sl_sd, err, sock_errstr(err) );
#else
				Debug( LDAP_DEBUG_ANY,
				       "slapd(%ld): setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n",
				       (long) l.sl_sd, err, sock_errstr(err) );
#endif
			}
#endif
			addrlen = sizeof(struct sockaddr_in6);
			break;
#endif
#ifdef LDAP_PF_LOCAL
		case AF_LOCAL:
			addrlen = sizeof(struct sockaddr_un);
			break;
#endif
		}

		if (bind(l.sl_sd, *sal, addrlen)) {
			err = sock_errno();
#ifdef NEW_LOGGING
		LDAP_LOG( CONNECTION, INFO, 
			"slap_open_listener: bind(%ld) failed errno=%d (%s)\n",
			(long)l.sl_sd, err, sock_errstr(err) );
#else
		Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
		       (long) l.sl_sd, err, sock_errstr(err) );
#endif
			tcp_close( l.sl_sd );
			sal++;
			continue;
		}

	switch ( (*sal)->sa_family ) {
#ifdef LDAP_PF_LOCAL
	case AF_LOCAL: {
		char *addr = ((struct sockaddr_un *)*sal)->sun_path;
		if ( chmod( addr, l.sl_perms ) < 0 && crit ) {
			int err = sock_errno();
#ifdef NEW_LOGGING
			LDAP_LOG( CONNECTION, INFO, 
				"slap_open_listener: fchmod(%ld) failed errno=%d (%s)\n",
				(long)l.sl_sd, err, sock_errstr(err) );
#else
			Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
			       (long) l.sl_sd, err, sock_errstr(err) );
#endif
			tcp_close( l.sl_sd );
			slap_free_listener_addresses(psal);
			return -1;
		}
		l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1;
		l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 );
		snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, 
				"PATH=%s", addr );
	} break;
#endif /* LDAP_PF_LOCAL */

	case AF_INET: {
		char *s;
#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
		char addr[INET_ADDRSTRLEN];
		inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
			   addr, sizeof(addr) );
		s = addr;
#else
		s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr );
#endif
		port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port );
		l.sl_name.bv_val = ber_memalloc( sizeof("IP=255.255.255.255:65535") );
		snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"),
			"IP=%s:%d",
			 s != NULL ? s : SLAP_STRING_UNKNOWN, port );
		l.sl_name.bv_len = strlen( l.sl_name.bv_val );
	} break;

#ifdef LDAP_PF_INET6
	case AF_INET6: {
		char addr[INET6_ADDRSTRLEN];
		inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
			   addr, sizeof addr);
		port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port );
		l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535");
		l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len );
		snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d", 
				addr, port );
		l.sl_name.bv_len = strlen( l.sl_name.bv_val );
	} break;
#endif /* LDAP_PF_INET6 */

	default:
#ifdef NEW_LOGGING
		LDAP_LOG( CONNECTION, INFO, 
			"slap_open_listener: unsupported address family (%d)\n",
			(int)(*sal)->sa_family, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
			(int) (*sal)->sa_family, 0, 0 );
#endif
		break;
	}

	AC_MEMCPY(&l.sl_sa, *sal, addrlen);
	ber_str2bv( url, 0, 1, &l.sl_url);
	li = ch_malloc( sizeof( Listener ) );
	*li = l;
	slap_listeners[*cur] = li;
	(*cur)++;
	sal++;

	} /* while ( *sal != NULL ) */

	slap_free_listener_addresses(psal);

	if ( l.sl_url.bv_val == NULL )
	{
#ifdef NEW_LOGGING
		LDAP_LOG( CONNECTION, RESULTS, 
			"slap_open_listener: failed on %s\n", url, 0, 0 );
#else
		Debug( LDAP_DEBUG_TRACE,
			"slap_open_listener: failed on %s\n", url, 0, 0 );
#endif
		return -1;
	}

#ifdef NEW_LOGGING
	LDAP_LOG( CONNECTION, RESULTS, 
		"slap_open_listener: daemon initialized %s\n",
		l.sl_url.bv_val, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
		l.sl_url.bv_val, 0, 0 );
#endif
	return 0;
}
Beispiel #21
0
static void
addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
{
    LDAPMod		**pmods;
    int			i, j;
    struct berval	*bvp;

    pmods = *pmodsp;
    modop |= LDAP_MOD_BVALUES;

    i = 0;
    if ( pmods != NULL ) {
		for ( ; pmods[ i ] != NULL; ++i ) {
	    	if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
		    	pmods[ i ]->mod_op == modop ) {
				break;
	    	}
		}
    }

    if ( pmods == NULL || pmods[ i ] == NULL ) {
		if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
			sizeof( LDAPMod * ))) == NULL ) {
	    		tester_perror( "realloc", NULL );
	    		exit( EXIT_FAILURE );
		}
		*pmodsp = pmods;
		pmods[ i + 1 ] = NULL;
		if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
			== NULL ) {
	    		tester_perror( "calloc", NULL );
	    		exit( EXIT_FAILURE );
		}
		pmods[ i ]->mod_op = modop;
		if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
	    	tester_perror( "strdup", NULL );
	    	exit( EXIT_FAILURE );
		}
    }

    if ( value != NULL ) {
		j = 0;
		if ( pmods[ i ]->mod_bvalues != NULL ) {
	    	for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
				;
	    	}
		}
		if (( pmods[ i ]->mod_bvalues =
			(struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
			(j + 2) * sizeof( struct berval * ))) == NULL ) {
	    		tester_perror( "ber_memrealloc", NULL );
	    		exit( EXIT_FAILURE );
		}
		pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
		if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
			== NULL ) {
	    		tester_perror( "ber_memalloc", NULL );
	    		exit( EXIT_FAILURE );
		}
		pmods[ i ]->mod_bvalues[ j ] = bvp;

	    bvp->bv_len = vlen;
	    if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
			tester_perror( "malloc", NULL );
			exit( EXIT_FAILURE );
	    }
	    AC_MEMCPY( bvp->bv_val, value, vlen );
	    bvp->bv_val[ vlen ] = '\0';
    }
}