1/*	$NetBSD: oidm.c,v 1.3 2021/08/14 16:14:58 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-2021 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.3 2021/08/14 16:14:58 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
34static LDAP_STAILQ_HEAD(OidMacroList, OidMacro) om_list
35	= LDAP_STAILQ_HEAD_INITIALIZER(om_list);
36
37OidMacro *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 */
43char *
44oidm_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
85void
86oidm_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
101int
102parse_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
176void 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