diff options
author | Noriko Hosoi <nhosoi@redhat.com> | 2010-04-26 11:03:52 -0700 |
---|---|---|
committer | Noriko Hosoi <nhosoi@redhat.com> | 2010-04-26 11:03:52 -0700 |
commit | 78c50664d6421cc5d0836bb03820680dc2cb7acf (patch) | |
tree | 20fcfadad9057617daa0b159216f0a92006969f5 /ldap/servers/plugins/acl | |
parent | 4754291972668c37559a8f68d75ac6f8c477efb8 (diff) | |
download | ds-78c50664d6421cc5d0836bb03820680dc2cb7acf.tar.gz ds-78c50664d6421cc5d0836bb03820680dc2cb7acf.tar.xz ds-78c50664d6421cc5d0836bb03820680dc2cb7acf.zip |
Update to New DN Format
Fix Description:
. adding slapi_dn_normalize_ext and its siblings to normalize/validate
invalid DNs; deprecating slapi_dn_normalize and its siblings. (dn.c)
. replacing slapi_dn_normalize with new corresponding functions.
. normalizing hardcoded DNs (e.g., removing spaces around ',')
. setting correct DN syntax to nsslapd-suffix, nsslapd-ldapiautodnsuffix,
costemplatedn, nsslapd-changelogsuffix, nsBaseDN, nsBindDN
. if nsslapd-dn-validate-strict is enabled, incoming DN is examined and
rejected if it is invalid. Once approved, the DN is normalized.
. fixing compiler warnings and typos.
See also:
http://directory.fedoraproject.org/wiki/Upgrade_to_New_DN_Format
Related bugs:
Bug 199923 - subtree search fails to find items under a db containing special
characters
Bug 567968 - subtree/user level password policy created using 389-ds-console
doesn't work.
Bug 570107 - The import of LDIFs with base-64 encoded DNs fails, modrdn with
non-ASCII new rdn incorrect
Bug 570962 - ns-inactivate.pl does not work
Bug 572785 - DN syntax: old style of DN <type>="<DN>",<the_rest> is not
correctly normalized
Bug 573060 - DN normalizer: ESC HEX HEX is not normalized
Bug 574167 - An escaped space at the end of the RDN value is not handled
correctly
Diffstat (limited to 'ldap/servers/plugins/acl')
-rw-r--r-- | ldap/servers/plugins/acl/acl.c | 56 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/acl.h | 7 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/acl_ext.c | 2 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/aclanom.c | 1 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/acleffectiverights.c | 47 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/acllas.c | 201 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/aclparse.c | 386 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/aclproxy.c | 17 | ||||
-rw-r--r-- | ldap/servers/plugins/acl/aclutil.c | 66 |
9 files changed, 516 insertions, 267 deletions
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c index aa22d566..715ad1ea 100644 --- a/ldap/servers/plugins/acl/acl.c +++ b/ldap/servers/plugins/acl/acl.c @@ -358,8 +358,8 @@ acl_access_allowed( if (oid && ((strcasecmp(oid, DN_SYNTAX_OID) == 0) || (strcasecmp(oid, NAMEANDOPTIONALUID_SYNTAX_OID) == 0))) { /* should use slapi_sdn_compare() but that'a an extra malloc/free */ - char *dn_val_to_write = slapi_dn_normalize(slapi_ch_strdup(val->bv_val)); - if ( aclpb->aclpb_authorization_sdn && + char *dn_val_to_write = slapi_create_dn_string("%s", val->bv_val); + if ( dn_val_to_write && aclpb->aclpb_authorization_sdn && slapi_utf8casecmp((ACLUCHP)dn_val_to_write, (ACLUCHP) slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn)) == 0) { access |= SLAPI_ACL_SELF; @@ -754,9 +754,10 @@ static void print_access_control_summary( char *source, int ret_val, char *clien if ( aclpb->aclpb_authorization_sdn != NULL ) { - proxy_user = (char *)(aclpb->aclpb_authorization_sdn->ndn ? - aclpb->aclpb_authorization_sdn->ndn: - null_user); + proxy_user = + (char *)(slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn)? + slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn): + null_user); slapi_log_error(loglevel, plugin_name, "conn=%" NSPRIu64 " op=%d (%s): %s %s on entry(%s).attr(%s) to proxy (%s)" @@ -1764,8 +1765,7 @@ acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change) if (parent_DN == NULL) { new_DN = new_RDN; } else { - new_DN = slapi_ch_smprintf("%s,%s", new_RDN, parent_DN); - slapi_dn_normalize (new_DN); + new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN); } /* Change the acls */ @@ -2028,8 +2028,7 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * ** We have a single ACI which we need to find if it applies to ** the resource or not. */ - if ((aci->aci_type & ACI_TARGET_DN) && - (aclpb->aclpb_curr_entry_sdn)) { + if ((aci->aci_type & ACI_TARGET_DN) && (aclpb->aclpb_curr_entry_sdn)) { char *avaType; struct berval *avaValue; @@ -2246,10 +2245,10 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * * */ - if ((aclpb->aclpb_access & SLAPI_ACL_ADD && - aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS )|| - (aclpb->aclpb_access & SLAPI_ACL_DELETE && - aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS ) ) { + if (((aclpb->aclpb_access & SLAPI_ACL_ADD) && + (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) )|| + ((aclpb->aclpb_access & SLAPI_ACL_DELETE) && + (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS) ) ) { Targetattrfilter **attrFilterArray; @@ -2367,10 +2366,10 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * goto acl__resource_match_aci_EXIT; } - } else if ( (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD && - aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) || - (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL && - aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS ) ) { + } else if ( ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) && + (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) || + ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) && + (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)) ) { /* @@ -2381,28 +2380,28 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * * match that filter. * * - */ + */ Targetattrfilter **attrFilterArray = NULL; Targetattrfilter *attrFilter; int found = 0; - if (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD && - aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) { + if ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) && + (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) { - attrFilterArray = aci->targetAttrAddFilters; + attrFilterArray = aci->targetAttrAddFilters; - } else if (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL && - aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS) { + } else if ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) && + (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)) { - attrFilterArray = aci->targetAttrDelFilters; + attrFilterArray = aci->targetAttrDelFilters; } /* * Scan this filter list for an applicable filter. - */ + */ found = 0; num_attrs = 0; @@ -2435,7 +2434,7 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * attr_matched= acl__test_filter(aclpb->aclpb_filter_test_entry, attrFilter->filter, 1 /* Do filter sense evaluation below */ - ); + ); slapi_entry_free( aclpb->aclpb_filter_test_entry ); } @@ -2452,8 +2451,6 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * */ attr_matched_in_targetattrfilters = 1; - - } } /* targetvaluefilters */ @@ -3233,9 +3230,6 @@ acl_match_substring ( Slapi_Filter *f, char *str, int exact_match) realval = tmp; } - slapi_dn_normalize (realval); - - /* What we have built is a regular pattaren expression. ** Now we will compile the pattern and compare wth the string to ** see if the input string matches with the patteren or not. diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h index 36bdd43c..3f4b4e62 100644 --- a/ldap/servers/plugins/acl/acl.h +++ b/ldap/servers/plugins/acl/acl.h @@ -119,7 +119,11 @@ static char* const aci_targetattr = "targetattr"; static char* const aci_targetattrfilters = "targattrfilters"; static char* const aci_targetfilter = "targetfilter"; +static char* const LDAP_URL_prefix_core = "ldap://"; +static char* const LDAPS_URL_prefix_core = "ldaps://"; + static char* const LDAP_URL_prefix = "ldap:///"; +static char* const LDAPS_URL_prefix = "ldaps:///"; static char* const access_str_compare = "compare"; static char* const access_str_search = "search"; @@ -827,7 +831,7 @@ int acl_skip_access_check ( Slapi_PBlock *pb, Slapi_Entry *e ); int aclext_alloc_lockarray (); -int aclutil_str_appened(char **str1, const char *str2); +int aclutil_str_append(char **str1, const char *str2); void aclutil_print_err (int rv , const Slapi_DN *sdn, const struct berval* val, char **errbuf); void aclutil_print_aci (aci_t *aci_item, char *type); @@ -911,6 +915,7 @@ acl_replace_str(char * s, char *substr, char* replace_with); int acl_strstr(char * s, char *substr); int aclutil_evaluate_macro( char * rule, lasInfo *lasinfo, acl_eval_types evalType ); +int aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t slen); /* acl hash table functions */ void acl_ht_add_and_freeOld(acl_ht_t * acl_ht, PLHashNumber key,char *value); diff --git a/ldap/servers/plugins/acl/acl_ext.c b/ldap/servers/plugins/acl/acl_ext.c index 5e1d360b..d9494ec3 100644 --- a/ldap/servers/plugins/acl/acl_ext.c +++ b/ldap/servers/plugins/acl/acl_ext.c @@ -791,7 +791,7 @@ acl__done_aclpb ( struct acl_pblock *aclpb ) */ /* Nothing needs to be cleaned up in this case */ - if ( !aclpb->aclpb_state & ACLPB_INITIALIZED) + if (!(aclpb->aclpb_state & ACLPB_INITIALIZED)) return; /* Check the state */ diff --git a/ldap/servers/plugins/acl/aclanom.c b/ldap/servers/plugins/acl/aclanom.c index 773dad2f..b1d15ca1 100644 --- a/ldap/servers/plugins/acl/aclanom.c +++ b/ldap/servers/plugins/acl/aclanom.c @@ -205,6 +205,7 @@ aclanom_gen_anomProfile (acl_lock_flag_t lock_flag) /* see if this is a monitor acl */ if (( strcasecmp ( dn, "cn=monitor") == 0 ) || + /* cn=monitor,cn=ldbm: No such object */ ( strcasecmp ( dn, "cn=monitor,cn=ldbm") == 0 )) { aci = acllist_get_next_aci ( NULL, aci, &cookie); continue; diff --git a/ldap/servers/plugins/acl/acleffectiverights.c b/ldap/servers/plugins/acl/acleffectiverights.c index 9afac079..acf856cc 100644 --- a/ldap/servers/plugins/acl/acleffectiverights.c +++ b/ldap/servers/plugins/acl/acleffectiverights.c @@ -170,7 +170,7 @@ _ger_g_permission_granted ( goto bailout; } - aclutil_str_appened ( errbuf, "get-effective-rights: requestor has no g permission on the entry" ); + aclutil_str_append ( errbuf, "get-effective-rights: requestor has no g permission on the entry" ); slapi_log_error (SLAPI_LOG_ACL, plugin_name, "_ger_g_permission_granted: %s\n", *errbuf); rc = LDAP_INSUFFICIENT_ACCESS; @@ -195,7 +195,10 @@ _ger_parse_control ( LDAPControl **requestcontrols; struct berval *subjectber; BerElement *ber; - int subjectndnlen = 0; + size_t subjectndnlen = 0; + char *orig = NULL; + char *normed = NULL; + int rc = 0; if (NULL == subjectndn) { @@ -215,7 +218,7 @@ _ger_parse_control ( if ( subjectber == NULL || subjectber->bv_val == NULL || subjectber->bv_len == 0 ) { - aclutil_str_appened ( errbuf, "get-effective-rights: missing subject" ); + aclutil_str_append ( errbuf, "get-effective-rights: missing subject" ); slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf ); return LDAP_INVALID_SYNTAX; } @@ -227,23 +230,23 @@ _ger_parse_control ( * or base64 encoding string. Hence users using -J option in * ldapsearch don't have to do BER encoding for the subject. */ - *subjectndn = slapi_ch_malloc ( subjectber->bv_len + 1 ); - strncpy ( *subjectndn, subjectber->bv_val, subjectber->bv_len ); - *(*subjectndn + subjectber->bv_len) = '\0'; + 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_appened ( errbuf, "get-effective-rights: ber_init failed for the subject" ); + aclutil_str_append ( errbuf, "get-effective-rights: ber_init failed for the subject" ); slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf ); return LDAP_OPERATIONS_ERROR; } /* "a" means to allocate storage as needed for octet string */ - if ( ber_scanf (ber, "a", subjectndn) == LBER_ERROR ) + if ( ber_scanf (ber, "a", orig) == LBER_ERROR ) { - aclutil_str_appened ( errbuf, "get-effective-rights: invalid ber tag in the subject" ); + aclutil_str_append ( errbuf, "get-effective-rights: invalid ber tag in the subject" ); slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf ); ber_free ( ber, 1 ); return LDAP_INVALID_SYNTAX; @@ -256,18 +259,32 @@ _ger_parse_control ( * (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 = strlen(*subjectndn); - if ( NULL == *subjectndn || subjectndnlen < 3 || - strncasecmp ( "dn:", *subjectndn, 3 ) != 0 ) + subjectndnlen = strlen(orig); + if ( NULL == orig || subjectndnlen < 3 || strncasecmp ( "dn:", orig, 3 ) != 0 ) { - aclutil_str_appened ( errbuf, "get-effective-rights: subject is not dnAuthzId" ); + aclutil_str_append ( errbuf, "get-effective-rights: subject is not dnAuthzId" ); slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf ); + slapi_ch_free_string(&orig); return LDAP_INVALID_SYNTAX; } /* memmove is safe for overlapping copy */ - memmove ( *subjectndn, *subjectndn + 3, subjectndnlen - 2);/* 1 for '\0' */ - slapi_dn_normalize ( *subjectndn ); + rc = slapi_dn_normalize_ext(orig + 3, 0, &normed, &subjectndnlen); + if (rc < 0) { + aclutil_str_append ( errbuf, "get-effective-rights: failed to normalize dn: "); + aclutil_str_append ( errbuf, orig); + slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf ); + slapi_ch_free_string(&orig); + return LDAP_INVALID_SYNTAX; + } + if (rc == 0) { /* orig+3 is passed in; not terminated */ + *(normed + subjectndnlen) = '\0'; + *subjectndn = slapi_ch_strdup(normed); + slapi_ch_free_string(&orig); + } else { + slapi_ch_free_string(&orig); + *subjectndn = normed; + } return LDAP_SUCCESS; } diff --git a/ldap/servers/plugins/acl/acllas.c b/ldap/servers/plugins/acl/acllas.c index 9a57d7c8..9fbd25bb 100644 --- a/ldap/servers/plugins/acl/acllas.c +++ b/ldap/servers/plugins/acl/acllas.c @@ -480,6 +480,7 @@ DS_LASUserDnEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, int rc; short len; const size_t LDAP_URL_prefix_len = strlen(LDAP_URL_prefix); + const size_t LDAPS_URL_prefix_len = strlen(LDAPS_URL_prefix); lasInfo lasinfo; int got_undefined = 0; @@ -530,15 +531,15 @@ DS_LASUserDnEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, ** userdn = "ldap:///DN1 || ldap:///DN2" */ - /* The DN is now "ldap:///DN" ** remove the "ldap:///" part */ - if (strncasecmp (user, LDAP_URL_prefix, - LDAP_URL_prefix_len) == 0) { + if (strncasecmp (user, LDAP_URL_prefix, LDAP_URL_prefix_len) == 0) { s_user = user; user += LDAP_URL_prefix_len; - + } else if (strncasecmp (user, LDAPS_URL_prefix, LDAPS_URL_prefix_len) == 0) { + s_user = user; + user += LDAPS_URL_prefix_len; } else { char ebuf[ BUFSIZ ]; slapi_log_error(SLAPI_LOG_FATAL, plugin_name, @@ -677,8 +678,19 @@ DS_LASUserDnEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, slapi_filter_free(f,1); } else { /* Must be a simple dn then */ - if (slapi_utf8casecmp((ACLUCHP)lasinfo.clientDn, - (ACLUCHP)slapi_dn_normalize(user)) == 0) { + char *normed = NULL; + size_t dnlen = 0; + rc = slapi_dn_normalize_ext(user, 0, &normed, &dnlen); + if (rc == 0) { /* user passed in; not terminated */ + *(normed + dnlen) = '\0'; + } else if (rc < 0) { /* normalization failed, user the original */ + normed = user; + } + rc = slapi_utf8casecmp((ACLUCHP)lasinfo.clientDn, (ACLUCHP)normed); + if (normed != user) { + slapi_ch_free_string(&normed); + } + if (0 == rc) { matched = ACL_TRUE; break; } @@ -1274,8 +1286,14 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, while ( j != -1 ) { attrVal = slapi_value_get_berval ( sval ); /* Here if atleast 1 value matches then we are done.*/ - val = slapi_dn_normalize ( - slapi_ch_strdup( attrVal->bv_val)); + val = slapi_create_dn_string("%s", attrVal->bv_val); + if (NULL == val) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "DS_LASUserDnAttrEval: Invalid syntax: %s\n", + attrVal->bv_val ); + slapi_ch_free ( (void**) &s_attrName); + return LAS_EVAL_FAIL; + } if (slapi_utf8casecmp((ACLUCHP)val, (ACLUCHP)lasinfo.clientDn ) == 0) { char ebuf [ BUFSIZ ]; @@ -2380,7 +2398,13 @@ acllas__handle_group_entry (Slapi_Entry* e, void *callback_data) while ( i != -1 ) { struct member_info *groupMember = NULL; attrVal = slapi_value_get_berval ( sval ); - n_dn = slapi_dn_normalize ( slapi_ch_strdup( attrVal->bv_val )); + n_dn = slapi_create_dn_string( attrVal->bv_val ); + if (NULL == n_dn) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__handle_group_entry: Invalid syntax: %s\n", + attrVal->bv_val ); + return 0; + } n = ++info->lu_idx; if (n < 0) { slapi_log_error( SLAPI_LOG_FATAL, plugin_name, @@ -2433,7 +2457,14 @@ acllas__handle_group_entry (Slapi_Entry* e, void *callback_data) */ if (strncasecmp( attrVal->bv_val, "ldap://",7) == 0 || strncasecmp( attrVal->bv_val, "ldaps://",8) == 0) { - savURL = memberURL = slapi_ch_strdup ( attrVal->bv_val); + savURL = memberURL = + slapi_create_dn_string("%s", attrVal->bv_val); + if (NULL == savURL) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__handle_group_entry: Invalid syntax: %s\n", + attrVal->bv_val ); + return 0; + } slapi_log_error( SLAPI_LOG_ACL, plugin_name, "ACL Group Eval:MemberURL:%s\n", memberURL); info->result = acllas__client_match_URL ( @@ -2656,8 +2687,13 @@ DS_LASGroupDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, attr_i= slapi_attr_first_value ( attr,&sval ); while ( attr_i != -1 ) { attrVal = slapi_value_get_berval ( sval ); - n_groupdn = slapi_dn_normalize( - slapi_ch_strdup( attrVal->bv_val)); + n_groupdn = slapi_create_dn_string("%s", attrVal->bv_val); + if (NULL == n_groupdn) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "DS_LASGroupDnAttrEval: Invalid syntax: %s\n", + attrVal->bv_val ); + return 0; + } matched = acllas__user_ismember_of_group ( lasinfo.aclpb, n_groupdn, lasinfo.clientDn, ACLLAS_CACHE_MEMBER_GROUPS, @@ -2855,6 +2891,7 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e, char *curMemberDn; int Done = 0; int ngr, tt; + char *normed = NULL; /* Add the scope to the list of scopes */ if (aclpb->aclpb_numof_bases >= (aclpb->aclpb_grpsearchbase_size-1)) { @@ -2866,9 +2903,15 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e, sizeof (char *)); aclpb->aclpb_grpsearchbase_size += ACLPB_INCR_BASES; } - aclpb->aclpb_grpsearchbase[aclpb->aclpb_numof_bases++] = - slapi_dn_normalize(slapi_ch_strdup(base)); - + normed = slapi_create_dn_string("%s", base); + if (NULL == normed) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__eval_memberGroupDnAttr: Invalid syntax: %s\n", + base ); + slapi_ch_free ( (void **)&s_str ); + return ACL_FALSE; + } + aclpb->aclpb_grpsearchbase[aclpb->aclpb_numof_bases++] = normed; /* Set up info to do a search */ attrs[0] = type_member; attrs[1] = type_uniquemember; @@ -2991,8 +3034,14 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e, while ( k != -1 ) { char *n_attrval; attrVal = slapi_value_get_berval ( sval ); - n_attrval = slapi_ch_strdup( attrVal->bv_val); - n_attrval = slapi_dn_normalize (n_attrval); + n_attrval = slapi_create_dn_string("%s", attrVal->bv_val); + if (NULL == n_attrval) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__eval_memberGroupDnAttr: Invalid syntax: %s\n", + attrVal->bv_val ); + slapi_ch_free ( (void **)&s_str ); + return ACL_FALSE; + } /* We support: The attribute value can be a USER or a GROUP. ** Let's compare with the client, thi might be just an user. If it is not @@ -3147,7 +3196,13 @@ acllas__verify_client (Slapi_Entry* e, void *callback_data) i = slapi_attr_first_value ( attr,&sval ); while ( i != -1 ) { attrVal = slapi_value_get_berval ( sval ); - val = slapi_dn_normalize(slapi_ch_strdup(attrVal->bv_val)); + val = slapi_create_dn_string("%s", attrVal->bv_val); + if (NULL == val) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__verify_client: Invalid syntax: %s\n", + attrVal->bv_val ); + return 0; + } if (slapi_utf8casecmp((ACLUCHP)val, (ACLUCHP)info->clientdn ) == 0) { info->result = 1; @@ -3235,7 +3290,12 @@ acllas__get_members (Slapi_Entry* e, void *callback_data) i = slapi_attr_first_value ( attr,&sval ); while ( i != -1 ) { attrVal =slapi_value_get_berval ( sval ); - info->member[i] = slapi_dn_normalize ( slapi_ch_strdup(attrVal->bv_val)); + info->member[i] = slapi_create_dn_string ("%s", attrVal->bv_val); + if (NULL == info->member[i]) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__get_members: Invalid syntax: %s\n", + attrVal->bv_val ); + } i = slapi_attr_next_value ( attr, i, &sval ); } return 0; @@ -3426,7 +3486,17 @@ acllas__client_match_URL (struct acl_pblock *aclpb, char *n_clientdn, char *url LDAPURLDesc *ludp; int rc; Slapi_Filter *f = NULL; - + char *rawdn = NULL; + char *dn = NULL; + size_t dnlen = 0; + char *p = NULL; + char *normed = NULL; + /* ldap(s)://host:port/suffix?attrs?scope?filter */ + const size_t LDAP_URL_prefix_len = strlen(LDAP_URL_prefix_core); + const size_t LDAPS_URL_prefix_len = strlen(LDAPS_URL_prefix_core); + size_t prefix_len = 0; + char Q = '?'; + char *hostport = NULL; /* Get the client's entry if we don't have already */ if ( aclpb && ( NULL == aclpb->aclpb_client_entry )) { @@ -3459,23 +3529,83 @@ acllas__client_match_URL (struct acl_pblock *aclpb, char *n_clientdn, char *url } if ( NULL == aclpb->aclpb_client_entry ) { - slapi_log_error ( SLAPI_LOG_ACL, plugin_name, - "DS_LASUserAttrEval: Unable to get client's entry\n"); + slapi_log_error (SLAPI_LOG_ACL, plugin_name, + "acllas__client_match_URL: Unable to get client's entry\n"); return ACL_FALSE; } - if (( rc = ldap_url_parse( url, &ludp)) != 0 ) { + /* DN potion of URL must be normalized before calling ldap_url_parse. + * lud_dn is pointing at the middle of lud_string. + * lud_dn won't be freed in ldap_free_urldesc. + */ + /* remove the "ldap{s}:///" part */ + if (strncasecmp (url, LDAP_URL_prefix, LDAP_URL_prefix_len) == 0) { + prefix_len = LDAP_URL_prefix_len; + } else if (strncasecmp (url, LDAPS_URL_prefix, LDAPS_URL_prefix_len) == 0) { + prefix_len = LDAPS_URL_prefix_len; + } else { + slapi_log_error (SLAPI_LOG_ACL, plugin_name, + "acllas__client_match_URL: url %s does not include ldap prefix: %s\n", url); + return ACL_FALSE; + } + rawdn = url + prefix_len; /* ldap(s)://host:port/... or ldap(s):///... */ + /* rawdn at ^ or ^ */ + /* let rawdn point the suffix */ + if ('/' == *(rawdn+1)) { /* ldap(s):/// */ + rawdn += 2; + hostport = "/"; + } else { + char *tmpp = rawdn; + rawdn = strchr(tmpp, '/'); + size_t hostport_len = 0; + if (NULL == rawdn) { + slapi_log_error (SLAPI_LOG_ACL, plugin_name, + "acllas__client_match_URL: url %s does not include correct ldap prefix: %s\n", url); + return ACL_FALSE; + } + hostport_len = ++rawdn - tmpp; /* ldap(s)://host:port/... */ + /* <--------> */ + hostport = (char *)slapi_ch_malloc(hostport_len + 1); + memcpy(hostport, tmpp, hostport_len); + *(hostport+hostport_len) = '\0'; + } + p = strchr(rawdn, Q); + if (p) { + /* url has scope and/or filter: ldap(s):///suffix?attr?scope?filter */ + *p = '\0'; + } + rc = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen); + if (rc < 0) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "acllas__client_match_URL: Invalid syntax: %s\n", url); + return ACL_FALSE; + } else if (rc == 0) { /* url is passed in and not terminated with NULL*/ + *(dn + dnlen) = '\0'; + } + if (p) { + *p = Q; + } + normed = slapi_ch_smprintf("%s%s%s%s", + (prefix_len==LDAP_URL_prefix_len)? + LDAP_URL_prefix_core:LDAPS_URL_prefix_core, + hostport, dn, p?p:""); + if (rc > 0) { + /* dn was allocated in slapi_dn_normalize_ext */ + slapi_ch_free_string(&dn); + } + if ('/' != *hostport) { + slapi_ch_free_string(&hostport); + } + rc = ldap_url_parse(normed, &ludp); + slapi_ch_free_string(&normed); + if (rc) { return ACL_FALSE; - } if ( ( NULL == ludp->lud_dn) || ( NULL == ludp->lud_filter) ) { ldap_free_urldesc( ludp ); return ACL_FALSE; } - /* Normalize in place the dn */ - slapi_dn_normalize ( ludp->lud_dn ); - /* Check the scope */ if ( ludp->lud_scope == LDAP_SCOPE_SUBTREE ) { if (!slapi_dn_issuffix(n_clientdn, ludp->lud_dn)) { @@ -3777,8 +3907,13 @@ DS_LASRoleDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, Slapi_DN *roleDN; attrVal = slapi_value_get_berval ( sval ); - n_attrval = slapi_ch_strdup( attrVal->bv_val); - n_attrval = slapi_dn_normalize (n_attrval); + n_attrval = slapi_create_dn_string("%s", attrVal->bv_val); + if (NULL == n_attrval) { + slapi_log_error( SLAPI_LOG_FATAL, plugin_name, + "DS_LASRoleDnAttrEval: Invalid syntax: %s\n", + attrVal->bv_val ); + return LAS_EVAL_FAIL; + } roleDN = slapi_sdn_new_dn_byval(n_attrval); /* We support: The attribute value can be a USER or a GROUP. @@ -3831,14 +3966,12 @@ DS_LASRoleDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, * returns: ACL_TRUE for matched, * ACL_FALSE for matched. * ACL_DONT_KNOW otherwise. - * - * -*/ + */ int aclutil_evaluate_macro( char * rule, lasInfo *lasinfo, - acl_eval_types evalType ) { - + acl_eval_types evalType ) +{ int matched = 0; aci_t *aci; char *matched_val = NULL; diff --git a/ldap/servers/plugins/acl/aclparse.c b/ldap/servers/plugins/acl/aclparse.c index 8d4a21a0..0c8d0fa3 100644 --- a/ldap/servers/plugins/acl/aclparse.c +++ b/ldap/servers/plugins/acl/aclparse.c @@ -50,7 +50,6 @@ static int __aclp__sanity_check_acltxt(aci_t *aci_item, char *str); static char * __aclp__normalize_acltxt (aci_t *aci_item, char *str); static char * __aclp__getNextLASRule(aci_t *aci_item, char *str, char **endOfCurrRule); -static char * __aclp__dn_normalize( char *dn , char *end); static int __aclp__get_aci_right ( char *str); static int __aclp__init_targetattr (aci_t *aci, char *attr_val); static int __acl__init_targetattrfilters( aci_t *aci_item, char *str); @@ -239,10 +238,10 @@ __aclp__parse_aci (char *str, aci_t *aci_item) /* - * The targetattrfilters bit looks like this: - * (targetattrfilters="add= attr1:F1 && attr2:F2 ... && attrn:Fn, - * del= attr1:F1 && attr2:F2... && attrn:Fn") - */ + * The targetattrfilters bit looks like this: + * (targetattrfilters="add= attr1:F1 && attr2:F2 ... && attrn:Fn, + * del= attr1:F1 && attr2:F2... && attrn:Fn") + */ if ( 0 != (rv= __acl__init_targetattrfilters( aci_item, str))) { return rv; @@ -256,15 +255,14 @@ __aclp__parse_aci (char *str, aci_t *aci_item) } /* Get individual components of the targetattr. * (targetattr = "cn || u* || phone ||tel:add:(tel=1234) - * || sn:del:(gn=5678)") - * If it contains a value filter, the type will also be - * ACI_TARGET_VALUE_ATTR. - */ - if ( 0 != (rv= __aclp__init_targetattr( - aci_item, str))) { + * || sn:del:(gn=5678)") + * If it contains a value filter, the type will also be + * ACI_TARGET_VALUE_ATTR. + */ + if (0 != (rv = __aclp__init_targetattr(aci_item, str))) { return rv; } - } else if (strncmp(str, aci_targetfilter,tfilterlen ) == 0) { + } else if (strncmp(str, aci_targetfilter,tfilterlen ) == 0) { if ( aci_item->targetFilter) return ACL_SYNTAX_ERR; @@ -311,8 +309,8 @@ __aclp__parse_aci (char *str, aci_t *aci_item) } else if (strncmp(str, aci_targetdn, targetdnlen) == 0) { char *tstr = NULL; - const size_t LDAP_URL_prefix_len = strlen (LDAP_URL_prefix); - char *tt; + size_t LDAP_URL_prefix_len = 0; + size_t tmplen = 0; type = ACI_TARGET_DN; /* Keep a copy of the target attr */ if (aci_item->target) { @@ -322,30 +320,40 @@ __aclp__parse_aci (char *str, aci_t *aci_item) type |= ACI_TARGET_NOT; strncpy(s, " ", 1); } - - /* Convert it to lower as slapi_dn_normalize() does not */ - for (tt = str; *tt; tt++) *tt = TOLOWER ( *tt ); - if ( (s = strchr( str, '=' )) != NULL ) { value = s + 1; - slapi_dn_normalize(value); + __acl_strip_leading_space(&value); len = strlen ( value ); - if (*value == '"' && value[len-1] == '"'){ + /* strip double quotes */ + if (*value == '"' && value[len-1] == '"') { value[len-1] = '\0'; value++; } __acl_strip_leading_space(&value); - } else { + } else { return ( ACL_SYNTAX_ERR ); } - - if ( strncasecmp ( value, LDAP_URL_prefix , LDAP_URL_prefix_len) ) + if (0 == + strncasecmp(value, LDAP_URL_prefix, strlen(LDAP_URL_prefix))) { + LDAP_URL_prefix_len = strlen(LDAP_URL_prefix); + } else if (0 == strncasecmp(value, LDAPS_URL_prefix, + strlen(LDAPS_URL_prefix))) { + LDAP_URL_prefix_len = strlen(LDAPS_URL_prefix); + } else { return ( ACL_SYNTAX_ERR ); + } value += LDAP_URL_prefix_len; - len = strlen ( value ); - tstr = (char *) slapi_ch_malloc ( targetdnlen + len + 4 ); - sprintf ( tstr, "(target=%s)", value); + rv = slapi_dn_normalize_case_ext(value, 0, &tmpstr, &tmplen); + if (rv < 0) { + return ACL_SYNTAX_ERR; + } else if (rv == 0) { /* value passed in; not null terminated */ + *(tmpstr + tmplen) = '\0'; + } + tstr = slapi_ch_smprintf("(target=%s)", tmpstr); + if (rv > 0) { + slapi_ch_free_string(&tmpstr); + } if ( (rv = acl_check_for_target_macro( aci_item, value)) == -1) { slapi_ch_free ( (void **) &tstr ); return(ACL_SYNTAX_ERR); @@ -356,7 +364,7 @@ __aclp__parse_aci (char *str, aci_t *aci_item) /* it's a normal target with no macros inside */ f = slapi_str2filter ( tstr ); } - slapi_ch_free ( (void **) &tstr ); + slapi_ch_free_string ( &tstr ); } else { /* did start with a 't' but was not a recognsied keyword */ return(ACL_SYNTAX_ERR); @@ -492,20 +500,86 @@ __aclp__sanity_check_acltxt (aci_t *aci_item, char *str) slapi_log_error(SLAPI_LOG_ACL, plugin_name, "Normalized String:%s\n", newstr); /* check for acl syntax error */ - if ((handle = (ACLListHandle_t *) ACL_ParseString(&errp, - newstr)) == NULL) { + if ((handle = (ACLListHandle_t *) ACL_ParseString(&errp, newstr)) == NULL) { acl_print_acllib_err(&errp, str); - slapi_ch_free ( (void **) &newstr ); + slapi_ch_free_string(&newstr); return ACL_SYNTAX_ERR; } else { /* get the rights and the aci type */ aci_item->aci_handle = handle; nserrDispose(&errp); - slapi_ch_free ( (void **) &newstr ); + slapi_ch_free_string(&newstr); return 0; } } + +/* + * If the src includes "ldap(s):///<dn>", normalize <dn> and copy + * the string starting from start to *dest. + * If isstrict is non-zero, if ldap(s):/// is not included in the src + * string, it returns an error (-1). + * If isstrict is zero, the string is copied as is. + * + * return value: 0 or positive: success + * negative: failure + */ +int +__aclp__copy_normalized_str (char *src, char *endsrc, char *start, + char **dest, size_t *destlen, int isstrict) +{ + char *p = NULL; + int rc = -1; + char *dn = NULL; + size_t dnlen = 0; + + p = PL_strnstr(src, LDAP_URL_prefix, endsrc - src); + if (p) { + p += strlen(LDAP_URL_prefix); + } else { + p = PL_strnstr(src, LDAPS_URL_prefix, endsrc - src); + if (p) { + p += strlen(LDAPS_URL_prefix); + } + } + + if (isstrict && ((NULL == p) || 0 == strlen(p))) { + return rc; /* error */ + } + + rc = 0; + if (p && strlen(p) > 0) { + size_t len = 0; + /* strip the string starting from ? */ + char *q = PL_strnchr(p, '?', endsrc - p); + if (q) { + len = q - p; + } else { + len = endsrc - p; + } + /* Normalize the value of userdn and append it to ret_str */ + rc = slapi_dn_normalize_ext(p, len, &dn, &dnlen); + if (rc < 0) { + return rc; + } + /* append up to ldap(s):/// */ + aclutil_str_append_ext(dest, destlen, start, p - start); + /* append the DN part */ + aclutil_str_append_ext(dest, destlen, dn, dnlen); + if (rc > 0) { /* if rc == 0, p is passed in */ + slapi_ch_free_string(&dn); + } + if (q) { + /* append the rest from '?' */ + aclutil_str_append_ext(dest, destlen, q, endsrc - q); + } + } else { + aclutil_str_append_ext(dest, destlen, start, endsrc - start); + } + + return rc; +} + /****************************************************************************** * * acl__normalize_acltxt @@ -534,23 +608,25 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str ) char *s, *p; char *end; char *aclstr, *s_aclstr; + char *prevend = NULL; char *ret_str = NULL; + size_t retstr_len = 0; int len; - char *ptr, *aclName; + char *aclName; char *nextACE; char *tmp_str = NULL; char *acestr = NULL; char *s_acestr = NULL; int aci_rights_val = 0; /* bug 389975 */ + int rc = 0; /* make a copy first */ s_aclstr = aclstr = slapi_ch_strdup ( str ); /* The rules are like this version 3.0; acl "xyz"; rule1; rule2; */ s = strchr (aclstr, ';'); - if ( NULL == s) { - slapi_ch_free ( (void **) &s_aclstr ); - return NULL; + if (NULL == s) { + goto error; } aclstr = ++s; @@ -564,9 +640,8 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str ) aclName = s+3; s = strchr (aclstr, ';'); - if ( NULL == s) { - slapi_ch_free ( (void **) &s_aclstr ); - return NULL; + if (NULL == s) { + goto error; } aclstr = s; @@ -576,8 +651,10 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str ) /* Here aclName is the acl description string */ aci_item->aclName = slapi_ch_strdup ( aclName ); - aclutil_str_appened (&ret_str, s_aclstr); - aclutil_str_appened (&ret_str, ";"); + retstr_len = strlen(str) * 3; + ret_str = (char *)slapi_ch_calloc(sizeof(char), retstr_len); + aclutil_str_append_ext (&ret_str, &retstr_len, s_aclstr, strlen(s_aclstr)); + aclutil_str_append_ext (&ret_str, &retstr_len, ";", 1); /* start with the string */ acestr = aclstr; @@ -586,37 +663,34 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str ) * Here acestr is something like: * * " allow (all) groupdn = "ldap:///cn=Domain Administrators, o=$dn.o, o=ISP";)" - * - * - */ + */ normalize_nextACERule: /* now we are in the rule part */ tmp_str = acestr; s = strchr (tmp_str, ';'); - if ( s == NULL) { - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return NULL; + if (s == NULL) { + goto error; } + nextACE = s; LDAP_UTF8INC(nextACE); *s = '\0'; - /* acestr now will hold copy of the ACE. Also add + /* acestr now will hold copy of the ACE. Also add ** some more space in case we need to add "absolute" - ** for deny rule. We will never need more 2 times - ** the len. + ** for deny rule. We will never need more 3 times + ** the len (even if all the chars are escaped). */ __acl_strip_leading_space(&tmp_str); len = strlen (tmp_str); - s_acestr = acestr = slapi_ch_calloc ( 1, 2 * len); + s_acestr = acestr = slapi_ch_calloc (1, 3 * len); /* * Now it's something like: * allow (all) groupdn = "ldap:///cn=Domain Administrators, o=$dn.o, o=ISP"; - */ + */ if (strncasecmp(tmp_str, "allow", 5) == 0) { memcpy(acestr, tmp_str, len); tmp_str += 5; @@ -624,6 +698,14 @@ normalize_nextACERule: aci_rights_val = __aclp__get_aci_right (tmp_str);/* bug 389975 */ aci_item->aci_type |= ACI_HAS_ALLOW_RULE; + s = strchr(acestr, ')'); + if (NULL == s) { + /* wrong syntax */ + goto error; + } + /* add "allow(rights...)" */ + aclutil_str_append_ext(&ret_str, &retstr_len, acestr, s - acestr + 1); + prevend = s + 1; } else if (strncasecmp(tmp_str, "deny", 4) == 0) { char *d_rule ="deny absolute"; /* Then we have to add "absolute" to the deny rule @@ -652,6 +734,15 @@ normalize_nextACERule: len = strlen ( d_rule ); memcpy (acestr, d_rule, len ); memcpy (acestr+len, tmp_str, strlen (tmp_str) ); + + s = strchr(acestr, ')'); + if (NULL == s) { + /* wrong syntax */ + goto error; + } + /* add "deny(rights...)" */ + aclutil_str_append_ext(&ret_str, &retstr_len, acestr, s - acestr + 1); + prevend = s + 1; } else { /* wrong syntax */ aci_rights_val = -1 ; @@ -659,32 +750,32 @@ normalize_nextACERule: if (aci_rights_val == -1 ) { /* wrong syntax */ - slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_acestr ); - slapi_ch_free ( (void **) &s_aclstr ); - return NULL; + goto error; } else - aci_item->aci_access |= aci_rights_val; + aci_item->aci_access |= aci_rights_val; - - /* Normalize all the DNs in the userdn rule */ - + /* Normalize all the DNs in the userdn, groupdn, roledn rules */ /* * * Here acestr starts like this: - * " allow (all) groupdn = "ldap:///cn=Domain Administrators, o=$dn.o, o=ISP" - */ - + * " allow (all) groupdn = "ldap:///cn=Domain Administrators,o=$dn.o,o=ISP" + */ s = __aclp__getNextLASRule(aci_item, acestr, &end); while ( s ) { - if ( 0 == strncmp ( s, DS_LAS_USERDNATTR, 10) || - ( 0 == strncmp ( s, DS_LAS_USERATTR, 8))) { + if ( (0 == strncmp(s, DS_LAS_USERDNATTR, 10)) || + (0 == strncmp(s, DS_LAS_USERATTR, 8)) ) { /* ** For userdnattr/userattr rule, the resources changes and hence ** we cannot cache the result. See above for more comments. */ aci_item->aci_elevel = ACI_ELEVEL_USERDNATTR; - } else if ( 0== strncmp ( s, DS_LAS_USERDN, 6)) { + + rc = __aclp__copy_normalized_str(s, end, prevend, + &ret_str, &retstr_len, 0); + if (rc < 0) { + goto error; + } + } else if ( 0 == strncmp ( s, DS_LAS_USERDN, 6)) { p = strstr ( s, "="); p--; if ( strncmp (p, "!=", 2) == 0) @@ -699,22 +790,12 @@ normalize_nextACERule: * which would ensure that acl info is not cached from * one resource entry to the next. (bug 558519) */ - p = strstr ( p, "ldap"); - if (p == NULL) { - /* must start with ldap */ - if (s_acestr) slapi_ch_free ( (void **) &s_acestr ); - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return (NULL); - } - p += 8; /* for ldap:/// */ - if( __aclp__dn_normalize (p, end) == NULL) { - if (s_acestr) slapi_ch_free ( (void **) &s_acestr ); - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return (NULL); + rc = __aclp__copy_normalized_str(s, end, prevend, + &ret_str, &retstr_len, 1); + if (rc < 0) { + goto error; } - + /* we have a rule like userdn = "ldap:///blah". s points to blah now. ** let's find if we have a SELF rule like userdn = "ldap:///self". ** Since the resource changes on entry basis, we can't cache the @@ -750,6 +831,12 @@ normalize_nextACERule: aci_item->aci_elevel = ACI_ELEVEL_GROUPDNATTR; } aci_item->aci_ruleType |= ACI_GROUPDNATTR_RULE; + + rc = __aclp__copy_normalized_str(s, end, prevend, + &ret_str, &retstr_len, 0); + if (rc < 0) { + goto error; + } } else if ( 0 == strncmp ( s, DS_LAS_GROUPDN, 7)) { p = strstr ( s, "="); @@ -757,21 +844,12 @@ normalize_nextACERule: if ( strncmp (p, "!=", 2) == 0) aci_item->aci_type |= ACI_CONTAIN_NOT_GROUPDN; - p = strstr ( s, "ldap"); - if (p == NULL) { - /* must start with ldap */ - if (s_acestr) slapi_ch_free ( (void **) &s_acestr ); - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return (NULL); - } - p += 8; - if (__aclp__dn_normalize (p, end) == NULL) { - if (s_acestr) slapi_ch_free ( (void **) &s_acestr ); - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return (NULL); + rc = __aclp__copy_normalized_str(s, end, prevend, + &ret_str, &retstr_len, 1); + if (rc < 0) { + goto error; } + /* check for param rules */ __aclp_chk_paramRules ( aci_item, p, end ); @@ -786,21 +864,12 @@ normalize_nextACERule: if ( strncmp (p, "!=", 2) == 0) aci_item->aci_type |= ACI_CONTAIN_NOT_ROLEDN; - p = strstr ( s, "ldap"); - if (p == NULL) { - /* must start with ldap */ - if (s_acestr) slapi_ch_free ( (void **) &s_acestr ); - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return (NULL); - } - p += 8; - if (__aclp__dn_normalize (p, end) == NULL) { - if (s_acestr) slapi_ch_free ( (void **) &s_acestr ); - if (ret_str) slapi_ch_free ( (void **) &ret_str ); - slapi_ch_free ( (void **) &s_aclstr ); - return (NULL); + rc = __aclp__copy_normalized_str(s, end, prevend, + &ret_str, &retstr_len, 1); + if (rc < 0) { + goto error; } + /* check for param rules */ __aclp_chk_paramRules ( aci_item, p, end ); @@ -808,40 +877,47 @@ normalize_nextACERule: if ( aci_item->aci_elevel > ACI_ELEVEL_GROUPDN ) aci_item->aci_elevel = ACI_ELEVEL_GROUPDN;*/ aci_item->aci_ruleType |= ACI_ROLEDN_RULE; + } else { + /* adding the string no need to be processed + * (e.g., dns="lab.example.com)" */ + aclutil_str_append_ext(&ret_str, &retstr_len, + prevend, end - prevend); } + prevend = end; s = ++end; s = __aclp__getNextLASRule(aci_item, s, &end); - }/* while */ + if (NULL == s) { + /* adding the rest of the string, e.g. '\"' */ + aclutil_str_append_ext(&ret_str, &retstr_len, + prevend, strlen(prevend)); + } + } /* while */ - /* get the head of the string */ - acestr = s_acestr; - len = strlen( acestr); - ptr = acestr +len-1; - while (*ptr && *ptr != '\"' && *ptr != ')' ) *ptr-- = ' '; - ptr++; - *ptr = ';'; - - aclutil_str_appened (&ret_str, acestr); - if (s_acestr) { - slapi_ch_free ( (void **) &s_acestr ); - } - s_acestr = NULL; + slapi_ch_free_string (&s_acestr); + __acl_strip_trailing_space(ret_str); + aclutil_str_append_ext(&ret_str, &retstr_len, ";", 1); if (nextACE) { s = strstr (nextACE, "allow"); if (s == NULL) s = strstr (nextACE, "deny"); if (s == NULL) { if (nextACE && *nextACE != '\0') - aclutil_str_appened (&ret_str, nextACE); - slapi_ch_free ( (void **) &s_aclstr ); + aclutil_str_append (&ret_str, nextACE); + slapi_ch_free_string (&s_aclstr); return (ret_str); } acestr = nextACE; goto normalize_nextACERule; } - slapi_ch_free ( (void **) &s_aclstr ); + slapi_ch_free_string (&s_aclstr); return (ret_str); + +error: + slapi_ch_free_string (&ret_str); + slapi_ch_free_string (&s_aclstr); + slapi_ch_free_string (&s_acestr); + return NULL; } /* * @@ -857,7 +933,7 @@ __aclp__getNextLASRule (aci_t *aci_item, char *original_str , char **endOfCurrRu { char *newstr, *word, *next, *start, *end; char *ruleStart = NULL; - int len, ruleLen; + int len, ruleLen = 0; int in_dn_expr = 0; *endOfCurrRule = NULL; @@ -1029,43 +1105,7 @@ __aclp__getNextLASRule (aci_t *aci_item, char *original_str , char **endOfCurrRu return ( ruleStart ); } -/****************************************************************************** -* -* __aclp__dn_normalize -* -* Normalize the DN INPLACE. This routine is similar to slapi_dn_normalize() -* except various small stuff at the end. -* Normalize until the "end" and not to the end of string. -* -******************************************************************************/ -static char * -__aclp__dn_normalize( char *dn , char *end) -{ - char *d; - - if ((end - dn) < 0) { - return(NULL); - } - d = slapi_dn_normalize_to_end ( dn, end ); - - /* Do I have the quotes already */ - if (*d != '\"' ) { - /* - ** We are taking care of this situation - ** " ") ". We need to remove the space - ** infront and tack it after the quote like this. - ** "" ) ". - */ - - *d = '\"'; - d++; - while (*d && *d != '\"') *d++ = ' '; - *d = ' '; - } - - return( dn ); -} /*************************************************************************** * acl__get_aci_right * @@ -1263,6 +1303,7 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val) } while (str != 0 && *str != 0) { + int lenstr = 0; __acl_strip_leading_space(&str); @@ -1292,23 +1333,28 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val) attr = (Targetattr *) slapi_ch_malloc (sizeof (Targetattr)); memset (attr, 0, sizeof(Targetattr)); - if (strchr(str, '*')) { - + /* strip double quotes */ + lenstr = strlen(str); + if (*str == '"' && *(str + lenstr - 1) == '"') { + *(str + lenstr - 1) = '\0'; + str++; + } + if (strchr(str, '*')) { + /* It contains a * so it's something like * or cn* */ if (strcmp(str, "*" ) != 0) { char line[100]; char *lineptr = &line[0]; char *newline = NULL; - int lenstr = 0; struct slapi_filter *f = NULL; - if ((lenstr = strlen(str)) > 91) { /* 100 - 8 for "(attr =%s)" */ - newline = slapi_ch_malloc(lenstr + 9); + if (lenstr > 92) { /* 100 - 8 for "(attr=%s)\0" */ + newline = slapi_ch_malloc(lenstr + 8); lineptr = newline; } attr->attr_type = ACL_ATTR_FILTER; - sprintf (lineptr, "(attr =%s)", str); + sprintf (lineptr, "(attr=%s)", str); f = slapi_str2filter (lineptr); if (f == NULL) { @@ -1320,7 +1366,7 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val) if (newline) slapi_ch_free((void **) &newline); } else { - attr->attr_type = ACL_ATTR_STAR; + attr->attr_type = ACL_ATTR_STAR; attr->u.attr_str = slapi_ch_strdup (str); } diff --git a/ldap/servers/plugins/acl/aclproxy.c b/ldap/servers/plugins/acl/aclproxy.c index d40f543f..9b28489a 100644 --- a/ldap/servers/plugins/acl/aclproxy.c +++ b/ldap/servers/plugins/acl/aclproxy.c @@ -87,7 +87,9 @@ parse_LDAPProxyAuth(struct berval *spec_ber, int version, char **errtextp, LDAPProxyAuth *spec = NULL; BerElement *ber = NULL; char *errstring = "unable to parse proxied authorization control"; - + int rc = 0; + char *normed = NULL; + size_t dnlen = 0; BEGIN ber_tag_t tag; @@ -132,11 +134,20 @@ parse_LDAPProxyAuth(struct berval *spec_ber, int version, char **errtextp, errstring = "proxied authorization id must be a DN (dn:...)"; break; } - strcpy( spec->auth_dn, spec->auth_dn + 3 ); + /* memmove is safe for overlapping copy */ + memmove ( spec->auth_dn, spec->auth_dn + 3, strlen(spec->auth_dn) - 2);/* 1 for '\0' */ } - slapi_dn_normalize(spec->auth_dn); lderr = LDAP_SUCCESS; /* got it! */ + rc = slapi_dn_normalize_ext(spec->auth_dn, 0, &normed, &dnlen); + if (rc < 0) { + lderr = LDAP_INVALID_SYNTAX; + } else if (rc == 0) { /* spec->auth_dn is passed in; not terminated */ + *(normed + dnlen) = '\0'; + } else { + slapi_ch_free_string(&spec->auth_dn); + spec->auth_dn = normed; + } END /* Cleanup */ diff --git a/ldap/servers/plugins/acl/aclutil.c b/ldap/servers/plugins/acl/aclutil.c index 4aebd477..c0b8f579 100644 --- a/ldap/servers/plugins/acl/aclutil.c +++ b/ldap/servers/plugins/acl/aclutil.c @@ -65,7 +65,7 @@ static PRIntn acl_ht_display_entry(PLHashEntry *he, PRIntn i, void *arg); /* UTILITY FUNCTIONS */ /***************************************************************************/ int -aclutil_str_appened(char **str1, const char *str2) +aclutil_str_append(char **str1, const char *str2) { int new_len; @@ -87,6 +87,43 @@ aclutil_str_appened(char **str1, const char *str2) return(0); } +/* + * dlen: the length of the buffer *dest (not the string length in *dest) + */ +int +aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t slen) +{ + char *ptr = NULL; + int rc = 0; + + if ( dest == NULL || src == NULL ) { + return rc; + } + + if (0 == slen) { + slen = strlen(src); + } + if (*dest && dlen > 0) { + size_t dest_strlen = strlen(*dest); + size_t new_len = dest_strlen + slen + 1; + if (new_len > *dlen) { + *dest = (char *)slapi_ch_realloc(*dest, new_len); + *dlen = new_len; + ptr = *dest + dest_strlen; + } else { + ptr = *dest + dest_strlen; + } + } else { + *dlen = slen + 1; + *dest = (char *)slapi_ch_malloc(*dlen); + ptr = *dest; + } + memcpy(ptr, src, slen); + *(ptr + slen) = '\0'; + + return rc; +} + /***************************************************************************/ /* Print routines */ /***************************************************************************/ @@ -104,9 +141,14 @@ acl_print_acllib_err (NSErr_t *errp , char * str) aclErrorFmt(errp, msgbuf, ACLUTIL_ACLLIB_MSGBUF_LEN, 1); msgbuf[ACLUTIL_ACLLIB_MSGBUF_LEN-1] = '\0'; - if (msgbuf) - slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)(%s)\n", - msgbuf, str ? str: "NULL"); + if (strlen(msgbuf) > 0) { + slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)(%s)\n", + msgbuf, str ? str: "NULL"); + } else { + slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)\n", + str ? str: "NULL"); + } + } void aclutil_print_aci (aci_t *aci_item, char *type) @@ -240,7 +282,7 @@ aclutil_print_err (int rv , const Slapi_DN *sdn, const struct berval* val, if (errbuf) { /* If a buffer is provided, then copy the error */ - aclutil_str_appened(errbuf, lineptr ); + aclutil_str_append(errbuf, lineptr ); } slapi_log_error( SLAPI_LOG_FATAL, plugin_name, "%s", lineptr); @@ -436,7 +478,7 @@ acl_gen_err_msg(int access, char *edn, char *attr, char **errbuf) line = PR_smprintf( "Insufficient 'delete' privilege to delete the entry '%s'.\n",edn); } - aclutil_str_appened(errbuf, line ); + aclutil_str_append(errbuf, line ); if (line) { PR_smprintf_free(line); @@ -540,7 +582,7 @@ aclutil_expand_paramString ( char *str, Slapi_Entry *e ) goto cleanup; } *p = '\0'; - aclutil_str_appened ( &buf,a_dns[i]); + aclutil_str_append ( &buf,a_dns[i]); if ( type == 1 ) { /* xyz = $dn.o */ @@ -573,15 +615,15 @@ aclutil_expand_paramString ( char *str, Slapi_Entry *e ) kk= slapi_attr_next_value( attr, kk, &sval ); if ( kk != -1 ) /* can't handle multiple --error */ goto cleanup; + attrValue = slapi_value_get_berval ( t_sval ); + attrVal = attrValue->bv_val; } - attrValue = slapi_value_get_berval ( t_sval ); - attrVal = attrValue->bv_val; } } else { attrVal = a_dns[i]; } - aclutil_str_appened ( &buf, attrVal); - aclutil_str_appened ( &buf, ","); + aclutil_str_append ( &buf, attrVal); + aclutil_str_append ( &buf, ","); } rc = 0; /* everything is okay*/ /* remove the last comma */ @@ -607,7 +649,7 @@ __aclutil_extract_dn_component ( char **e_dns, int position, char *attrName ) int i, matched, len; char *s; - int matchedPosition; + int matchedPosition = 0; len = strlen ( attrName ); |