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