Пример #1
0
static int
_ger_parse_control (
	Slapi_PBlock *pb,
	char **subjectndn,
	int *iscritical,
	char **errbuf
	)
{
	LDAPControl **requestcontrols;
	struct berval *subjectber;
	BerElement *ber;
	size_t subjectndnlen = 0;
	char *orig = NULL;
	char *normed = NULL;

	if (NULL == subjectndn)
	{
		return LDAP_OPERATIONS_ERROR;
	}

	*subjectndn = NULL;

	/*
	 * Get the control
	 */
	slapi_pblock_get ( pb, SLAPI_REQCONTROLS, (void *) &requestcontrols );
	slapi_control_present ( requestcontrols,
							LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
							&subjectber,
							iscritical );
	if ( subjectber == NULL || subjectber->bv_val == NULL ||
		 subjectber->bv_len == 0 )
	{
		aclutil_str_append ( errbuf, "get-effective-rights: missing subject" );
		slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
                if (iscritical)
                    return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                else
                    return LDAP_INVALID_SYNTAX;
	}

	if ( strncasecmp ( "dn:", subjectber->bv_val, 3 ) == 0 )
	{
		/*
		 * This is a non-standard support to allow the subject being a plain
		 * or base64 encoding string. Hence users using -J option in
		 * ldapsearch don't have to do BER encoding for the subject.
		 */
		orig = slapi_ch_malloc ( subjectber->bv_len + 1 );
		strncpy ( orig, subjectber->bv_val, subjectber->bv_len );
		*(orig + subjectber->bv_len) = '\0';
	}
	else
	{
		ber = ber_init (subjectber);
		if ( ber == NULL )
		{
			aclutil_str_append ( errbuf, "get-effective-rights: ber_init failed for the subject" );
			slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
                        if (iscritical)
                            return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                        else
                            return LDAP_OPERATIONS_ERROR;
		}
		/* "a" means to allocate storage as needed for octet string */
		if ( ber_scanf (ber, "a", &orig) == LBER_ERROR )
		{
			aclutil_str_append ( errbuf, "get-effective-rights: invalid ber tag in the subject" );
			slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
			ber_free ( ber, 1 );
                        if (iscritical)
                            return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                        else
                            return LDAP_INVALID_SYNTAX;
		}
		ber_free ( ber, 1 );
	}

	/*
	 * The current implementation limits the subject to authorization ID
	 * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId"
	 * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous.
	 */
	subjectndnlen = orig ? strlen(orig) : 0;
	if ( NULL == orig || subjectndnlen < 3 || strncasecmp ( "dn:", orig, 3 ) != 0 )
	{
		aclutil_str_append ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
		slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
		slapi_ch_free_string(&orig);
                if (iscritical)
                    return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                else
                    return LDAP_INVALID_SYNTAX;
	}

	/* memmove is safe for overlapping copy */
	normed = slapi_create_dn_string("%s", orig + 3);
	if (NULL == normed) {
		aclutil_str_append (errbuf, "get-effective-rights: failed to normalize dn: ");
		aclutil_str_append (errbuf, orig);
		slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf);
		slapi_ch_free_string(&orig);
                if (iscritical)
                    return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;  /* RFC 4511 4.1.11 */
                else
                    return LDAP_INVALID_SYNTAX;
	}
	slapi_ch_free_string(&orig);
	*subjectndn = normed;
	slapi_dn_ignore_case(*subjectndn);
	return LDAP_SUCCESS;
}
Пример #2
0
/*
 * update multiple attribute values per _do_modify
 */
