]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
Initial implementation of Kerberos password verification for
[openldap] / servers / slapd / back-ldbm / index.c
1 /* index.c - routines for dealing with attribute indexes */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16 #include "back-ldbm.h"
17
18 static int      change_value(Backend *be,
19                           DBCache *db,
20                           char *type,
21                           int indextype,
22                           char *val,
23                           ID id,
24                           int
25                           (*idl_func)(Backend *, DBCache *, Datum, ID));
26 static int      index2prefix(int indextype);
27
28 int
29 index_add_entry(
30     Backend     *be,
31     Entry       *e
32 )
33 {
34         Attribute       *ap;
35         struct berval   bv;
36         struct berval   *bvals[2];
37
38         Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
39             e->e_dn, 0 );
40
41         /*
42          * dn index entry - make it look like an attribute so it works
43          * with index_change_values() call
44          */
45
46         bv.bv_val = ch_strdup( e->e_ndn );
47         bv.bv_len = strlen( bv.bv_val );
48         bvals[0] = &bv;
49         bvals[1] = NULL;
50
51         /* add the dn to the indexes */
52         {
53                 char *dn = ch_strdup("dn");
54                 index_change_values( be, dn, bvals, e->e_id, SLAP_INDEX_ADD_OP );
55                 free( dn );
56         }
57
58         free( bv.bv_val );
59
60         /* add each attribute to the indexes */
61         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
62                 index_change_values( be, ap->a_type, ap->a_vals, e->e_id,
63                                      SLAP_INDEX_ADD_OP );
64         }
65
66         Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
67             e->e_ndn, 0 );
68         return( 0 );
69 }
70
71 int
72 index_add_mods(
73     Backend     *be,
74     LDAPModList *ml,
75     ID          id
76 )
77 {
78         int     rc;
79
80         for ( ; ml != NULL; ml = ml->ml_next ) {
81                 LDAPMod *mod = &ml->ml_mod;
82
83                 switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
84                 case LDAP_MOD_REPLACE:
85                         /* XXX: Delete old index data==>problem when this 
86                          * gets called we lost values already!
87                          */
88                 case LDAP_MOD_ADD:
89                         rc = index_change_values( be,
90                                                mod->mod_type,
91                                                mod->mod_bvalues,
92                                                id,
93                                                SLAP_INDEX_ADD_OP );
94                         break;
95                 case LDAP_MOD_DELETE:
96                         rc =  index_change_values( be,
97                                                    mod->mod_type,
98                                                    mod->mod_bvalues,
99                                                    id,
100                                                    SLAP_INDEX_DELETE_OP );
101                         break;
102                 case LDAP_MOD_SOFTADD:  /* SOFTADD means index was there */
103                         rc = 0;
104                         break;
105                 }
106
107                 if ( rc != 0 ) {
108                         return( rc );
109                 }
110         }
111
112         return( 0 );
113 }
114
115 ID_BLOCK *
116 index_read(
117     Backend     *be,
118     char        *type,
119     int         indextype,
120     char        *val
121 )
122 {
123         DBCache *db;
124         Datum           key;
125         ID_BLOCK                *idl;
126         int             indexmask, syntax;
127         char            prefix;
128         char            *realval, *tmpval;
129         char            buf[BUFSIZ];
130
131         char            *at_cn;
132
133         ldbm_datum_init( key );
134
135         prefix = index2prefix( indextype );
136         Debug( LDAP_DEBUG_TRACE, "=> index_read(\"%c%s\"->\"%s\")\n",
137             prefix, type, val );
138
139         attr_masks( be->be_private, type, &indexmask, &syntax );
140         if ( ! (indextype & indexmask) ) {
141                 idl =  idl_allids( be );
142                 Debug( LDAP_DEBUG_TRACE,
143                     "<= index_read %ld candidates (allids - not indexed)\n",
144                     idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
145                 return( idl );
146         }
147
148         attr_normalize( type );
149         at_cn = at_canonical_name( type );
150
151         if ( at_cn == NULL ) {
152                 Debug( LDAP_DEBUG_ANY,
153                     "<= index_read no canonical name for type \"%s\"\n",
154                         type != NULL ? type : "(NULL)", 0, 0 );
155                 return( NULL );
156         }
157
158         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
159             == NULL ) {
160                 Debug( LDAP_DEBUG_ANY,
161                     "<= index_read NULL (could not open %s%s)\n",
162                         at_cn, LDBM_SUFFIX, 0 );
163                 return( NULL );
164         }
165
166         realval = val;
167         tmpval = NULL;
168         if ( prefix != UNKNOWN_PREFIX ) {
169                 unsigned int    len = strlen( val );
170
171                 if ( (len + 2) < sizeof(buf) ) {
172                         realval = buf;
173                 } else {
174                         /* value + prefix + null */
175                         tmpval = (char *) ch_malloc( len + 2 );
176                         realval = tmpval;
177                 }
178
179                 realval[0] = prefix;
180                 strcpy( &realval[1], val );
181         }
182
183         key.dptr = realval;
184         key.dsize = strlen( realval ) + 1;
185
186         idl = idl_fetch( be, db, key );
187         if ( tmpval != NULL ) {
188               free( tmpval );
189         }
190
191         ldbm_cache_close( be, db );
192
193         Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
194                idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
195         return( idl );
196 }
197
198 /* Add or remove stuff from index files */
199
200 static int
201 change_value(
202     Backend             *be,
203     DBCache     *db,
204     char                *type,
205     int                 indextype,
206     char                *val,
207     ID                  id,
208     int                 (*idl_func)(Backend *, DBCache *, Datum, ID)
209 )
210 {
211         int     rc;
212         Datum   key;
213         char    *tmpval = NULL;
214         char    *realval = val;
215         char    buf[BUFSIZ];
216
217         char    prefix = index2prefix( indextype );
218
219         ldbm_datum_init( key );
220
221         Debug( LDAP_DEBUG_TRACE,
222                "=> change_value( \"%c%s\", op=%s )\n",
223                prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") );
224
225         if ( prefix != UNKNOWN_PREFIX ) {
226               unsigned int     len = strlen( val );
227
228               if ( (len + 2) < sizeof(buf) ) {
229                         realval = buf;
230               } else {
231                         /* value + prefix + null */
232                         tmpval = (char *) ch_malloc( len + 2 );
233                         realval = tmpval;
234               }
235               realval[0] = prefix;
236               strcpy( &realval[1], val );
237         }
238
239         key.dptr = realval;
240         key.dsize = strlen( realval ) + 1;
241
242         rc = idl_func( be, db, key, id );
243
244         if ( tmpval != NULL ) {
245                 free( tmpval );
246         }
247
248         ldap_pvt_thread_yield();
249
250         Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 );
251
252         return( rc );
253
254 }/* static int change_value() */
255
256
257 int
258 index_change_values(
259     Backend             *be,
260     char                *type,
261     struct berval       **vals,
262     ID                  id,
263     unsigned int        op
264 )
265 {
266         char            *val, *p, *code, *w;
267         unsigned        i, j, len;
268         int             indexmask, syntax;
269         char            buf[SUBLEN + 1];
270         char            vbuf[BUFSIZ];
271         char            *bigbuf;
272         DBCache *db;
273
274         int             (*idl_funct)(Backend *,
275                                     DBCache *,
276                                     Datum, ID);
277         char            *at_cn; /* Attribute canonical name */
278         int             mode;
279
280         if( vals == NULL ) {
281                 Debug( LDAP_DEBUG_TRACE,
282                         "=> index_change_values( %s, NULL, %ld, op=%s )\n", 
283                         type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
284                 return 0;
285         }
286
287         Debug( LDAP_DEBUG_TRACE,
288                "=> index_change_values( \"%s\", %ld, op=%s )\n", 
289                type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
290
291         
292         if (op == SLAP_INDEX_ADD_OP) {
293
294             /* Add values */
295
296             idl_funct =  idl_insert_key;
297             mode = LDBM_WRCREAT;
298
299         } else {
300
301             /* Delete values */
302
303             idl_funct = idl_delete_key;
304             mode = LDBM_WRITER;
305
306         }
307
308         attr_normalize(type);
309         attr_masks( be->be_private, type, &indexmask, &syntax );
310
311         if ( indexmask == 0 ) {
312                 return( 0 );
313         }
314
315         at_cn = at_canonical_name( type );
316
317         if ( at_cn == NULL ) {
318                 Debug( LDAP_DEBUG_ANY,
319                     "<= index_change_values no canonical name for type \"%s\"\n",
320                         type != NULL ? type : "(NULL)", 0, 0 );
321                 return( -1 );
322         }
323
324         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode ))
325              == NULL ) {
326                 Debug( LDAP_DEBUG_ANY,
327                        "<= index_change_values (couldn't open(%s%s),md=%s)\n",
328                        at_cn, LDBM_SUFFIX,
329                        ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
330                 return( -1 );
331         }
332
333
334         for ( i = 0; vals[i] != NULL; i++ ) {
335                 /*
336                  * presence index entry
337                  */
338                 if ( indexmask & INDEX_PRESENCE ) {
339
340                         change_value( be, db, at_cn, INDEX_PRESENCE,
341                                       "*", id, idl_funct );
342
343                 }
344
345                 Debug( LDAP_DEBUG_TRACE,
346                        "index_change_values syntax 0x%x syntax bin 0x%x\n",
347                        syntax, SYNTAX_BIN, 0 );
348
349                 if ( syntax & SYNTAX_BIN ) {
350
351                         ldbm_cache_close( be, db );
352                         return( 0 );
353
354                 }
355
356                 bigbuf = NULL;
357                 len = vals[i]->bv_len;
358
359                 /* value + null */
360                 if ( len + 2 > sizeof(vbuf) ) {
361                         bigbuf = (char *) ch_malloc( len + 1 );
362                         val = bigbuf;
363                 } else {
364                         val = vbuf;
365                 }
366                 (void) memcpy( val, vals[i]->bv_val, len );
367                 val[len] = '\0';
368
369                 value_normalize( val, syntax );
370
371                 /* value_normalize could change the length of val */
372                 len = strlen( val );
373
374                 /*
375                  * equality index entry
376                  */
377                 if ( indexmask & INDEX_EQUALITY ) {
378                     
379                         change_value( be, db, at_cn, INDEX_EQUALITY,
380                                       val, id, idl_funct);
381
382                 }
383
384                 /*
385                  * approximate index entry
386                  */
387                 if ( indexmask & INDEX_APPROX ) {
388                         for ( w = first_word( val ); w != NULL;
389                             w = next_word( w ) ) {
390                                 if ( (code = phonetic( w )) != NULL ) {
391                                         change_value( be,
392                                                       db,
393                                                       at_cn,
394                                                       INDEX_APPROX,
395                                                       code,
396                                                       id,
397                                                       idl_funct );
398                                         free( code );
399                                 }
400                         }
401                 }
402
403                 /*
404                  * substrings index entry
405                  */
406                 if ( indexmask & INDEX_SUB ) {
407                         /* leading and trailing */
408                         if ( len > SUBLEN - 2 ) {
409                                 buf[0] = '^';
410                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
411                                         buf[j + 1] = val[j];
412                                 }
413                                 buf[SUBLEN] = '\0';
414
415                                 change_value( be, db, at_cn, INDEX_SUB,
416                                               buf, id, idl_funct );
417
418                                 p = val + len - SUBLEN + 1;
419                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
420                                         buf[j] = p[j];
421                                 }
422                                 buf[SUBLEN - 1] = '$';
423                                 buf[SUBLEN] = '\0';
424
425                                 change_value( be, db, at_cn, INDEX_SUB,
426                                               buf, id, idl_funct );
427                         }
428
429                         /* any */
430                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
431                                 for ( j = 0; j < SUBLEN; j++ ) {
432                                         buf[j] = p[j];
433                                 }
434                                 buf[SUBLEN] = '\0';
435
436                                 change_value( be, db, at_cn, INDEX_SUB,
437                                               buf, id, idl_funct );
438                         }
439                 }
440
441                 if ( bigbuf != NULL ) {
442                         free( bigbuf );
443                 }
444         }
445
446         ldbm_cache_close( be, db );
447
448         return( 0 );
449
450 }
451
452 static int
453 index2prefix( int indextype )
454 {
455         int     prefix;
456
457         switch ( indextype ) {
458         case INDEX_EQUALITY:
459                 prefix = EQ_PREFIX;
460                 break;
461         case INDEX_APPROX:
462                 prefix = APPROX_PREFIX;
463                 break;
464         case INDEX_SUB:
465                 prefix = SUB_PREFIX;
466                 break;
467         default:
468                 prefix = UNKNOWN_PREFIX;
469                 break;
470         }
471
472         return( prefix );
473 }