]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldapsyntax.c
Per ITS#419, don't require SLAPD_RLOOKUPS when HAVE_TCPD
[openldap] / servers / slapd / tools / ldapsyntax.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright (c) 1995 Regents of the University of Michigan.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted
7  * provided that this notice is preserved and that due credit is given
8  * to the University of Michigan at Ann Arbor. The name of the University
9  * may not be used to endorse or promote products derived from this
10  * software without specific prior written permission. This software
11  * is provided ``as is'' without express or implied warranty.
12  */
13
14 #include "portable.h"
15
16 #include <stdio.h>
17
18 #include <ac/ctype.h>
19 #include <ac/string.h>
20
21 #include <quipu/commonarg.h>
22 #include <quipu/attrvalue.h>
23 #include <quipu/ds_error.h>
24 #include <quipu/ds_search.h>
25 /* #include <quipu/dap2.h> */
26 #include <quipu/dua.h>
27
28 #include <ldap.h>
29
30 #include "ldif.h"
31 #include "ldapsyntax.h"
32
33 short   ldap_dn_syntax;
34 short   ldap_password_syntax;
35 short   ldap_photo_syntax;
36 short   ldap_jpeg_syntax;
37 short   ldap_audio_syntax;
38
39 static int      dn2ldif( PS ps, DN dn );
40 static int      jpeg2ldif( PS ps, AttributeValue av );
41 static int      audio2ldif( PS ps, AttributeValue av );
42 static int      photo2ldif( PS ps, AttributeValue av );
43 static int      fileattr2ldif( PS ps, AttributeValue av );
44 static void     de_t61( char *s, int t61mark );
45 static void     de_crypt( char *s );
46
47 extern char     *progname;
48
49 #define SEPARATOR(c)    ((c) == ',' || (c) == ';')
50 #define SPACE(c)        ((c) == ' ' || (c) == '\n')
51
52
53 int
54 init_syntaxes()
55 {
56     if (( ldap_dn_syntax = str2syntax( "DN" )) == 0 ) {
57         return( -1 );   /* must have this syntax handler */
58     }
59     ldap_password_syntax = str2syntax( "password" );
60     ldap_photo_syntax = str2syntax( "photo" );
61     ldap_jpeg_syntax = str2syntax( "jpeg" );
62     ldap_audio_syntax = str2syntax( "audio" );
63
64     return( 0 );
65 }
66
67
68 /*
69  * av2ldif:  convert attribute value contained in "av" to ldif format
70  * and write to "outfp".  If "dn" is not NULL, convert it instead of "av".
71  */
72 int
73 av2ldif( FILE *outfp, AV_Sequence av, DN dn, short syntax, char *attrname,
74     PS str_ps )
75 {
76     char                *buf;
77     int                 rc;
78     struct file_syntax  *fsyntax;
79
80     if ( av != NULLAV ) {
81         fsyntax = (struct file_syntax *) av->avseq_av.av_struct;
82     }
83
84     rc = 0;     /* optimistic */
85     str_ps->ps_ptr = str_ps->ps_base;   /* reset string PS */
86
87     if ( dn != NULL || syntax == ldap_dn_syntax ) {     /* DNs */
88         rc = dn2ldif( str_ps, ( dn != NULLDN ) ? dn :
89                 (DN)(av->avseq_av.av_struct));
90
91     } else if ( syntax == ldap_jpeg_syntax || ( syntax > AV_WRITE_FILE &&
92             fsyntax->fs_real_syntax == ldap_jpeg_syntax )) {
93         rc = jpeg2ldif( str_ps, &av->avseq_av );
94
95     } else if ( syntax == ldap_photo_syntax || ( syntax > AV_WRITE_FILE &&
96             fsyntax->fs_real_syntax == ldap_photo_syntax )) {
97         rc = photo2ldif( str_ps, &av->avseq_av );
98
99     } else if ( syntax == ldap_audio_syntax || ( syntax > AV_WRITE_FILE &&
100             fsyntax->fs_real_syntax == ldap_audio_syntax )) {
101         rc = audio2ldif( str_ps, &av->avseq_av );
102
103     } else if ( syntax > AV_WRITE_FILE ) {
104         rc = fileattr2ldif( str_ps, &av->avseq_av );
105
106     } else {
107         AttrV_print( str_ps, &av->avseq_av, EDBOUT );
108         *str_ps->ps_ptr = '\0';
109         de_t61( str_ps->ps_base, 0 );
110
111         if ( syntax == ldap_password_syntax ) {
112             de_crypt( str_ps->ps_base );
113         }
114
115         str_ps->ps_ptr = str_ps->ps_base + strlen( str_ps->ps_base );
116     }
117
118     if ( rc == 0 && str_ps->ps_ptr > str_ps->ps_base ) {
119         *str_ps->ps_ptr = '\0';
120         if (( buf = ldif_type_and_value( attrname, str_ps->ps_base,
121                 str_ps->ps_ptr - str_ps->ps_base )) == NULL ) {
122             rc = -1;
123         } else {
124             if ( fputs( buf, outfp ) == EOF ) {
125                 rc = -1;
126             }
127             ber_memfree( buf );
128         }
129     }
130
131     if ( rc == -2 ) {
132         if ( syntax > AV_WRITE_FILE ) {
133             fprintf( stderr,
134                     "%s: attribute file '%s' not found (skipping value)\n",
135                      progname, fsyntax->fs_name );
136         }
137         rc = 0; /* treat as "soft" error -- keep going */
138     }
139
140     return( rc );
141 }
142
143
144 static int
145 dn2ldif( PS ps, DN dn )
146 {
147     RDN rdn;
148     int firstrdn, rc;
149     char        *value;
150     PS  rps;
151
152     if ( dn == NULLDN ) {
153         return( 0 );
154     }
155
156     if ( dn->dn_parent != NULLDN ) {
157         if (( rc = dn2ldif( ps, dn->dn_parent )) != 0 ) {
158             return( rc );
159         }
160         ps_print( ps, ", " );
161     }
162
163     if ( (rps = ps_alloc( str_open )) == NULLPS ||
164             str_setup( rps, NULLCP, 0, 0 ) == NOTOK ) {
165         return( -1 );
166     }
167
168     firstrdn = 1;
169     for ( rdn = dn->dn_rdn; rdn != NULLRDN; rdn = rdn->rdn_next ) {
170         if ( firstrdn ) {
171             firstrdn = 0;
172         } else {
173             ps_print( ps, " + " );
174         }
175
176         AttrT_print( ps, rdn->rdn_at, EDBOUT );
177         ps_print( ps, "=" );
178
179         if ( rdn->rdn_at->oa_syntax == ldap_dn_syntax ) {
180             if (( rc = dn2ldif( rps, (DN) rdn->rdn_av.av_struct )) != 0 ) {
181                 return( rc );
182             }
183             *rps->ps_ptr = '\0';
184             value = rps->ps_base;
185         } else {
186             AttrV_print( rps, &rdn->rdn_av, EDBOUT );
187             *rps->ps_ptr = '\0';
188             value = rps->ps_base;
189             de_t61( value, 0 );
190         }
191
192         /*
193          * ,+="\\\n all go in quotes.  " and \\ need to
194          * be preceeded by \\.
195          */
196
197         if ( strpbrk( value, ",+=\"\\\n" ) != NULL || SPACE( value[0] )
198                 || SPACE( value[max( strlen(value) - 1, 0 )] ) ) {
199             char        *p, *t, *tmp;
200             int specialcount;
201
202             ps_print( ps, "\"" );
203
204             specialcount = 0;
205             for ( p = value; *p != '\0'; p++ ) {
206                 if ( *p == '"' || *p == '\\' ) {
207                     specialcount++;
208                 }
209             }
210             if ( specialcount > 0 ) {
211                 tmp = smalloc( strlen( value ) + specialcount + 1 );
212                 for ( p = value, t = tmp; *p != '\0'; p++ ) {
213                     switch ( *p ) {
214                     case '"':
215                     case '\\':
216                             *t++ = '\\';
217                             /* FALL THROUGH */
218                     default:
219                             *t++ = *p;
220                     }
221                 }
222                 *t = '\0';
223                 ps_print( ps, tmp );
224                 free( tmp );
225             } else {
226                 ps_print( ps, value );
227             }
228
229             ps_print( ps, "\"" );
230         } else {
231             ps_print( ps, value );
232         }
233
234         rps->ps_ptr = rps->ps_base;
235     }
236
237     ps_free( rps );
238
239     return( 0 );
240 }
241
242 #define T61     "{T.61}"
243 #define T61LEN  6
244
245 static void
246 de_t61( s, t61mark )
247 char    *s;
248 int     t61mark;
249 {
250         char    *next = s;
251         unsigned char   c;
252         unsigned int    hex;
253
254         while ( *s ) {
255                 switch ( *s ) {
256                 case '{' :
257                         if ( strncasecmp( s, T61, T61LEN) == 0 ) {
258                                 s += T61LEN;
259                                 if ( t61mark )
260                                         *next++ = '@';
261                         } else {
262                                 *next++ = *s++;
263                         }
264                         break;
265
266                 case '\\':
267                         c = *(s + 1);
268                         if ( c == '\n' ) {
269                                 s += 2;
270                                 if ( *s == '\t' )
271                                         s++;
272                                 break;
273                         }
274                         if ( isdigit( c ) )
275                                 hex = c - '0';
276                         else if ( c >= 'A' && c <= 'F' )
277                                 hex = c - 'A' + 10;
278                         else if ( c >= 'a' && c <= 'f' )
279                                 hex = c - 'a' + 10;
280                         else {
281                                 *next++ = *s++;
282                                 break;
283                         }
284                         hex <<= 4;
285                         c = *(s + 2);
286                         if ( isdigit( c ) )
287                                 hex += c - '0';
288                         else if ( c >= 'A' && c <= 'F' )
289                                 hex += c - 'A' + 10;
290                         else if ( c >= 'a' && c <= 'f' )
291                                 hex += c - 'a' + 10;
292                         else {
293                                 *next++ = *s++;
294                                 *next++ = *s++;
295                                 break;
296                         }
297
298                         *next++ = hex;
299                         s += 3;
300                         break;
301
302                 default:
303                         *next++ = *s++;
304                         break;
305                 }
306         }
307         *next = '\0';
308 }
309
310
311 #define CRYPT_MASK 0x23
312
313 static void
314 de_crypt( char *s )
315 {
316     char *p;
317
318     if ( strncmp( s, "{CRYPT}", 7 ) == 0 ) {
319         SAFEMEMCPY( s, s + 7, strlen( s + 7 ) + 1 ); /* strip off "{CRYPT}" */
320
321         for ( p = s; *p != '\0'; ++p) {         /* "decrypt" each byte */
322             if ( *p != CRYPT_MASK ) {
323                 *p ^= CRYPT_MASK;
324             }
325         }
326     }
327 }
328
329
330 static int
331 jpeg2ldif( PS ps, AttributeValue av )
332 {
333     PE  pe;
334     int len;
335
336     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
337         return( -2 );   /* signal soft error */
338     }
339
340     if (( pe->pe_class != PE_CLASS_UNIV && pe->pe_class != PE_CLASS_CONT )
341             || pe->pe_form != PE_FORM_PRIM || pe->pe_id != PE_PRIM_OCTS ) {
342         return( -1 );
343     }
344
345     if ( pe_pullup( pe ) == NOTOK ) {
346         return( -1 );
347     }
348
349     len = ps_get_abs( pe );
350
351     if ( ps_write( ps, (PElementData)pe->pe_prim, len ) == NOTOK ) {
352         return( -1 );
353     }
354
355     return( 0 );
356 }
357
358
359 static int
360 audio2ldif( PS ps, AttributeValue av )
361 {
362     PE          pe;
363     struct qbuf *qb, *p;
364     int         rc, len;
365     char        *buf;
366
367     return( 0 );        /* for now */
368
369     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
370         return( -2 );   /* signal soft error */
371     }
372
373     qb = (struct qbuf *)pe;
374
375     len = 0;
376     for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
377         len += p->qb_len;
378     }
379
380     if (( buf = (char *) malloc( len )) == NULL ) {
381         return( -1 );
382     }
383
384     len = 0;
385     for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
386         SAFEMEMCPY( buf + len, p->qb_data, p->qb_len );
387         len += p->qb_len;
388     }
389
390     if ( ps_write( ps, (PElementData)buf, len ) == NOTOK ) {
391         rc = -1;
392     } else {
393         rc = 0;
394     }
395
396     free( buf );
397
398     return( rc );
399 }
400
401
402 static int
403 photo2ldif( PS ps, AttributeValue av )
404 {
405     PE          pe;
406     int         len;
407     char        *faxparamset = "\000\300\000\000";
408     BerElement  *phber;
409
410     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
411         return( -2 );   /* signal soft error */
412     }
413
414     /* old bit string-like format - only handle this for now */
415     if ( pe->pe_class == PE_CLASS_UNIV && pe->pe_form == PE_FORM_PRIM
416             && pe->pe_id == PE_PRIM_BITS ) {
417         len = ps_get_abs( pe );
418         if (( phber = der_alloc()) == NULL ) {
419             return( -1 );
420         }
421         if ( ber_printf( phber, "t{[tB]{B}}",
422                 (ber_tag_t) 0xA3, (ber_tag_t) 0x81, faxparamset, (ber_len_t) 31,
423                 (char *)pe->pe_prim, (ber_len_t) (len * 8) ) == -1 )
424         {
425             ber_free( phber, 1 );
426             return( -1 );
427         }
428         if ( ps_write( ps, (PElementData)phber->ber_buf,
429                 phber->ber_ptr - phber->ber_buf ) == NOTOK ) {
430             ber_free( phber, 1 );
431             return( -1 );
432         }
433         ber_free( phber, 1 );
434     } else {
435         /*
436          * try just writing this into a PS and sending it along
437          */
438         if ( pe2ps( ps, pe ) == NOTOK ) {
439             return( -1 );
440         }
441     }
442
443     return( 0 );
444 }
445
446
447 static int
448 fileattr2ldif( PS ps, AttributeValue av )
449 {
450     PE          pe;
451
452     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
453         return( -2 );   /* signal soft error */
454     }
455
456     /*
457      * try just writing this into a PS and sending it along
458      */
459     if ( pe2ps( ps, pe ) == NOTOK ) {
460         return( -1 );
461     }
462
463     return( 0 );
464 }