Back to index

openldap  2.4.31
slapacl.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 2004-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 2004 Pierangelo Masarati.
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 file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* ACKNOWLEDGEMENTS:
00017  * This work was initially developed by Pierangelo Masarati for inclusion
00018  * in OpenLDAP Software.
00019  */
00020 
00021 #include "portable.h"
00022 
00023 #include <stdio.h>
00024 
00025 #include <ac/stdlib.h>
00026 
00027 #include <ac/ctype.h>
00028 #include <ac/string.h>
00029 #include <ac/socket.h>
00030 #include <ac/unistd.h>
00031 
00032 #include <lber.h>
00033 #include <ldif.h>
00034 #include <lutil.h>
00035 
00036 #include "slapcommon.h"
00037 
00038 static int
00039 print_access(
00040        Operation            *op,
00041        Entry                *e,
00042        AttributeDescription *desc,
00043        struct berval        *val,
00044        struct berval        *nval )
00045 {
00046        int                  rc;
00047        slap_mask_t          mask;
00048        char                 accessmaskbuf[ACCESSMASK_MAXLEN];
00049 
00050        rc = access_allowed_mask( op, e, desc, nval, ACL_AUTH, NULL, &mask );
00051 
00052        fprintf( stderr, "%s%s%s: %s\n",
00053                      desc->ad_cname.bv_val,
00054                      ( val && !BER_BVISNULL( val ) ) ? "=" : "",
00055                      ( val && !BER_BVISNULL( val ) ) ?
00056                             ( desc == slap_schema.si_ad_userPassword ?
00057                                    "****" : val->bv_val ) : "",
00058                      accessmask2str( mask, accessmaskbuf, 1 ) );
00059 
00060        return rc;
00061 }
00062 
00063 int
00064 slapacl( int argc, char **argv )
00065 {
00066        int                  rc = EXIT_SUCCESS;
00067        const char           *progname = "slapacl";
00068        Connection           conn = { 0 };
00069        Listener             listener;
00070        OperationBuffer      opbuf;
00071        Operation            *op = NULL;
00072        Entry                e = { 0 }, *ep = &e;
00073        char                 *attr = NULL;
00074        int                  doclose = 0;
00075        BackendDB            *bd;
00076        void                 *thrctx;
00077 
00078        slap_tool_init( progname, SLAPACL, argc, argv );
00079 
00080        if ( !dryrun ) {
00081               int    i = 0;
00082 
00083               LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
00084                      if ( bd != be && backend_startup( bd ) ) {
00085                             fprintf( stderr, "backend_startup(#%d%s%s) failed\n",
00086                                           i,
00087                                           bd->be_suffix ? ": " : "",
00088                                           bd->be_suffix ? bd->be_suffix[0].bv_val : "" );
00089                             rc = 1;
00090                             goto destroy;
00091                      }
00092 
00093                      i++;
00094               }
00095        }
00096 
00097        argv = &argv[ optind ];
00098        argc -= optind;
00099 
00100        thrctx = ldap_pvt_thread_pool_context();
00101        connection_fake_init( &conn, &opbuf, thrctx );
00102        op = &opbuf.ob_op;
00103        op->o_tmpmemctx = NULL;
00104 
00105        conn.c_listener = &listener;
00106        conn.c_listener_url = listener_url;
00107        conn.c_peer_domain = peer_domain;
00108        conn.c_peer_name = peer_name;
00109        conn.c_sock_name = sock_name;
00110        op->o_ssf = ssf;
00111        op->o_transport_ssf = transport_ssf;
00112        op->o_tls_ssf = tls_ssf;
00113        op->o_sasl_ssf = sasl_ssf;
00114 
00115        if ( !BER_BVISNULL( &authcID ) ) {
00116               if ( !BER_BVISNULL( &authcDN ) ) {
00117                      fprintf( stderr, "both authcID=\"%s\" "
00118                                    "and authcDN=\"%s\" provided\n",
00119                                    authcID.bv_val, authcDN.bv_val );
00120                      rc = 1;
00121                      goto destroy;
00122               }
00123 
00124               rc = slap_sasl_getdn( &conn, op, &authcID, NULL,
00125                             &authcDN, SLAP_GETDN_AUTHCID );
00126               if ( rc != LDAP_SUCCESS ) {
00127                      fprintf( stderr, "authcID: <%s> check failed %d (%s)\n",
00128                                    authcID.bv_val, rc,
00129                                    ldap_err2string( rc ) );
00130                      rc = 1;
00131                      goto destroy;
00132               }
00133 
00134        } else if ( !BER_BVISNULL( &authcDN ) ) {
00135               struct berval ndn;
00136 
00137               rc = dnNormalize( 0, NULL, NULL, &authcDN, &ndn, NULL );
00138               if ( rc != LDAP_SUCCESS ) {
00139                      fprintf( stderr, "autchDN=\"%s\" normalization failed %d (%s)\n",
00140                                    authcDN.bv_val, rc,
00141                                    ldap_err2string( rc ) );
00142                      rc = 1;
00143                      goto destroy;
00144               }
00145               ch_free( authcDN.bv_val );
00146               authcDN = ndn;
00147        }
00148 
00149        if ( !BER_BVISNULL( &authzID ) ) {
00150               if ( !BER_BVISNULL( &authzDN ) ) {
00151                      fprintf( stderr, "both authzID=\"%s\" "
00152                                    "and authzDN=\"%s\" provided\n",
00153                                    authzID.bv_val, authzDN.bv_val );
00154                      rc = 1;
00155                      goto destroy;
00156               }
00157 
00158               rc = slap_sasl_getdn( &conn, op, &authzID, NULL,
00159                             &authzDN, SLAP_GETDN_AUTHZID );
00160               if ( rc != LDAP_SUCCESS ) {
00161                      fprintf( stderr, "authzID: <%s> check failed %d (%s)\n",
00162                                    authzID.bv_val, rc,
00163                                    ldap_err2string( rc ) );
00164                      rc = 1;
00165                      goto destroy;
00166               }
00167 
00168        } else if ( !BER_BVISNULL( &authzDN ) ) {
00169               struct berval ndn;
00170 
00171               rc = dnNormalize( 0, NULL, NULL, &authzDN, &ndn, NULL );
00172               if ( rc != LDAP_SUCCESS ) {
00173                      fprintf( stderr, "autchDN=\"%s\" normalization failed %d (%s)\n",
00174                                    authzDN.bv_val, rc,
00175                                    ldap_err2string( rc ) );
00176                      rc = 1;
00177                      goto destroy;
00178               }
00179               ch_free( authzDN.bv_val );
00180               authzDN = ndn;
00181        }
00182 
00183 
00184        if ( !BER_BVISNULL( &authcDN ) ) {
00185               fprintf( stderr, "authcDN: \"%s\"\n", authcDN.bv_val );
00186        }
00187 
00188        if ( !BER_BVISNULL( &authzDN ) ) {
00189               fprintf( stderr, "authzDN: \"%s\"\n", authzDN.bv_val );
00190        }
00191 
00192        if ( !BER_BVISNULL( &authzDN ) ) {
00193               op->o_dn = authzDN;
00194               op->o_ndn = authzDN;
00195               
00196               if ( !BER_BVISNULL( &authcDN ) ) {
00197                      op->o_conn->c_dn = authcDN;
00198                      op->o_conn->c_ndn = authcDN;
00199 
00200               } else {
00201                      op->o_conn->c_dn = authzDN;
00202                      op->o_conn->c_ndn = authzDN;
00203               }
00204 
00205        } else if ( !BER_BVISNULL( &authcDN ) ) {
00206               op->o_conn->c_dn = authcDN;
00207               op->o_conn->c_ndn = authcDN;
00208               op->o_dn = authcDN;
00209               op->o_ndn = authcDN;
00210        }
00211 
00212        assert( !BER_BVISNULL( &baseDN ) );
00213        rc = dnPrettyNormal( NULL, &baseDN, &e.e_name, &e.e_nname, NULL );
00214        if ( rc != LDAP_SUCCESS ) {
00215               fprintf( stderr, "base=\"%s\" normalization failed %d (%s)\n",
00216                             baseDN.bv_val, rc,
00217                             ldap_err2string( rc ) );
00218               rc = 1;
00219               goto destroy;
00220        }
00221 
00222        op->o_bd = be;
00223        if ( op->o_bd == NULL ) {
00224               /* NOTE: if no database could be found (e.g. because
00225                * accessing the rootDSE or so), use the frontendDB
00226                * rules; might need work */
00227               op->o_bd = frontendDB;
00228        }
00229 
00230        if ( !dryrun ) {
00231               ID     id;
00232 
00233               if ( be == NULL ) {
00234                      fprintf( stderr, "%s: no target database "
00235                             "has been found for baseDN=\"%s\"; "
00236                             "you may try with \"-u\" (dry run).\n",
00237                             baseDN.bv_val, progname );
00238                      rc = 1;
00239                      goto destroy;
00240               }
00241 
00242               if ( !be->be_entry_open ||
00243                      !be->be_entry_close ||
00244                      !be->be_dn2id_get ||
00245                      !be->be_entry_get )
00246               {
00247                      fprintf( stderr, "%s: target database "
00248                             "doesn't support necessary operations; "
00249                             "you may try with \"-u\" (dry run).\n",
00250                             progname );
00251                      rc = 1;
00252                      goto destroy;
00253               }
00254 
00255               if ( be->be_entry_open( be, 0 ) != 0 ) {
00256                      fprintf( stderr, "%s: could not open database.\n",
00257                             progname );
00258                      rc = 1;
00259                      goto destroy;
00260               }
00261 
00262               doclose = 1;
00263 
00264               id = be->be_dn2id_get( be, &e.e_nname );
00265               if ( id == NOID ) {
00266                      fprintf( stderr, "%s: unable to fetch ID of DN \"%s\"\n",
00267                             progname, e.e_nname.bv_val );
00268                      rc = 1;
00269                      goto destroy;
00270               }
00271               ep = be->be_entry_get( be, id );
00272               if ( ep == NULL ) {
00273                      fprintf( stderr, "%s: unable to fetch entry \"%s\" (%lu)\n",
00274                             progname, e.e_nname.bv_val, id );
00275                      rc = 1;
00276                      goto destroy;
00277 
00278               }
00279 
00280               if ( argc == 0 ) {
00281                      Attribute     *a;
00282 
00283                      (void)print_access( op, ep, slap_schema.si_ad_entry, NULL, NULL );
00284                      (void)print_access( op, ep, slap_schema.si_ad_children, NULL, NULL );
00285 
00286                      for ( a = ep->e_attrs; a; a = a->a_next ) {
00287                             int    i;
00288 
00289                             for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
00290                                    (void)print_access( op, ep, a->a_desc,
00291                                                  &a->a_vals[ i ],
00292                                                  &a->a_nvals[ i ] );
00293                             }
00294                      }
00295               }
00296        }
00297 
00298        for ( ; argc--; argv++ ) {
00299               slap_mask_t          mask;
00300               AttributeDescription *desc = NULL;
00301               struct berval        val = BER_BVNULL,
00302                                    *valp = NULL;
00303               const char           *text;
00304               char                 accessmaskbuf[ACCESSMASK_MAXLEN];
00305               char                 *accessstr;
00306               slap_access_t        access = ACL_AUTH;
00307 
00308               if ( attr == NULL ) {
00309                      attr = argv[ 0 ];
00310               }
00311 
00312               val.bv_val = strchr( attr, ':' );
00313               if ( val.bv_val != NULL ) {
00314                      val.bv_val[0] = '\0';
00315                      val.bv_val++;
00316                      val.bv_len = strlen( val.bv_val );
00317                      valp = &val;
00318               }
00319 
00320               accessstr = strchr( attr, '/' );
00321               if ( accessstr != NULL ) {
00322                      int    invalid = 0;
00323 
00324                      accessstr[0] = '\0';
00325                      accessstr++;
00326                      access = str2access( accessstr );
00327                      switch ( access ) {
00328                      case ACL_INVALID_ACCESS:
00329                             fprintf( stderr, "unknown access \"%s\" for attribute \"%s\"\n",
00330                                           accessstr, attr );
00331                             invalid = 1;
00332                             break;
00333 
00334                      case ACL_NONE:
00335                             fprintf( stderr, "\"none\" not allowed for attribute \"%s\"\n",
00336                                           attr );
00337                             invalid = 1;
00338                             break;
00339 
00340                      default:
00341                             break;
00342                      }
00343 
00344                      if ( invalid ) {
00345                             if ( continuemode ) {
00346                                    continue;
00347                             }
00348                             break;
00349                      }
00350               }
00351 
00352               rc = slap_str2ad( attr, &desc, &text );
00353               if ( rc != LDAP_SUCCESS ) {
00354                      fprintf( stderr, "slap_str2ad(%s) failed %d (%s)\n",
00355                                    attr, rc, ldap_err2string( rc ) );
00356                      if ( continuemode ) {
00357                             continue;
00358                      }
00359                      break;
00360               }
00361 
00362               rc = access_allowed_mask( op, ep, desc, valp, access,
00363                             NULL, &mask );
00364 
00365               if ( accessstr ) {
00366                      fprintf( stderr, "%s access to %s%s%s: %s\n",
00367                                    accessstr,
00368                                    desc->ad_cname.bv_val,
00369                                    val.bv_val ? "=" : "",
00370                                    val.bv_val ? val.bv_val : "",
00371                                    rc ? "ALLOWED" : "DENIED" );
00372 
00373               } else {
00374                      fprintf( stderr, "%s%s%s: %s\n",
00375                                    desc->ad_cname.bv_val,
00376                                    val.bv_val ? "=" : "",
00377                                    val.bv_val ? val.bv_val : "",
00378                                    accessmask2str( mask, accessmaskbuf, 1 ) );
00379               }
00380               rc = 0;
00381               attr = NULL;
00382        }
00383 
00384 destroy:;
00385        if ( !BER_BVISNULL( &e.e_name ) ) {
00386               ber_memfree( e.e_name.bv_val );
00387        }
00388        if ( !BER_BVISNULL( &e.e_nname ) ) {
00389               ber_memfree( e.e_nname.bv_val );
00390        }
00391        if ( !dryrun && be ) {
00392               if ( ep && ep != &e ) {
00393                      be_entry_release_r( op, ep );
00394               }
00395               if ( doclose ) {
00396                      be->be_entry_close( be );
00397               }
00398 
00399               LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
00400                      if ( bd != be ) {
00401                             backend_shutdown( bd );
00402                      }
00403               }
00404        }
00405 
00406        if ( slap_tool_destroy())
00407               rc = EXIT_FAILURE;
00408 
00409        return rc;
00410 }
00411