xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/oidm.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: oidm.c,v 1.1.1.4 2014/05/28 09:58:47 tron 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-2014 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 
31 static LDAP_STAILQ_HEAD(OidMacroList, OidMacro) om_list
32 	= LDAP_STAILQ_HEAD_INITIALIZER(om_list);
33 
34 OidMacro *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  */
40 char *
41 oidm_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 
82 void
83 oidm_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 
98 int
99 parse_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 
173 void 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