Back to index

openldap  2.4.31
posixgroup.c
Go to the documentation of this file.
00001 /* posixgroup.c */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include <portable.h>
00018 
00019 #include <ac/string.h>
00020 #include <slap.h>
00021 #include <lutil.h>
00022 
00023 /* Need dynacl... */
00024 
00025 #ifdef SLAP_DYNACL
00026 
00027 typedef struct pg_t {
00028        slap_style_t         pg_style;
00029        struct berval        pg_pat;
00030 } pg_t;
00031 
00032 static ObjectClass          *pg_posixGroup;
00033 static AttributeDescription *pg_memberUid;
00034 static ObjectClass          *pg_posixAccount;
00035 static AttributeDescription *pg_uidNumber;
00036 
00037 static int pg_dynacl_destroy( void *priv );
00038 
00039 static int
00040 pg_dynacl_parse(
00041        const char    *fname,
00042        int           lineno,
00043        const char    *opts,
00044        slap_style_t  style,
00045        const char    *pattern,
00046        void          **privp )
00047 {
00048        pg_t          *pg;
00049        int           rc;
00050        const char    *text = NULL;
00051        struct berval pat;
00052 
00053        ber_str2bv( pattern, 0, 0, &pat );
00054 
00055        pg = ch_calloc( 1, sizeof( pg_t ) );
00056 
00057        pg->pg_style = style;
00058 
00059        switch ( pg->pg_style ) {
00060        case ACL_STYLE_BASE:
00061               rc = dnNormalize( 0, NULL, NULL, &pat, &pg->pg_pat, NULL );
00062               if ( rc != LDAP_SUCCESS ) {
00063                      fprintf( stderr, "%s line %d: posixGroup ACL: "
00064                             "unable to normalize DN \"%s\".\n",
00065                             fname, lineno, pattern );
00066                      goto cleanup;
00067               }
00068               break;
00069 
00070        case ACL_STYLE_EXPAND:
00071               ber_dupbv( &pg->pg_pat, &pat );
00072               break;
00073 
00074        default:
00075               fprintf( stderr, "%s line %d: posixGroup ACL: "
00076                      "unsupported style \"%s\".\n",
00077                      fname, lineno, style_strings[ pg->pg_style ] );
00078               goto cleanup;
00079        }
00080 
00081        /* TODO: use opts to allow the use of different
00082         * group objects and member attributes */
00083        if ( pg_posixGroup == NULL ) {
00084               pg_posixGroup = oc_find( "posixGroup" );
00085               if ( pg_posixGroup == NULL ) {
00086                      fprintf( stderr, "%s line %d: posixGroup ACL: "
00087                             "unable to lookup \"posixGroup\" "
00088                             "objectClass.\n",
00089                             fname, lineno );
00090                      goto cleanup;
00091               }
00092 
00093               pg_posixAccount = oc_find( "posixAccount" );
00094               if ( pg_posixGroup == NULL ) {
00095                      fprintf( stderr, "%s line %d: posixGroup ACL: "
00096                             "unable to lookup \"posixAccount\" "
00097                             "objectClass.\n",
00098                             fname, lineno );
00099                      goto cleanup;
00100               }
00101 
00102               rc = slap_str2ad( "memberUid", &pg_memberUid, &text );
00103               if ( rc != LDAP_SUCCESS ) {
00104                      fprintf( stderr, "%s line %d: posixGroup ACL: "
00105                             "unable to lookup \"memberUid\" "
00106                             "attributeDescription (%d: %s).\n",
00107                             fname, lineno, rc, text );
00108                      goto cleanup;
00109               }
00110 
00111               rc = slap_str2ad( "uidNumber", &pg_uidNumber, &text );
00112               if ( rc != LDAP_SUCCESS ) {
00113                      fprintf( stderr, "%s line %d: posixGroup ACL: "
00114                             "unable to lookup \"uidNumber\" "
00115                             "attributeDescription (%d: %s).\n",
00116                             fname, lineno, rc, text );
00117                      goto cleanup;
00118               }
00119        }
00120 
00121        *privp = (void *)pg;
00122        return 0;
00123 
00124 cleanup:
00125        (void)pg_dynacl_destroy( (void *)pg );
00126 
00127        return 1;
00128 }
00129 
00130 static int
00131 pg_dynacl_unparse(
00132        void          *priv,
00133        struct berval *bv )
00134 {
00135        pg_t          *pg = (pg_t *)priv;
00136        char          *ptr;
00137 
00138        bv->bv_len = STRLENOF( " dynacl/posixGroup.expand=" ) + pg->pg_pat.bv_len;
00139        bv->bv_val = ch_malloc( bv->bv_len + 1 );
00140 
00141        ptr = lutil_strcopy( bv->bv_val, " dynacl/posixGroup" );
00142 
00143        switch ( pg->pg_style ) {
00144        case ACL_STYLE_BASE:
00145               ptr = lutil_strcopy( ptr, ".exact=" );
00146               break;
00147 
00148        case ACL_STYLE_EXPAND:
00149               ptr = lutil_strcopy( ptr, ".expand=" );
00150               break;
00151 
00152        default:
00153               assert( 0 );
00154        }
00155 
00156        ptr = lutil_strncopy( ptr, pg->pg_pat.bv_val, pg->pg_pat.bv_len );
00157        ptr[ 0 ] = '\0';
00158 
00159        bv->bv_len = ptr - bv->bv_val;
00160 
00161        return 0;
00162 }
00163 
00164 static int
00165 pg_dynacl_mask(
00166        void                 *priv,
00167        Operation            *op,
00168        Entry                *target,
00169        AttributeDescription *desc,
00170        struct berval        *val,
00171        int                  nmatch,
00172        regmatch_t           *matches,
00173        slap_access_t        *grant,
00174        slap_access_t        *deny )
00175 {
00176        pg_t          *pg = (pg_t *)priv;
00177        Entry         *group = NULL,
00178                      *user = NULL;
00179        int           rc;
00180        Backend              *be = op->o_bd,
00181                      *group_be = NULL,
00182                      *user_be = NULL;
00183        struct berval group_ndn;
00184 
00185        ACL_INVALIDATE( *deny );
00186 
00187        /* get user */
00188        if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) {
00189               user = target;
00190               rc = LDAP_SUCCESS;
00191 
00192        } else {
00193               user_be = op->o_bd = select_backend( &op->o_ndn, 0 );
00194               if ( op->o_bd == NULL ) {
00195                      op->o_bd = be;
00196                      return 0;
00197               }
00198               rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user );
00199        }
00200 
00201        if ( rc != LDAP_SUCCESS || user == NULL ) {
00202               op->o_bd = be;
00203               return 0;
00204        }
00205 
00206        /* get target */
00207        if ( pg->pg_style == ACL_STYLE_EXPAND ) {
00208               char          buf[ 1024 ];
00209               struct berval bv;
00210               AclRegexMatches amatches = { 0 };
00211 
00212               amatches.dn_count = nmatch;
00213               AC_MEMCPY( amatches.dn_data, matches, sizeof( amatches.dn_data ) );
00214 
00215               bv.bv_len = sizeof( buf ) - 1;
00216               bv.bv_val = buf;
00217 
00218               if ( acl_string_expand( &bv, &pg->pg_pat,
00219                             &target->e_nname,
00220                             NULL, &amatches ) )
00221               {
00222                      goto cleanup;
00223               }
00224 
00225               if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn,
00226                             op->o_tmpmemctx ) != LDAP_SUCCESS )
00227               {
00228                      /* did not expand to a valid dn */
00229                      goto cleanup;
00230               }
00231               
00232        } else {
00233               group_ndn = pg->pg_pat;
00234        }
00235 
00236        if ( target && dn_match( &target->e_nname, &group_ndn ) ) {
00237               group = target;
00238               rc = LDAP_SUCCESS;
00239 
00240        } else {
00241               group_be = op->o_bd = select_backend( &group_ndn, 0 );
00242               if ( op->o_bd == NULL ) {
00243                      goto cleanup;
00244               }
00245               rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group );
00246        }
00247 
00248        if ( group_ndn.bv_val != pg->pg_pat.bv_val ) {
00249               op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx );
00250        }
00251 
00252        if ( rc == LDAP_SUCCESS && group != NULL ) {
00253               Attribute     *a_uid,
00254                             *a_member;
00255 
00256               a_uid = attr_find( user->e_attrs, pg_uidNumber );
00257               if ( !a_uid || !BER_BVISNULL( &a_uid->a_nvals[ 1 ] ) ) {
00258                      rc = LDAP_NO_SUCH_ATTRIBUTE;
00259 
00260               } else {
00261                      a_member = attr_find( group->e_attrs, pg_memberUid );
00262                      if ( !a_member ) {
00263                             rc = LDAP_NO_SUCH_ATTRIBUTE;
00264 
00265                      } else {
00266                             rc = value_find_ex( pg_memberUid,
00267                                    SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
00268                                    SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
00269                                    a_member->a_nvals, &a_uid->a_nvals[ 0 ],
00270                                    op->o_tmpmemctx );
00271                      }
00272               }
00273 
00274        } else {
00275               rc = LDAP_NO_SUCH_OBJECT;
00276        }
00277 
00278 
00279        if ( rc == LDAP_SUCCESS ) {
00280               ACL_LVL_ASSIGN_WRITE( *grant );
00281        }
00282 
00283 cleanup:;
00284        if ( group != NULL && group != target ) {
00285               op->o_bd = group_be;
00286               be_entry_release_r( op, group );
00287               op->o_bd = be;
00288        }
00289 
00290        if ( user != NULL && user != target ) {
00291               op->o_bd = user_be;
00292               be_entry_release_r( op, user );
00293               op->o_bd = be;
00294        }
00295 
00296        return 0;
00297 }
00298 
00299 static int
00300 pg_dynacl_destroy(
00301        void          *priv )
00302 {
00303        pg_t          *pg = (pg_t *)priv;
00304 
00305        if ( pg != NULL ) {
00306               if ( !BER_BVISNULL( &pg->pg_pat ) ) {
00307                      ber_memfree( pg->pg_pat.bv_val );
00308               }
00309               ch_free( pg );
00310        }
00311 
00312        return 0;
00313 }
00314 
00315 static struct slap_dynacl_t pg_dynacl = {
00316        "posixGroup",
00317        pg_dynacl_parse,
00318        pg_dynacl_unparse,
00319        pg_dynacl_mask,
00320        pg_dynacl_destroy
00321 };
00322 
00323 int
00324 init_module( int argc, char *argv[] )
00325 {
00326        return slap_dynacl_register( &pg_dynacl );
00327 }
00328 
00329 #endif /* SLAP_DYNACL */