]> git.sur5r.net Git - openldap/blob - servers/slurpd/ldap_op.c
656bd7c885153e17f8959cbd3c54643931b4759f
[openldap] / servers / slurpd / ldap_op.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright (c) 1996 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 /*
15  * ldap_op.c - routines to perform LDAP operations
16  */
17
18 #include "portable.h"
19
20 #include <stdio.h>
21
22 #include <ac/stdlib.h>
23
24 #include <ac/errno.h>
25 #include <ac/string.h>
26 #include <ac/ctype.h>
27 #include <ac/time.h>
28 #include <ac/unistd.h>
29
30 #include <ac/krb.h>
31
32 #if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET )
33 /* Get LDAP->ld_lberoptions.  Must precede slurp.h, both define ldap_debug. */
34 #include "../../libraries/libldap/ldap-int.h"
35 #endif
36
37 #include <lber.h>
38 #include <ldap.h>
39
40 #include "slurp.h"
41
42 /* Forward references */
43 static struct berval **make_singlevalued_berval LDAP_P(( char   *, int ));
44 static int op_ldap_add LDAP_P(( Ri *, Re *, char ** ));
45 static int op_ldap_modify LDAP_P(( Ri *, Re *, char ** ));
46 static int op_ldap_delete LDAP_P(( Ri *, Re *, char ** ));
47 static int op_ldap_modrdn LDAP_P(( Ri *, Re *, char ** ));
48 static LDAPMod *alloc_ldapmod LDAP_P(( void ));
49 static void free_ldapmod LDAP_P(( LDAPMod * ));
50 static void free_ldmarr LDAP_P(( LDAPMod ** ));
51 static int getmodtype LDAP_P(( char * ));
52 static void dump_ldm_array LDAP_P(( LDAPMod ** ));
53 static char **read_krbnames LDAP_P(( Ri * ));
54 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
55 static void upcase LDAP_P(( char * ));
56 #endif
57 static int do_bind LDAP_P(( Ri *, int * ));
58 static int do_unbind LDAP_P(( Ri * ));
59
60
61 static char *kattrs[] = {"kerberosName", NULL };
62 static struct timeval kst = {30L, 0L};
63
64
65
66 /*
67  * Determine the type of ldap operation being performed and call the
68  * appropriate routine.
69  * - If successful, returns ERR_DO_LDAP_OK
70  * - If a retryable error occurs, ERR_DO_LDAP_RETRYABLE is returned.
71  *   The caller should wait a while and retry the operation.
72  * - If a fatal error occurs, ERR_DO_LDAP_FATAL is returned.  The caller
73  *   should reject the operation and continue with the next replication
74  *   entry.
75  */
76 int
77 do_ldap(
78     Ri          *ri,
79     Re          *re,
80     char        **errmsg
81 )
82 {
83     int rc = 0;
84     int lderr = LDAP_SUCCESS;
85     int retry = 2;
86
87     *errmsg = NULL;
88
89     while ( retry > 0 ) {
90         if ( ri->ri_ldp == NULL ) {
91             rc = do_bind( ri, &lderr );
92
93             if ( rc != BIND_OK ) {
94                         return DO_LDAP_ERR_RETRYABLE;
95             }
96         }
97
98         switch ( re->re_changetype ) {
99         case T_ADDCT:
100             lderr = op_ldap_add( ri, re, errmsg );
101             if ( lderr != LDAP_SUCCESS ) {
102                 Debug( LDAP_DEBUG_ANY,
103                         "Error: ldap_add_s failed adding \"%s\": %s\n",
104                         *errmsg ? *errmsg : ldap_err2string( lderr ),
105                         re->re_dn, 0 );
106             }
107             break;
108         case T_MODIFYCT:
109             lderr = op_ldap_modify( ri, re, errmsg );
110             if ( lderr != LDAP_SUCCESS ) {
111                 Debug( LDAP_DEBUG_ANY,
112                         "Error: ldap_modify_s failed modifying \"%s\": %s\n",
113                         *errmsg ? *errmsg : ldap_err2string( lderr ),
114                         re->re_dn, 0 );
115             }
116             break;
117         case T_DELETECT:
118             lderr = op_ldap_delete( ri, re, errmsg );
119             if ( lderr != LDAP_SUCCESS ) {
120                 Debug( LDAP_DEBUG_ANY,
121                         "Error: ldap_delete_s failed deleting \"%s\": %s\n",
122                         *errmsg ? *errmsg : ldap_err2string( lderr ),
123                         re->re_dn, 0 );
124             }
125             break;
126         case T_MODRDNCT:
127             lderr = op_ldap_modrdn( ri, re, errmsg );
128             if ( lderr != LDAP_SUCCESS ) {
129                 Debug( LDAP_DEBUG_ANY,
130                         "Error: ldap_modrdn_s failed modifying %s: %s\n",
131                         *errmsg ? *errmsg : ldap_err2string( lderr ),
132                         re->re_dn, 0 );
133             }
134             break;
135         default:
136             Debug( LDAP_DEBUG_ANY,
137                     "Error: do_ldap: bad op \"%d\", dn = \"%s\"\n",
138                     re->re_changetype, re->re_dn, 0 );
139             return DO_LDAP_ERR_FATAL;
140         }
141
142         /*
143          * Analyze return code.  If ok, just return.  If LDAP_SERVER_DOWN,
144          * we may have been idle long enough that the remote slapd timed
145          * us out.  Rebind and try again.
146          */
147         if ( lderr == LDAP_SUCCESS ) {
148             return DO_LDAP_OK;
149         } else if ( lderr == LDAP_SERVER_DOWN ) {
150             /* The LDAP server may have timed us out - rebind and try again */
151             (void) do_unbind( ri );
152             retry--;
153         } else {
154             return DO_LDAP_ERR_FATAL;
155         }
156     }
157     return DO_LDAP_ERR_FATAL;
158 }
159
160
161
162
163 /*
164  * Perform an ldap add operation.
165  */
166 static int
167 op_ldap_add(
168     Ri          *ri,
169     Re          *re,
170     char        **errmsg
171 )
172 {
173     Mi          *mi;
174     int         nattrs, rc = 0, i;
175     LDAPMod     *ldm, **ldmarr;
176     int         lderr = 0;
177
178     nattrs = i = 0;
179     ldmarr = NULL;
180
181     /*
182      * Construct a null-terminated array of LDAPMod structs.
183      */
184     mi = re->re_mods;
185     while ( mi[ i ].mi_type != NULL ) {
186         ldm = alloc_ldapmod();
187         ldmarr = ( LDAPMod ** ) ch_realloc( ldmarr,
188                 ( nattrs + 2 ) * sizeof( LDAPMod * ));
189         ldmarr[ nattrs ] = ldm;
190         ldm->mod_op = LDAP_MOD_BVALUES;
191         ldm->mod_type = mi[ i ].mi_type;
192         ldm->mod_bvalues =
193                 make_singlevalued_berval( mi[ i ].mi_val, mi[ i ].mi_len );
194         i++;
195         nattrs++;
196     }
197
198     if ( ldmarr != NULL ) {
199         ldmarr[ nattrs ] = NULL;
200
201         /* Perform the operation */
202         Debug( LDAP_DEBUG_ARGS, "replica %s:%d - add dn \"%s\"\n",
203                 ri->ri_hostname, ri->ri_port, re->re_dn );
204         rc = ldap_add_s( ri->ri_ldp, re->re_dn, ldmarr );
205
206         ldap_get_option( ri->ri_ldp, LDAP_OPT_ERROR_NUMBER, &lderr);
207
208     } else {
209         *errmsg = "No modifications to do";
210         Debug( LDAP_DEBUG_ANY,
211                "Error: op_ldap_add: no mods to do (%s)!\n", re->re_dn, 0, 0 );
212     }
213     free_ldmarr( ldmarr );
214     return( lderr ); 
215 }
216
217
218
219
220 /*
221  * Perform an ldap modify operation.
222  */
223 #define AWAITING_OP -1
224 static int
225 op_ldap_modify(
226     Ri          *ri,
227     Re          *re,
228     char        **errmsg
229 )
230 {
231     Mi          *mi;
232     int         state;  /* This code is a simple-minded state machine */
233     int         nvals;  /* Number of values we're modifying */
234     int         nops;   /* Number of LDAPMod structs in ldmarr */
235     LDAPMod     *ldm, **ldmarr;
236     int         i, len;
237     char        *type, *value;
238     int         rc = 0;
239
240     state = AWAITING_OP;
241     nvals = 0;
242     nops = 0;
243     ldmarr = NULL;
244
245     if ( re->re_mods == NULL ) {
246         *errmsg = "No arguments given";
247         Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modify: no arguments\n",
248                 0, 0, 0 );
249             return -1;
250     }
251
252     /*
253      * Construct a null-terminated array of LDAPMod structs.
254      */
255     for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
256         type = mi[ i ].mi_type;
257         value = mi[ i ].mi_val;
258         len = mi[ i ].mi_len;
259         switch ( getmodtype( type )) {
260         case T_MODSEP:
261             state = T_MODSEP; /* Got a separator line "-\n" */
262             continue;
263         case T_MODOPADD:
264             state = T_MODOPADD;
265             ldmarr = ( LDAPMod ** )
266                     ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
267             ldmarr[ nops ] = ldm = alloc_ldapmod();
268             ldm->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
269             ldm->mod_type = value;
270             nvals = 0;
271             nops++;
272             break;
273         case T_MODOPREPLACE:
274             state = T_MODOPREPLACE;
275             ldmarr = ( LDAPMod ** )
276                     ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
277             ldmarr[ nops ] = ldm = alloc_ldapmod();
278             ldm->mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
279             ldm->mod_type = value;
280             nvals = 0;
281             nops++;
282             break;
283         case T_MODOPDELETE:
284             state = T_MODOPDELETE;
285             ldmarr = ( LDAPMod ** )
286                     ch_realloc(ldmarr, (( nops + 2 ) * ( sizeof( LDAPMod * ))));
287             ldmarr[ nops ] = ldm = alloc_ldapmod();
288             ldm->mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
289             ldm->mod_type = value;
290             nvals = 0;
291             nops++;
292             break;
293         default:
294             if ( state == AWAITING_OP ) {
295                 Debug( LDAP_DEBUG_ANY,
296                         "Error: op_ldap_modify: unknown mod type \"%s\"\n",
297                         type, 0, 0 );
298                 continue;
299             }
300
301             /*
302              * We should have an attribute: value pair here.
303              * Construct the mod_bvalues part of the ldapmod struct.
304              */
305             if ( strcasecmp( type, ldm->mod_type )) {
306                 Debug( LDAP_DEBUG_ANY,
307                         "Error: malformed modify op, %s: %s (expecting %s:)\n",
308                         type, value, ldm->mod_type );
309                 continue;
310             }
311             ldm->mod_bvalues = ( struct berval ** )
312                     ch_realloc( ldm->mod_bvalues,
313                     ( nvals + 2 ) * sizeof( struct berval * ));
314             ldm->mod_bvalues[ nvals + 1 ] = NULL;
315             ldm->mod_bvalues[ nvals ] = ( struct berval * )
316                     ch_malloc( sizeof( struct berval ));
317             ldm->mod_bvalues[ nvals ]->bv_val = value;
318             ldm->mod_bvalues[ nvals ]->bv_len = len;
319             nvals++;
320         }
321     }
322     ldmarr[ nops ] = NULL;
323
324     if ( nops > 0 ) {
325         /* Actually perform the LDAP operation */
326         Debug( LDAP_DEBUG_ARGS, "replica %s:%d - modify dn \"%s\"\n",
327                 ri->ri_hostname, ri->ri_port, re->re_dn );
328         rc = ldap_modify_s( ri->ri_ldp, re->re_dn, ldmarr );
329     }
330     free_ldmarr( ldmarr );
331     return( rc );
332 }
333
334
335
336
337 /*
338  * Perform an ldap delete operation.
339  */
340 static int
341 op_ldap_delete(
342     Ri          *ri,
343     Re          *re,
344     char        **errmsg
345 )
346 {
347     int         rc;
348
349     Debug( LDAP_DEBUG_ARGS, "replica %s:%d - delete dn \"%s\"\n",
350             ri->ri_hostname, ri->ri_port, re->re_dn );
351     rc = ldap_delete_s( ri->ri_ldp, re->re_dn );
352
353     return( rc );
354 }
355
356
357
358
359 /*
360  * Perform an ldap modrdn operation.
361  */
362 #define GOT_NEWRDN              0x1
363 #define GOT_DELOLDRDN   0x2
364 #define GOT_NEWSUP              0x4
365
366 #define GOT_MODDN_REQ   (GOT_NEWRDN|GOT_DELOLDRDN)
367 #define GOT_ALL_MODDN(f)        (((f) & GOT_MODDN_REQ) == GOT_MODDN_REQ)
368 static int
369 op_ldap_modrdn(
370     Ri          *ri,
371     Re          *re,
372     char        **errmsg
373 )
374 {
375     int         rc = 0;
376     Mi          *mi;
377     int         i;
378         int             lderr = 0;
379     int         state = 0;
380     int         drdnflag = -1;
381     char        *newrdn;
382         char    *newsup = NULL;
383
384     if ( re->re_mods == NULL ) {
385         *errmsg = "No arguments given";
386         Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: no arguments\n",
387                 0, 0, 0 );
388             return -1;
389     }
390
391     /*
392      * Get the arguments: should see newrdn: and deleteoldrdn: args.
393      */
394     for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
395         if ( !strcmp( mi[ i ].mi_type, T_NEWRDNSTR )) {
396                 if( state & GOT_NEWRDN ) {
397                 Debug( LDAP_DEBUG_ANY,
398                         "Error: op_ldap_modrdn: multiple newrdn arg \"%s\"\n",
399                         mi[ i ].mi_val, 0, 0 );
400                 *errmsg = "Multiple newrdn argument";
401                 return -1;
402                 }
403
404             newrdn = mi[ i ].mi_val;
405             state |= GOT_NEWRDN;
406
407         } else if ( !strcmp( mi[ i ].mi_type, T_DELOLDRDNSTR )) {
408                 if( state & GOT_DELOLDRDN ) {
409                 Debug( LDAP_DEBUG_ANY,
410                         "Error: op_ldap_modrdn: multiple deleteoldrdn arg \"%s\"\n",
411                         mi[ i ].mi_val, 0, 0 );
412                 *errmsg = "Multiple newrdn argument";
413                 return -1;
414                 }
415
416             state |= GOT_DELOLDRDN;
417             if ( !strcmp( mi[ i ].mi_val, "0" )) {
418                 drdnflag = 0;
419             } else if ( !strcmp( mi[ i ].mi_val, "1" )) {
420                 drdnflag = 1;
421             } else {
422                 Debug( LDAP_DEBUG_ANY,
423                         "Error: op_ldap_modrdn: bad deleteoldrdn arg \"%s\"\n",
424                         mi[ i ].mi_val, 0, 0 );
425                 *errmsg = "Incorrect argument to deleteoldrdn";
426                 return -1;
427             }
428
429         } else if ( !strcmp( mi[ i ].mi_type, T_NEWSUPSTR )) {
430                 if( state & GOT_NEWSUP ) {
431                 Debug( LDAP_DEBUG_ANY,
432                         "Error: op_ldap_modrdn: multiple newsuperior arg \"%s\"\n",
433                         mi[ i ].mi_val, 0, 0 );
434                 *errmsg = "Multiple newrdn argument";
435                 return -1;
436                 }
437
438                 newrdn = mi[ i ].mi_val;
439             state |= GOT_NEWSUP;
440
441         } else {
442             Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: bad type \"%s\"\n",
443                     mi[ i ].mi_type, 0, 0 );
444             *errmsg = "Bad value in replication log entry";
445             return -1;
446         }
447     }
448
449     /*
450      * Punt if we don't have all the args.
451      */
452     if ( GOT_ALL_MODDN(state) ) {
453         Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: missing arguments\n",
454                 0, 0, 0 );
455         *errmsg = "Missing argument: requires \"newrdn\" and \"deleteoldrdn\"";
456         return -1;
457     }
458
459 #ifdef LDAP_DEBUG
460     if ( ldap_debug & LDAP_DEBUG_ARGS ) {
461         char buf[ 256 ];
462         char *buf2;
463         sprintf( buf, "%s:%d", ri->ri_hostname, ri->ri_port );
464         buf2 = (char *) ch_malloc( strlen( re->re_dn ) + strlen( mi->mi_val )
465                 + 10 );
466         sprintf( buf2, "(\"%s\" -> \"%s\")", re->re_dn, mi->mi_val );
467         Debug( LDAP_DEBUG_ARGS,
468                 "replica %s - modify rdn %s (flag: %d)\n",
469                 buf, buf2, drdnflag );
470         free( buf2 );
471     }
472 #endif /* LDAP_DEBUG */
473
474     /* Do the modrdn */
475     rc = ldap_rename2_s( ri->ri_ldp, re->re_dn, mi->mi_val, newsup, drdnflag );
476
477         ldap_get_option( ri->ri_ldp, LDAP_OPT_ERROR_NUMBER, &lderr);
478     return( lderr );
479 }
480
481
482
483 /*
484  * Allocate and initialize an ldapmod struct.
485  */
486 static LDAPMod *
487 alloc_ldapmod( void )
488 {
489     LDAPMod     *ldm;
490
491     ldm = ( struct ldapmod * ) ch_malloc( sizeof ( struct ldapmod ));
492     ldm->mod_type = NULL;
493     ldm->mod_bvalues = ( struct berval ** ) NULL;
494     return( ldm );
495 }
496
497
498
499 /*
500  * Free an ldapmod struct associated mod_bvalues.  NOTE - it is assumed
501  * that mod_bvalues and mod_type contain pointers to the same block of memory
502  * pointed to by the repl struct.  Therefore, it's not freed here.
503  */
504 static void
505 free_ldapmod(
506 LDAPMod *ldm )
507 {
508     int         i;
509
510     if ( ldm == NULL ) {
511         return;
512     }
513     if ( ldm->mod_bvalues != NULL ) {
514         for ( i = 0; ldm->mod_bvalues[ i ] != NULL; i++ ) {
515             free( ldm->mod_bvalues[ i ] );
516         }
517         free( ldm->mod_bvalues );
518     }
519     free( ldm );
520     return;
521 }
522
523
524 /*
525  * Free an an array of LDAPMod pointers and the LDAPMod structs they point
526  * to.
527  */
528 static void
529 free_ldmarr(
530 LDAPMod **ldmarr )
531 {
532     int i;
533
534     for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
535         free_ldapmod( ldmarr[ i ] );
536     }
537     free( ldmarr );
538 }
539
540
541 /*
542  * Create a berval with a single value. 
543  */
544 static struct berval **
545 make_singlevalued_berval( 
546 char    *value,
547 int     len )
548 {
549     struct berval **p;
550
551     p = ( struct berval ** ) ch_malloc( 2 * sizeof( struct berval * ));
552     p[ 0 ] = ( struct berval * ) ch_malloc( sizeof( struct berval ));
553     p[ 1 ] = NULL;
554     p[ 0 ]->bv_val = value;
555     p[ 0 ]->bv_len = len;
556     return( p );
557 }
558
559
560 /*
561  * Given a modification type (string), return an enumerated type.
562  * Avoids ugly copy in op_ldap_modify - lets us use a switch statement
563  * there.
564  */
565 static int
566 getmodtype( 
567 char *type )
568 {
569     if ( !strcmp( type, T_MODSEPSTR )) {
570         return( T_MODSEP );
571     }
572     if ( !strcmp( type, T_MODOPADDSTR )) {
573         return( T_MODOPADD );
574     }
575     if ( !strcmp( type, T_MODOPREPLACESTR )) {
576         return( T_MODOPREPLACE );
577     }
578     if ( !strcmp( type, T_MODOPDELETESTR )) {
579         return( T_MODOPDELETE );
580     }
581     return( T_ERR );
582 }
583
584
585 /*
586  * Perform an LDAP unbind operation.  If replica is NULL, or the
587  * repl_ldp is NULL, just return LDAP_SUCCESS.  Otherwise, unbind,
588  * set the ldp to NULL, and return the result of the unbind call.
589  */
590 static int
591 do_unbind(
592     Ri  *ri
593 )
594 {
595     int         rc = LDAP_SUCCESS;
596
597     if (( ri != NULL ) && ( ri->ri_ldp != NULL )) {
598         rc = ldap_unbind( ri->ri_ldp );
599         if ( rc != LDAP_SUCCESS ) {
600             Debug( LDAP_DEBUG_ANY,
601                     "Error: do_unbind: ldap_unbind failed for %s:%d: %s\n",
602                     ri->ri_hostname, ri->ri_port, ldap_err2string( rc ) );
603         }
604         ri->ri_ldp = NULL;
605     }
606     return rc;
607 }
608
609
610
611 /*
612  * Perform an LDAP bind operation to the replication site given
613  * by replica.  If replica->repl_ldp is non-NULL, then we unbind
614  * from the replica before rebinding.  It should be safe to call
615  * this to re-connect if the replica's connection goes away
616  * for some reason.
617  *
618  * Returns 0 on success, -1 if an LDAP error occurred, and a return
619  * code > 0 if some other error occurred, e.g. invalid bind method.
620  * If an LDAP error occurs, the LDAP error is returned in lderr.
621  */
622 static int
623 do_bind( 
624     Ri  *ri,
625     int *lderr
626 )
627 {
628     int         ldrc;
629
630     *lderr = 0;
631
632     if ( ri == NULL ) {
633         Debug( LDAP_DEBUG_ANY, "Error: do_bind: null ri ptr\n", 0, 0, 0 );
634         return( BIND_ERR_BADRI );
635     }
636
637     if ( ri->ri_ldp != NULL ) {
638         ldrc = ldap_unbind( ri->ri_ldp );
639         if ( ldrc != LDAP_SUCCESS ) {
640             Debug( LDAP_DEBUG_ANY,
641                     "Error: do_bind: ldap_unbind failed: %s\n",
642                     ldap_err2string( ldrc ), 0, 0 );
643         }
644         ri->ri_ldp = NULL;
645     }
646
647     Debug( LDAP_DEBUG_ARGS, "Initializing session to %s:%d\n",
648             ri->ri_hostname, ri->ri_port, 0 );
649
650     ri->ri_ldp = ldap_init( ri->ri_hostname, ri->ri_port );
651     if ( ri->ri_ldp == NULL ) {
652                 Debug( LDAP_DEBUG_ANY, "Error: ldap_init(%s, %d) failed: %s\n",
653                         ri->ri_hostname, ri->ri_port, sys_errlist[ errno ] );
654                 return( BIND_ERR_OPEN );
655     }
656
657         {       /* set version 3 */
658                 int err, version = 3;
659                 err = ldap_set_option(ri->ri_ldp,
660                         LDAP_OPT_PROTOCOL_VERSION, &version);
661
662                 if( err != LDAP_OPT_SUCCESS ) {
663                         Debug( LDAP_DEBUG_ANY,
664                                 "Error: ldap_set_option(%s, LDAP_OPT_VERSION, 3) failed!\n",
665                                 ri->ri_hostname, NULL, NULL );
666
667                         ldap_unbind( ri->ri_ldp );
668                         ri->ri_ldp = NULL;
669                         return BIND_ERR_VERSION;
670                 }
671         }
672
673     /*
674      * Set ldap library options to (1) not follow referrals, and 
675      * (2) restart the select() system call.
676      */
677         {
678                 int err;
679                 err = ldap_set_option(ri->ri_ldp, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
680
681                 if( err != LDAP_OPT_SUCCESS ) {
682                         Debug( LDAP_DEBUG_ANY,
683                                 "Error: ldap_set_option(%s,REFERRALS, OFF) failed!\n",
684                                 ri->ri_hostname, NULL, NULL );
685                         ldap_unbind( ri->ri_ldp );
686                         ri->ri_ldp = NULL;
687                         return BIND_ERR_REFERRALS;
688                 }
689         }
690         ldap_set_option(ri->ri_ldp, LDAP_OPT_RESTART, LDAP_OPT_ON);
691
692     switch ( ri->ri_bind_method ) {
693     case AUTH_SIMPLE:
694         /*
695          * Bind with a plaintext password.
696          */
697         Debug( LDAP_DEBUG_ARGS, "bind to %s:%d as %s (simple)\n",
698                 ri->ri_hostname, ri->ri_port, ri->ri_bind_dn );
699         ldrc = ldap_simple_bind_s( ri->ri_ldp, ri->ri_bind_dn,
700                 ri->ri_password );
701         if ( ldrc != LDAP_SUCCESS ) {
702             Debug( LDAP_DEBUG_ANY,
703                     "Error: ldap_simple_bind_s for %s:%d failed: %s\n",
704                     ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
705             *lderr = ldrc;
706                 ldap_unbind( ri->ri_ldp );
707                 ri->ri_ldp = NULL;
708             return( BIND_ERR_SIMPLE_FAILED );
709         }
710         break;
711     default:
712         Debug(  LDAP_DEBUG_ANY,
713                 "Error: do_bind: unknown auth type \"%d\" for %s:%d\n",
714                 ri->ri_bind_method, ri->ri_hostname, ri->ri_port );
715         ldap_unbind( ri->ri_ldp );
716         ri->ri_ldp = NULL;
717         return( BIND_ERR_BAD_ATYPE );
718     }
719
720         {
721                 int err;
722                 LDAPControl c;
723                 LDAPControl *ctrls[2];
724                 ctrls[0] = &c;
725                 ctrls[1] = NULL;
726
727                 c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
728                 c.ldctl_value.bv_val = NULL;
729                 c.ldctl_value.bv_len = 0;
730                 c.ldctl_iscritical = 1;
731
732                 err = ldap_set_option(ri->ri_ldp, LDAP_OPT_SERVER_CONTROLS, &ctrls);
733
734                 if( err != LDAP_OPT_SUCCESS ) {
735                         Debug( LDAP_DEBUG_ANY,
736                                 "Error: ldap_set_option(%s, SERVER_CONTROLS, ManageDSAit) failed!\n",
737                                 ri->ri_hostname, NULL, NULL );
738                         ldap_unbind( ri->ri_ldp );
739                         ri->ri_ldp = NULL;
740                         return BIND_ERR_MANAGEDSAIT;
741                 }
742         }
743
744         return( BIND_OK );
745 }
746
747
748
749
750
751 /*
752  * For debugging.  Print the contents of an ldmarr array.
753  */
754 static void
755 dump_ldm_array(
756     LDAPMod **ldmarr
757 )
758 {
759     int                  i, j;
760     LDAPMod             *ldm;
761     struct berval       *b;
762     char                *msgbuf;
763
764     for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
765         ldm = ldmarr[ i ];
766         Debug( LDAP_DEBUG_TRACE,
767                 "Trace (%ld): *** ldmarr[ %d ] contents:\n",
768                 (long) getpid(), i, 0 );
769         Debug( LDAP_DEBUG_TRACE,
770                 "Trace (%ld): *** ldm->mod_op: %d\n",
771                 (long) getpid(), ldm->mod_op, 0 );
772         Debug( LDAP_DEBUG_TRACE,
773                 "Trace (%ld): *** ldm->mod_type: %s\n",
774                 (long) getpid(), ldm->mod_type, 0 );
775         if ( ldm->mod_bvalues != NULL ) {
776             for ( j = 0; ( b = ldm->mod_bvalues[ j ] ) != NULL; j++ ) {
777                 msgbuf = ch_malloc( b->bv_len + 512 );
778                 sprintf( msgbuf, "***** bv[ %d ] len = %ld, val = <%s>",
779                         j, b->bv_len, b->bv_val );
780                 Debug( LDAP_DEBUG_TRACE,
781                         "Trace (%ld):%s\n", (long) getpid(), msgbuf, 0 );
782                 free( msgbuf );
783             }
784         }
785     }
786 }
787
788
789 /*
790  * Get the kerberos names from the binddn for "replica" via an ldap search.
791  * Returns a null-terminated array of char *, or NULL if the entry could
792  * not be found or there were no kerberosName attributes.  The caller is
793  * responsible for freeing the returned array and strings it points to.
794  */
795 static char **
796 read_krbnames(
797     Ri  *ri
798 )
799 {
800     int rc;
801     char **krbnames;
802     int ne;
803     LDAPMessage *result, *entry;
804
805     /* First need to bind as NULL */
806     rc = ldap_simple_bind_s( ri->ri_ldp, NULL, NULL );
807     if ( rc != LDAP_SUCCESS ) {
808         Debug( LDAP_DEBUG_ANY,
809                 "Error: null bind failed getting krbnames for %s:%d: %s\n",
810                 ri->ri_hostname, ri->ri_port, ldap_err2string( rc ));
811         return( NULL );
812     }
813     rc = ldap_search_st( ri->ri_ldp, ri->ri_bind_dn, LDAP_SCOPE_BASE,
814             NULL, kattrs, 0, &kst, &result );
815     if ( rc != LDAP_SUCCESS ) {
816         Debug( LDAP_DEBUG_ANY,
817                 "Error: search failed getting krbnames for %s:%d: %s\n",
818                 ri->ri_hostname, ri->ri_port, ldap_err2string( rc ));
819         return( NULL );
820     }
821     ne = ldap_count_entries( ri->ri_ldp, result );
822     if ( ne == 0 ) {
823         Debug( LDAP_DEBUG_ANY,
824                 "Error: Can't find entry \"%s\" for %s:%d kerberos bind\n",
825                 ri->ri_bind_dn, ri->ri_hostname, ri->ri_port );
826             return( NULL );
827     }
828     if ( ne > 1 ) {
829         Debug( LDAP_DEBUG_ANY,
830                 "Error: Kerberos binddn \"%s\" for %s:%dis ambiguous\n",
831                 ri->ri_bind_dn, ri->ri_hostname, ri->ri_port );
832             return( NULL );
833     }
834     entry = ldap_first_entry( ri->ri_ldp, result );
835     if ( entry == NULL ) {
836         Debug( LDAP_DEBUG_ANY,
837                 "Error: Can't find \"%s\" for kerberos binddn for %s:%d\n",
838                     ri->ri_bind_dn, ri->ri_hostname, ri->ri_port );
839         return( NULL );
840     }
841     krbnames = ldap_get_values( ri->ri_ldp, entry, "kerberosName" );
842     ldap_msgfree( result );
843     return( krbnames );
844 }
845
846
847 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
848
849 /*
850  * upcase a string
851  */
852 static void
853 upcase(
854     char *s
855 )
856 {
857     char *p;
858
859     for ( p = s; ( p != NULL ) && ( *p != '\0' ); p++ ) {
860             *p = TOUPPER( (unsigned char) *p );
861     }
862 }
863
864 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */