1 1.3 christos /* $NetBSD: allop.c,v 1.4 2025/09/05 21:16:15 christos Exp $ */ 2 1.2 christos 3 1.1 lukem /* allop.c - returns all operational attributes when appropriate */ 4 1.2 christos /* $OpenLDAP$ */ 5 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 1.1 lukem * 7 1.4 christos * Copyright 2005-2024 The OpenLDAP Foundation. 8 1.1 lukem * All rights reserved. 9 1.1 lukem * 10 1.1 lukem * Redistribution and use in source and binary forms, with or without 11 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP 12 1.1 lukem * Public License. 13 1.1 lukem * 14 1.1 lukem * A copy of this license is available in the file LICENSE in the 15 1.1 lukem * top-level directory of the distribution or, alternatively, at 16 1.1 lukem * <http://www.OpenLDAP.org/license.html>. 17 1.1 lukem */ 18 1.1 lukem /* ACKNOWLEDGEMENTS: 19 1.1 lukem * This work was initially developed by Pierangelo Masarati for inclusion in 20 1.1 lukem * OpenLDAP Software. 21 1.1 lukem */ 22 1.1 lukem 23 1.1 lukem /* 24 1.1 lukem * The intended usage is as a global overlay for use with those clients 25 1.1 lukem * that do not make use of the RFC3673 allOp ("+") in the requested 26 1.1 lukem * attribute list, but expect all operational attributes to be returned. 27 1.1 lukem * Usage: add 28 1.1 lukem * 29 1.1 lukem 30 1.1 lukem overlay allop 31 1.1 lukem allop-URI <ldapURI> 32 1.1 lukem 33 1.1 lukem * 34 1.1 lukem * if the allop-URI is not given, the rootDSE, i.e. "ldap:///??base", 35 1.1 lukem * is assumed. 36 1.1 lukem */ 37 1.1 lukem 38 1.2 christos #include <sys/cdefs.h> 39 1.3 christos __RCSID("$NetBSD: allop.c,v 1.4 2025/09/05 21:16:15 christos Exp $"); 40 1.2 christos 41 1.1 lukem #include "portable.h" 42 1.1 lukem 43 1.1 lukem #include <stdio.h> 44 1.1 lukem #include <ac/string.h> 45 1.1 lukem 46 1.1 lukem #include "slap.h" 47 1.3 christos #include "slap-config.h" 48 1.1 lukem 49 1.1 lukem #define SLAP_OVER_VERSION_REQUIRE(major,minor,patch) \ 50 1.1 lukem ( \ 51 1.1 lukem ( LDAP_VENDOR_VERSION_MAJOR == X || LDAP_VENDOR_VERSION_MAJOR >= (major) ) \ 52 1.1 lukem && ( LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR >= (minor) ) \ 53 1.1 lukem && ( LDAP_VENDOR_VERSION_PATCH == X || LDAP_VENDOR_VERSION_PATCH >= (patch) ) \ 54 1.1 lukem ) 55 1.1 lukem 56 1.1 lukem #if !SLAP_OVER_VERSION_REQUIRE(2,3,0) 57 1.1 lukem #error "version mismatch" 58 1.1 lukem #endif 59 1.1 lukem 60 1.1 lukem typedef struct allop_t { 61 1.1 lukem struct berval ao_ndn; 62 1.1 lukem int ao_scope; 63 1.1 lukem } allop_t; 64 1.1 lukem 65 1.1 lukem static int 66 1.1 lukem allop_db_config( 67 1.1 lukem BackendDB *be, 68 1.1 lukem const char *fname, 69 1.1 lukem int lineno, 70 1.1 lukem int argc, 71 1.1 lukem char **argv ) 72 1.1 lukem { 73 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info; 74 1.1 lukem allop_t *ao = (allop_t *)on->on_bi.bi_private; 75 1.1 lukem 76 1.1 lukem if ( strcasecmp( argv[ 0 ], "allop-uri" ) == 0 ) { 77 1.1 lukem LDAPURLDesc *lud; 78 1.1 lukem struct berval dn, 79 1.1 lukem ndn; 80 1.1 lukem int scope, 81 1.1 lukem rc = LDAP_SUCCESS; 82 1.1 lukem 83 1.1 lukem if ( argc != 2 ) { 84 1.1 lukem fprintf( stderr, "%s line %d: " 85 1.1 lukem "need exactly 1 arg " 86 1.1 lukem "in \"allop-uri <ldapURI>\" " 87 1.1 lukem "directive.\n", 88 1.1 lukem fname, lineno ); 89 1.1 lukem return 1; 90 1.1 lukem } 91 1.1 lukem 92 1.1 lukem if ( ldap_url_parse( argv[ 1 ], &lud ) != LDAP_URL_SUCCESS ) { 93 1.1 lukem return -1; 94 1.1 lukem } 95 1.1 lukem 96 1.1 lukem scope = lud->lud_scope; 97 1.1 lukem if ( scope == LDAP_SCOPE_DEFAULT ) { 98 1.1 lukem scope = LDAP_SCOPE_BASE; 99 1.1 lukem } 100 1.1 lukem 101 1.1 lukem if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) { 102 1.1 lukem if ( scope == LDAP_SCOPE_BASE ) { 103 1.1 lukem BER_BVZERO( &ndn ); 104 1.1 lukem 105 1.1 lukem } else { 106 1.1 lukem ber_str2bv( "", 0, 1, &ndn ); 107 1.1 lukem } 108 1.1 lukem 109 1.1 lukem } else { 110 1.1 lukem 111 1.1 lukem ber_str2bv( lud->lud_dn, 0, 0, &dn ); 112 1.1 lukem rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ); 113 1.1 lukem } 114 1.1 lukem 115 1.1 lukem ldap_free_urldesc( lud ); 116 1.1 lukem if ( rc != LDAP_SUCCESS ) { 117 1.1 lukem return -1; 118 1.1 lukem } 119 1.1 lukem 120 1.1 lukem if ( BER_BVISNULL( &ndn ) ) { 121 1.1 lukem /* rootDSE */ 122 1.1 lukem if ( ao != NULL ) { 123 1.1 lukem ch_free( ao->ao_ndn.bv_val ); 124 1.1 lukem ch_free( ao ); 125 1.1 lukem on->on_bi.bi_private = NULL; 126 1.1 lukem } 127 1.1 lukem 128 1.1 lukem } else { 129 1.1 lukem if ( ao == NULL ) { 130 1.1 lukem ao = ch_calloc( 1, sizeof( allop_t ) ); 131 1.1 lukem on->on_bi.bi_private = (void *)ao; 132 1.1 lukem 133 1.1 lukem } else { 134 1.1 lukem ch_free( ao->ao_ndn.bv_val ); 135 1.1 lukem } 136 1.1 lukem 137 1.1 lukem ao->ao_ndn = ndn; 138 1.1 lukem ao->ao_scope = scope; 139 1.1 lukem } 140 1.1 lukem 141 1.1 lukem } else { 142 1.1 lukem return SLAP_CONF_UNKNOWN; 143 1.1 lukem } 144 1.1 lukem 145 1.1 lukem return 0; 146 1.1 lukem } 147 1.1 lukem 148 1.1 lukem static int 149 1.1 lukem allop_db_destroy( BackendDB *be, ConfigReply *cr ) 150 1.1 lukem { 151 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info; 152 1.1 lukem allop_t *ao = (allop_t *)on->on_bi.bi_private; 153 1.1 lukem 154 1.1 lukem if ( ao != NULL ) { 155 1.1 lukem assert( !BER_BVISNULL( &ao->ao_ndn ) ); 156 1.1 lukem 157 1.1 lukem ch_free( ao->ao_ndn.bv_val ); 158 1.1 lukem ch_free( ao ); 159 1.1 lukem on->on_bi.bi_private = NULL; 160 1.1 lukem } 161 1.1 lukem 162 1.1 lukem return 0; 163 1.1 lukem } 164 1.1 lukem 165 1.1 lukem static int 166 1.1 lukem allop_op_search( Operation *op, SlapReply *rs ) 167 1.1 lukem { 168 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 169 1.1 lukem allop_t *ao = (allop_t *)on->on_bi.bi_private; 170 1.1 lukem 171 1.1 lukem slap_mask_t mask; 172 1.1 lukem int i, 173 1.1 lukem add_allUser = 0; 174 1.1 lukem 175 1.1 lukem if ( ao == NULL ) { 176 1.1 lukem if ( !BER_BVISEMPTY( &op->o_req_ndn ) 177 1.1 lukem || op->ors_scope != LDAP_SCOPE_BASE ) 178 1.1 lukem { 179 1.1 lukem return SLAP_CB_CONTINUE; 180 1.1 lukem } 181 1.1 lukem 182 1.1 lukem } else { 183 1.1 lukem if ( !dnIsSuffix( &op->o_req_ndn, &ao->ao_ndn ) ) { 184 1.1 lukem return SLAP_CB_CONTINUE; 185 1.1 lukem } 186 1.1 lukem 187 1.1 lukem switch ( ao->ao_scope ) { 188 1.1 lukem case LDAP_SCOPE_BASE: 189 1.1 lukem if ( op->o_req_ndn.bv_len != ao->ao_ndn.bv_len ) { 190 1.1 lukem return SLAP_CB_CONTINUE; 191 1.1 lukem } 192 1.1 lukem break; 193 1.1 lukem 194 1.1 lukem case LDAP_SCOPE_ONELEVEL: 195 1.1 lukem if ( op->ors_scope == LDAP_SCOPE_BASE ) { 196 1.1 lukem struct berval rdn = op->o_req_ndn; 197 1.1 lukem 198 1.1 lukem rdn.bv_len -= ao->ao_ndn.bv_len + STRLENOF( "," ); 199 1.1 lukem if ( !dnIsOneLevelRDN( &rdn ) ) { 200 1.1 lukem return SLAP_CB_CONTINUE; 201 1.1 lukem } 202 1.1 lukem 203 1.1 lukem break; 204 1.1 lukem } 205 1.1 lukem return SLAP_CB_CONTINUE; 206 1.1 lukem 207 1.1 lukem case LDAP_SCOPE_SUBTREE: 208 1.1 lukem break; 209 1.1 lukem } 210 1.1 lukem } 211 1.1 lukem 212 1.1 lukem mask = slap_attr_flags( op->ors_attrs ); 213 1.1 lukem if ( SLAP_OPATTRS( mask ) ) { 214 1.1 lukem return SLAP_CB_CONTINUE; 215 1.1 lukem } 216 1.1 lukem 217 1.1 lukem if ( !SLAP_USERATTRS( mask ) ) { 218 1.1 lukem return SLAP_CB_CONTINUE; 219 1.1 lukem } 220 1.1 lukem 221 1.1 lukem i = 0; 222 1.1 lukem if ( op->ors_attrs == NULL ) { 223 1.1 lukem add_allUser = 1; 224 1.1 lukem 225 1.1 lukem } else { 226 1.1 lukem for ( ; !BER_BVISNULL( &op->ors_attrs[ i ].an_name ); i++ ) 227 1.1 lukem ; 228 1.1 lukem } 229 1.1 lukem 230 1.1 lukem op->ors_attrs = op->o_tmprealloc( op->ors_attrs, 231 1.1 lukem sizeof( AttributeName ) * ( i + add_allUser + 2 ), 232 1.1 lukem op->o_tmpmemctx ); 233 1.1 lukem 234 1.1 lukem if ( add_allUser ) { 235 1.1 lukem op->ors_attrs[ i ] = slap_anlist_all_user_attributes[ 0 ]; 236 1.1 lukem i++; 237 1.1 lukem } 238 1.1 lukem 239 1.1 lukem op->ors_attrs[ i ] = slap_anlist_all_operational_attributes[ 0 ]; 240 1.1 lukem 241 1.1 lukem BER_BVZERO( &op->ors_attrs[ i + 1 ].an_name ); 242 1.1 lukem 243 1.1 lukem return SLAP_CB_CONTINUE; 244 1.1 lukem } 245 1.1 lukem 246 1.1 lukem static slap_overinst allop; 247 1.1 lukem 248 1.1 lukem int 249 1.1 lukem allop_init() 250 1.1 lukem { 251 1.1 lukem allop.on_bi.bi_type = "allop"; 252 1.1 lukem 253 1.3 christos allop.on_bi.bi_flags = SLAPO_BFLAG_SINGLE; 254 1.1 lukem allop.on_bi.bi_db_config = allop_db_config; 255 1.1 lukem allop.on_bi.bi_db_destroy = allop_db_destroy; 256 1.1 lukem 257 1.1 lukem allop.on_bi.bi_op_search = allop_op_search; 258 1.1 lukem 259 1.1 lukem return overlay_register( &allop ); 260 1.1 lukem } 261 1.1 lukem 262 1.1 lukem int 263 1.1 lukem init_module( int argc, char *argv[] ) 264 1.1 lukem { 265 1.1 lukem return allop_init(); 266 1.1 lukem } 267 1.1 lukem 268