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 
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 *
oidm_find(char * oid)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
oidm_destroy()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
parse_oidm(struct config_args_s * c,int user,OidMacro ** rom)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 
oidm_unparse(BerVarray * res,OidMacro * start,OidMacro * end,int sys)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