1/* $NetBSD: slapacl.c,v 1.1.1.3 2010/12/12 15:22:47 adam Exp $ */ 2 3/* OpenLDAP: pkg/ldap/servers/slapd/slapacl.c,v 1.24.2.11 2010/04/13 20:23:20 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 2004-2010 The OpenLDAP Foundation. 7 * Portions Copyright 2004 Pierangelo Masarati. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18/* ACKNOWLEDGEMENTS: 19 * This work was initially developed by Pierangelo Masarati for inclusion 20 * in OpenLDAP Software. 21 */ 22 23#include "portable.h" 24 25#include <stdio.h> 26 27#include <ac/stdlib.h> 28 29#include <ac/ctype.h> 30#include <ac/string.h> 31#include <ac/socket.h> 32#include <ac/unistd.h> 33 34#include <lber.h> 35#include <ldif.h> 36#include <lutil.h> 37 38#include "slapcommon.h" 39 40static int 41print_access( 42 Operation *op, 43 Entry *e, 44 AttributeDescription *desc, 45 struct berval *val, 46 struct berval *nval ) 47{ 48 int rc; 49 slap_mask_t mask; 50 char accessmaskbuf[ACCESSMASK_MAXLEN]; 51 52 rc = access_allowed_mask( op, e, desc, nval, ACL_AUTH, NULL, &mask ); 53 54 fprintf( stderr, "%s%s%s: %s\n", 55 desc->ad_cname.bv_val, 56 ( val && !BER_BVISNULL( val ) ) ? "=" : "", 57 ( val && !BER_BVISNULL( val ) ) ? 58 ( desc == slap_schema.si_ad_userPassword ? 59 "****" : val->bv_val ) : "", 60 accessmask2str( mask, accessmaskbuf, 1 ) ); 61 62 return rc; 63} 64 65int 66slapacl( int argc, char **argv ) 67{ 68 int rc = EXIT_SUCCESS; 69 const char *progname = "slapacl"; 70 Connection conn = { 0 }; 71 Listener listener; 72 OperationBuffer opbuf; 73 Operation *op = NULL; 74 Entry e = { 0 }, *ep = &e; 75 char *attr = NULL; 76 int doclose = 0; 77 BackendDB *bd; 78 void *thrctx; 79 80 slap_tool_init( progname, SLAPACL, argc, argv ); 81 82 if ( !dryrun ) { 83 int i = 0; 84 85 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) { 86 if ( bd != be && backend_startup( bd ) ) { 87 fprintf( stderr, "backend_startup(#%d%s%s) failed\n", 88 i, 89 bd->be_suffix ? ": " : "", 90 bd->be_suffix ? bd->be_suffix[0].bv_val : "" ); 91 rc = 1; 92 goto destroy; 93 } 94 95 i++; 96 } 97 } 98 99 argv = &argv[ optind ]; 100 argc -= optind; 101 102 thrctx = ldap_pvt_thread_pool_context(); 103 connection_fake_init( &conn, &opbuf, thrctx ); 104 op = &opbuf.ob_op; 105 op->o_tmpmemctx = NULL; 106 107 conn.c_listener = &listener; 108 conn.c_listener_url = listener_url; 109 conn.c_peer_domain = peer_domain; 110 conn.c_peer_name = peer_name; 111 conn.c_sock_name = sock_name; 112 op->o_ssf = ssf; 113 op->o_transport_ssf = transport_ssf; 114 op->o_tls_ssf = tls_ssf; 115 op->o_sasl_ssf = sasl_ssf; 116 117 if ( !BER_BVISNULL( &authcID ) ) { 118 if ( !BER_BVISNULL( &authcDN ) ) { 119 fprintf( stderr, "both authcID=\"%s\" " 120 "and authcDN=\"%s\" provided\n", 121 authcID.bv_val, authcDN.bv_val ); 122 rc = 1; 123 goto destroy; 124 } 125 126 rc = slap_sasl_getdn( &conn, op, &authcID, NULL, 127 &authcDN, SLAP_GETDN_AUTHCID ); 128 if ( rc != LDAP_SUCCESS ) { 129 fprintf( stderr, "authcID: <%s> check failed %d (%s)\n", 130 authcID.bv_val, rc, 131 ldap_err2string( rc ) ); 132 rc = 1; 133 goto destroy; 134 } 135 136 } else if ( !BER_BVISNULL( &authcDN ) ) { 137 struct berval ndn; 138 139 rc = dnNormalize( 0, NULL, NULL, &authcDN, &ndn, NULL ); 140 if ( rc != LDAP_SUCCESS ) { 141 fprintf( stderr, "autchDN=\"%s\" normalization failed %d (%s)\n", 142 authcDN.bv_val, rc, 143 ldap_err2string( rc ) ); 144 rc = 1; 145 goto destroy; 146 } 147 ch_free( authcDN.bv_val ); 148 authcDN = ndn; 149 } 150 151 if ( !BER_BVISNULL( &authzID ) ) { 152 if ( !BER_BVISNULL( &authzDN ) ) { 153 fprintf( stderr, "both authzID=\"%s\" " 154 "and authzDN=\"%s\" provided\n", 155 authzID.bv_val, authzDN.bv_val ); 156 rc = 1; 157 goto destroy; 158 } 159 160 rc = slap_sasl_getdn( &conn, op, &authzID, NULL, 161 &authzDN, SLAP_GETDN_AUTHZID ); 162 if ( rc != LDAP_SUCCESS ) { 163 fprintf( stderr, "authzID: <%s> check failed %d (%s)\n", 164 authzID.bv_val, rc, 165 ldap_err2string( rc ) ); 166 rc = 1; 167 goto destroy; 168 } 169 170 } else if ( !BER_BVISNULL( &authzDN ) ) { 171 struct berval ndn; 172 173 rc = dnNormalize( 0, NULL, NULL, &authzDN, &ndn, NULL ); 174 if ( rc != LDAP_SUCCESS ) { 175 fprintf( stderr, "autchDN=\"%s\" normalization failed %d (%s)\n", 176 authzDN.bv_val, rc, 177 ldap_err2string( rc ) ); 178 rc = 1; 179 goto destroy; 180 } 181 ch_free( authzDN.bv_val ); 182 authzDN = ndn; 183 } 184 185 186 if ( !BER_BVISNULL( &authcDN ) ) { 187 fprintf( stderr, "authcDN: \"%s\"\n", authcDN.bv_val ); 188 } 189 190 if ( !BER_BVISNULL( &authzDN ) ) { 191 fprintf( stderr, "authzDN: \"%s\"\n", authzDN.bv_val ); 192 } 193 194 if ( !BER_BVISNULL( &authzDN ) ) { 195 op->o_dn = authzDN; 196 op->o_ndn = authzDN; 197 198 if ( !BER_BVISNULL( &authcDN ) ) { 199 op->o_conn->c_dn = authcDN; 200 op->o_conn->c_ndn = authcDN; 201 202 } else { 203 op->o_conn->c_dn = authzDN; 204 op->o_conn->c_ndn = authzDN; 205 } 206 207 } else if ( !BER_BVISNULL( &authcDN ) ) { 208 op->o_conn->c_dn = authcDN; 209 op->o_conn->c_ndn = authcDN; 210 op->o_dn = authcDN; 211 op->o_ndn = authcDN; 212 } 213 214 assert( !BER_BVISNULL( &baseDN ) ); 215 rc = dnPrettyNormal( NULL, &baseDN, &e.e_name, &e.e_nname, NULL ); 216 if ( rc != LDAP_SUCCESS ) { 217 fprintf( stderr, "base=\"%s\" normalization failed %d (%s)\n", 218 baseDN.bv_val, rc, 219 ldap_err2string( rc ) ); 220 rc = 1; 221 goto destroy; 222 } 223 224 op->o_bd = be; 225 if ( op->o_bd == NULL ) { 226 /* NOTE: if no database could be found (e.g. because 227 * accessing the rootDSE or so), use the frontendDB 228 * rules; might need work */ 229 op->o_bd = frontendDB; 230 } 231 232 if ( !dryrun ) { 233 ID id; 234 235 if ( be == NULL ) { 236 fprintf( stderr, "%s: no target database " 237 "has been found for baseDN=\"%s\"; " 238 "you may try with \"-u\" (dry run).\n", 239 baseDN.bv_val, progname ); 240 rc = 1; 241 goto destroy; 242 } 243 244 if ( !be->be_entry_open || 245 !be->be_entry_close || 246 !be->be_dn2id_get || 247 !be->be_entry_get ) 248 { 249 fprintf( stderr, "%s: target database " 250 "doesn't support necessary operations; " 251 "you may try with \"-u\" (dry run).\n", 252 progname ); 253 rc = 1; 254 goto destroy; 255 } 256 257 if ( be->be_entry_open( be, 0 ) != 0 ) { 258 fprintf( stderr, "%s: could not open database.\n", 259 progname ); 260 rc = 1; 261 goto destroy; 262 } 263 264 doclose = 1; 265 266 id = be->be_dn2id_get( be, &e.e_nname ); 267 if ( id == NOID ) { 268 fprintf( stderr, "%s: unable to fetch ID of DN \"%s\"\n", 269 progname, e.e_nname.bv_val ); 270 rc = 1; 271 goto destroy; 272 } 273 ep = be->be_entry_get( be, id ); 274 if ( ep == NULL ) { 275 fprintf( stderr, "%s: unable to fetch entry \"%s\" (%lu)\n", 276 progname, e.e_nname.bv_val, id ); 277 rc = 1; 278 goto destroy; 279 280 } 281 282 if ( argc == 0 ) { 283 Attribute *a; 284 285 (void)print_access( op, ep, slap_schema.si_ad_entry, NULL, NULL ); 286 (void)print_access( op, ep, slap_schema.si_ad_children, NULL, NULL ); 287 288 for ( a = ep->e_attrs; a; a = a->a_next ) { 289 int i; 290 291 for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) { 292 (void)print_access( op, ep, a->a_desc, 293 &a->a_vals[ i ], 294 &a->a_nvals[ i ] ); 295 } 296 } 297 } 298 } 299 300 for ( ; argc--; argv++ ) { 301 slap_mask_t mask; 302 AttributeDescription *desc = NULL; 303 struct berval val = BER_BVNULL, 304 *valp = NULL; 305 const char *text; 306 char accessmaskbuf[ACCESSMASK_MAXLEN]; 307 char *accessstr; 308 slap_access_t access = ACL_AUTH; 309 310 if ( attr == NULL ) { 311 attr = argv[ 0 ]; 312 } 313 314 val.bv_val = strchr( attr, ':' ); 315 if ( val.bv_val != NULL ) { 316 val.bv_val[0] = '\0'; 317 val.bv_val++; 318 val.bv_len = strlen( val.bv_val ); 319 valp = &val; 320 } 321 322 accessstr = strchr( attr, '/' ); 323 if ( accessstr != NULL ) { 324 int invalid = 0; 325 326 accessstr[0] = '\0'; 327 accessstr++; 328 access = str2access( accessstr ); 329 switch ( access ) { 330 case ACL_INVALID_ACCESS: 331 fprintf( stderr, "unknown access \"%s\" for attribute \"%s\"\n", 332 accessstr, attr ); 333 invalid = 1; 334 break; 335 336 case ACL_NONE: 337 fprintf( stderr, "\"none\" not allowed for attribute \"%s\"\n", 338 attr ); 339 invalid = 1; 340 break; 341 342 default: 343 break; 344 } 345 346 if ( invalid ) { 347 if ( continuemode ) { 348 continue; 349 } 350 break; 351 } 352 } 353 354 rc = slap_str2ad( attr, &desc, &text ); 355 if ( rc != LDAP_SUCCESS ) { 356 fprintf( stderr, "slap_str2ad(%s) failed %d (%s)\n", 357 attr, rc, ldap_err2string( rc ) ); 358 if ( continuemode ) { 359 continue; 360 } 361 break; 362 } 363 364 rc = access_allowed_mask( op, ep, desc, valp, access, 365 NULL, &mask ); 366 367 if ( accessstr ) { 368 fprintf( stderr, "%s access to %s%s%s: %s\n", 369 accessstr, 370 desc->ad_cname.bv_val, 371 val.bv_val ? "=" : "", 372 val.bv_val ? val.bv_val : "", 373 rc ? "ALLOWED" : "DENIED" ); 374 375 } else { 376 fprintf( stderr, "%s%s%s: %s\n", 377 desc->ad_cname.bv_val, 378 val.bv_val ? "=" : "", 379 val.bv_val ? val.bv_val : "", 380 accessmask2str( mask, accessmaskbuf, 1 ) ); 381 } 382 rc = 0; 383 attr = NULL; 384 } 385 386destroy:; 387 if ( !BER_BVISNULL( &e.e_name ) ) { 388 ber_memfree( e.e_name.bv_val ); 389 } 390 if ( !BER_BVISNULL( &e.e_nname ) ) { 391 ber_memfree( e.e_nname.bv_val ); 392 } 393 if ( !dryrun && be ) { 394 if ( ep && ep != &e ) { 395 be_entry_release_r( op, ep ); 396 } 397 if ( doclose ) { 398 be->be_entry_close( be ); 399 } 400 401 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) { 402 if ( bd != be ) { 403 backend_shutdown( bd ); 404 } 405 } 406 } 407 408 if ( slap_tool_destroy()) 409 rc = EXIT_FAILURE; 410 411 return rc; 412} 413 414