Home | History | Annotate | Line # | Download | only in slapd
      1 /*	$NetBSD: oidm.c,v 1.4 2025/09/05 21:16:25 christos Exp $	*/
      2 
      3 /* oidm.c - object identifier macro routines */
      4 /* $OpenLDAP$ */
      5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  *
      7  * Copyright 1998-2024 The OpenLDAP Foundation.
      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 the file LICENSE in the
     15  * top-level directory of the distribution or, alternatively, at
     16  * <http://www.OpenLDAP.org/license.html>.
     17  */
     18 
     19 #include <sys/cdefs.h>
     20 __RCSID("$NetBSD: oidm.c,v 1.4 2025/09/05 21:16:25 christos Exp $");
     21 
     22 #include "portable.h"
     23 
     24 #include <stdio.h>
     25 
     26 #include <ac/ctype.h>
     27 #include <ac/string.h>
     28 #include <ac/socket.h>
     29 
     30 #include "slap.h"
     31 #include "lutil.h"
     32 #include "slap-config.h"
     33 
     34 static LDAP_STAILQ_HEAD(OidMacroList, OidMacro) om_list
     35 	= LDAP_STAILQ_HEAD_INITIALIZER(om_list);
     36 
     37 OidMacro *om_sys_tail;
     38 
     39 /* Replace an OID Macro invocation with its full numeric OID.
     40  * If the macro is used with "macroname:suffix" append ".suffix"
     41  * to the expansion.
     42  */
     43 char *
     44 oidm_find(char *oid)
     45 {
     46 	OidMacro *om;
     47 
     48 	/* OID macros must start alpha */
     49 	if ( OID_LEADCHAR( *oid ) )	{
     50 		return oid;
     51 	}
     52 
     53 	LDAP_STAILQ_FOREACH( om, &om_list, som_next ) {
     54 		BerVarray names = om->som_names;
     55 
     56 		if( names == NULL ) {
     57 			continue;
     58 		}
     59 
     60 		for( ; !BER_BVISNULL( names ) ; names++ ) {
     61 			int pos = dscompare(names->bv_val, oid, ':');
     62 
     63 			if( pos ) {
     64 				int suflen = strlen(oid + pos);
     65 				char *tmp = SLAP_MALLOC( om->som_oid.bv_len
     66 					+ suflen + 1);
     67 				if( tmp == NULL ) {
     68 					Debug( LDAP_DEBUG_ANY,
     69 						"oidm_find: SLAP_MALLOC failed" );
     70 					return NULL;
     71 				}
     72 				strcpy(tmp, om->som_oid.bv_val);
     73 				if( suflen ) {
     74 					suflen = om->som_oid.bv_len;
     75 					tmp[suflen++] = '.';
     76 					strcpy(tmp+suflen, oid+pos+1);
     77 				}
     78 				return tmp;
     79 			}
     80 		}
     81 	}
     82 	return NULL;
     83 }
     84 
     85 void
     86 oidm_destroy()
     87 {
     88 	OidMacro *om;
     89 	while( !LDAP_STAILQ_EMPTY( &om_list )) {
     90 		om = LDAP_STAILQ_FIRST( &om_list );
     91 		LDAP_STAILQ_REMOVE_HEAD( &om_list, som_next );
     92 
     93 		ber_bvarray_free(om->som_names);
     94 		ber_bvarray_free(om->som_subs);
     95 		free(om->som_oid.bv_val);
     96 		free(om);
     97 
     98 	}
     99 }
    100 
    101 int
    102 parse_oidm(
    103 	struct config_args_s *c,
    104 	int		user,
    105 	OidMacro **rom)
    106 {
    107 	char *oid, *oidv;
    108 	OidMacro *om = NULL, *prev = NULL;
    109 	struct berval bv;
    110 
    111 	oidv = oidm_find( c->argv[2] );
    112 	if( !oidv ) {
    113 		snprintf( c->cr_msg, sizeof( c->cr_msg ),
    114 			"%s: OID %s not recognized",
    115 			c->argv[0], c->argv[2] );
    116 		Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
    117 			"%s %s\n", c->log, c->cr_msg );
    118 		return 1;
    119 	}
    120 
    121 	oid = oidm_find( c->argv[1] );
    122 	if( oid != NULL ) {
    123 		int rc;
    124 		snprintf( c->cr_msg, sizeof( c->cr_msg ),
    125 			"%s: \"%s\" previously defined \"%s\"",
    126 			c->argv[0], c->argv[1], oid );
    127 		Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
    128 			"%s %s\n", c->log, c->cr_msg );
    129 		/* Allow duplicate if the definition is identical */
    130 		rc = strcmp( oid, oidv ) != 0;
    131 		SLAP_FREE( oid );
    132 		if ( oidv != c->argv[2] )
    133 			SLAP_FREE( oidv );
    134 		return rc;
    135 	}
    136 
    137 	om = (OidMacro *) SLAP_CALLOC( sizeof(OidMacro), 1 );
    138 	if( om == NULL ) {
    139 		snprintf( c->cr_msg, sizeof( c->cr_msg ),
    140 			"%s: SLAP_CALLOC failed", c->argv[0] );
    141 		Debug( LDAP_DEBUG_ANY,
    142 			"%s %s\n", c->log, c->cr_msg );
    143 		if ( oidv != c->argv[2] )
    144 			SLAP_FREE( oidv );
    145 		return 1;
    146 	}
    147 
    148 	om->som_names = NULL;
    149 	om->som_subs = NULL;
    150 	ber_str2bv( c->argv[1], 0, 1, &bv );
    151 	ber_bvarray_add( &om->som_names, &bv );
    152 	ber_str2bv( c->argv[2], 0, 1, &bv );
    153 	ber_bvarray_add( &om->som_subs, &bv );
    154 	om->som_oid.bv_val = oidv;
    155 
    156 	if (om->som_oid.bv_val == c->argv[2]) {
    157 		om->som_oid.bv_val = ch_strdup( c->argv[2] );
    158 	}
    159 
    160 	om->som_oid.bv_len = strlen( om->som_oid.bv_val );
    161 	if ( !user ) {
    162 		om->som_flags |= SLAP_OM_HARDCODE;
    163 		prev = om_sys_tail;
    164 		om_sys_tail = om;
    165 	}
    166 
    167 	if ( prev ) {
    168 		LDAP_STAILQ_INSERT_AFTER( &om_list, prev, om, som_next );
    169 	} else {
    170 		LDAP_STAILQ_INSERT_TAIL( &om_list, om, som_next );
    171 	}
    172 	if ( rom ) *rom = om;
    173 	return 0;
    174 }
    175 
    176 void oidm_unparse( BerVarray *res, OidMacro *start, OidMacro *end, int sys )
    177 {
    178 	OidMacro *om;
    179 	int i, j, num;
    180 	struct berval *bva = NULL, idx;
    181 	char ibuf[32], *ptr;
    182 
    183 	if ( !start )
    184 		start = LDAP_STAILQ_FIRST( &om_list );
    185 
    186 	/* count the result size */
    187 	i = 0;
    188 	for ( om=start; om; om=LDAP_STAILQ_NEXT(om, som_next)) {
    189 		if ( sys && !(om->som_flags & SLAP_OM_HARDCODE)) break;
    190 		for ( j=0; !BER_BVISNULL(&om->som_names[j]); j++ );
    191 		i += j;
    192 		if ( om == end ) break;
    193 	}
    194 	num = i;
    195 	if (!i) return;
    196 
    197 	bva = ch_malloc( (num+1) * sizeof(struct berval) );
    198 	BER_BVZERO( bva+num );
    199 	idx.bv_val = ibuf;
    200 	if ( sys ) {
    201 		idx.bv_len = 0;
    202 		ibuf[0] = '\0';
    203 	}
    204 	for ( i=0,om=start; om; om=LDAP_STAILQ_NEXT(om, som_next)) {
    205 		if ( sys && !(om->som_flags & SLAP_OM_HARDCODE)) break;
    206 		for ( j=0; !BER_BVISNULL(&om->som_names[j]); i++,j++ ) {
    207 			if ( !sys ) {
    208 				idx.bv_len = sprintf(idx.bv_val, "{%d}", i );
    209 			}
    210 			bva[i].bv_len = idx.bv_len + om->som_names[j].bv_len +
    211 				om->som_subs[j].bv_len + 1;
    212 			bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
    213 			ptr = lutil_strcopy( bva[i].bv_val, ibuf );
    214 			ptr = lutil_strcopy( ptr, om->som_names[j].bv_val );
    215 			*ptr++ = ' ';
    216 			strcpy( ptr, om->som_subs[j].bv_val );
    217 		}
    218 		if ( i>=num ) break;
    219 		if ( om == end ) break;
    220 	}
    221 	*res = bva;
    222 }
    223