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