static int
_update_all_per_mod(Slapi_DN *entrySDN,      /* DN of the searched entry */
                    Slapi_Attr *attr,        /* referred attribute */
                    char *attrName,
                    Slapi_DN *origDN,        /* original DN that was modified */
                    char *newRDN,            /* new RDN from modrdn */
                    const char *newsuperior, /* new superior from modrdn */
                    Slapi_PBlock *mod_pb)
{
    Slapi_Mods *smods = NULL;
    char *newDN = NULL;
    char **dnParts = NULL;
    char *sval = NULL;
    char *newvalue = NULL;
    char *p = NULL;
    size_t dnlen = 0;
    int rc = 0;
    int nval = 0;

    slapi_attr_get_numvalues(attr, &nval);

    if (NULL == newRDN && NULL == newsuperior) {
        /* in delete mode */
        LDAPMod *mods[2];
        char *values_del[2];
        LDAPMod attribute1;

        /* delete old dn so set that up */
        values_del[0] = (char *)slapi_sdn_get_dn(origDN);
        values_del[1] = NULL;
        attribute1.mod_type = attrName;
        attribute1.mod_op = LDAP_MOD_DELETE;
        attribute1.mod_values = values_del;
        mods[0] = &attribute1;
        /* terminate list of mods. */
        mods[1] = NULL;
        rc = _do_modify(mod_pb, entrySDN, mods);
        if (rc) {
            slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
                "_update_all_per_mod: entry %s: deleting \"%s: %s\" failed (%d)"
                "\n", slapi_sdn_get_dn(entrySDN), attrName, slapi_sdn_get_dn(origDN), rc);
        }
    } else {
        /* in modrdn mode */
        const char *superior = NULL;
        int nval = 0;
        Slapi_Value *v = NULL;

        if (NULL == origDN) {
            slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
                            "_update_all_per_mod: NULL dn was passed\n");
            goto bail;
        }
        /* need to put together rdn into a dn */
        dnParts = slapi_ldap_explode_dn( slapi_sdn_get_dn(origDN), 0 );
        if (NULL == dnParts) {
            slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
                            "_update_all_per_mod: failed to explode dn %s\n",
                            slapi_sdn_get_dn(origDN));
            goto bail;
        }
        if (NULL == newRDN) {
            newRDN = dnParts[0];
        }
        if (newsuperior) {
            superior = newsuperior;
        } else {
            /* do not free superior */
            superior = slapi_dn_find_parent(slapi_sdn_get_dn(origDN));
        }
        /* newRDN and superior are already normalized. */
        newDN = slapi_ch_smprintf("%s,%s", newRDN, superior);
        slapi_dn_ignore_case(newDN);
        /* 
         * Compare the modified dn with the value of 
         * the target attribute of referint to find out
         * the modified dn is the ancestor (case 2) or
         * the value itself (case 1).
         *
         * E.g., 
         * (case 1) 
         * modrdn: uid=A,ou=B,o=C --> uid=A',ou=B',o=C
         *            (origDN)             (newDN)
         * member: uid=A,ou=B,ou=C --> uid=A',ou=B',ou=C
         *            (sval)               (newDN)
         *
         * (case 2) 
         * modrdn: ou=B,o=C --> ou=B',o=C
         *         (origDN)      (newDN)
         * member: uid=A,ou=B,ou=C --> uid=A,ou=B',ou=C
         *         (sval)              (sval' + newDN)
         */
        slapi_attr_get_numvalues(attr, &nval);
        smods = slapi_mods_new();
        slapi_mods_init(smods, 2 * nval + 1);

        for (nval = slapi_attr_first_value(attr, &v);
             nval != -1;
             nval = slapi_attr_next_value(attr, nval, &v)) {
            p = NULL;
            dnlen = 0;

            /* DN syntax, which should be a string */
            sval = slapi_ch_strdup(slapi_value_get_string(v));
            rc = slapi_dn_normalize_case_ext(sval, 0,  &p, &dnlen);
            if (rc == 0) { /* sval is passed in; not terminated */
                *(p + dnlen) = '\0';
                sval = p;
            } else if (rc > 0) {
                slapi_ch_free_string(&sval);
                sval = p;
            }
            /* else: (rc < 0) Ignore the DN normalization error for now. */

            p = PL_strstr(sval, slapi_sdn_get_ndn(origDN));
            if (p == sval) {
                /* (case 1) */
                slapi_mods_add_string(smods, LDAP_MOD_DELETE, attrName, sval);
                slapi_mods_add_string(smods, LDAP_MOD_ADD, attrName, newDN);

            } else if (p) {
                /* (case 2) */
                slapi_mods_add_string(smods, LDAP_MOD_DELETE, attrName, sval);
                *p = '\0';
                newvalue = slapi_ch_smprintf("%s%s", sval, newDN);
                slapi_mods_add_string(smods, LDAP_MOD_ADD, attrName, newvalue);
                slapi_ch_free_string(&newvalue);
            } 
            /* else: value does not include the modified DN.  Ignore it. */
            slapi_ch_free_string(&sval);
        }
        rc = _do_modify(mod_pb, entrySDN, slapi_mods_get_ldapmods_byref(smods));
        if (rc) {
            slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
                        "_update_all_per_mod: entry %s failed (%d)\n",
                        slapi_sdn_get_dn(entrySDN), rc);
        }

        /* cleanup memory allocated for dnParts and newDN */
        if (dnParts){
            slapi_ldap_value_free(dnParts);
            dnParts = NULL;
        }
        slapi_ch_free_string(&newDN);
        slapi_mods_free(&smods);
    }

bail:
    return rc;
}