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