]> git.sur5r.net Git - openldap/blob - servers/slurpd/ldap_op.c
487f7466cc349792efa5817f1a5949e67132d005
[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 #define DISABLE_BRIDGE
18 #include "portable.h"
19
20 #include <stdio.h>
21 #include <ac/string.h>
22 #include <ac/time.h>
23 #include <sys/types.h>
24
25 #ifdef KERBEROS
26 #ifdef KERBEROS_V
27 #include <kerberosIV/krb.h>
28 #else
29 #include <krb.h>
30 #endif /* KERBEROS_V */
31 #endif /* KERBEROS */
32
33 #include <lber.h>
34 #include <ldap.h>
35
36 #include "slurp.h"
37
38 /* Forward references */
39 static int get_changetype LDAP_P(( char * ));
40 static struct berval **make_singlevalued_berval LDAP_P(( char   *, int ));
41 static int op_ldap_add LDAP_P(( Ri *, Re *, char ** ));
42 static int op_ldap_modify LDAP_P(( Ri *, Re *, char ** ));
43 static int op_ldap_delete LDAP_P(( Ri *, Re *, char ** ));
44 static int op_ldap_modrdn LDAP_P(( Ri *, Re *, char ** ));
45 static LDAPMod *alloc_ldapmod LDAP_P(());
46 static void free_ldapmod LDAP_P(( LDAPMod * ));
47 static void free_ldmarr LDAP_P(( LDAPMod ** ));
48 static int getmodtype LDAP_P(( char * ));
49 static void dump_ldm_array LDAP_P(( LDAPMod ** ));
50 static char **read_krbnames LDAP_P(( Ri * ));
51 static void upcase LDAP_P(( char * ));
52 static int do_bind LDAP_P(( Ri *, int * ));
53 static int do_unbind LDAP_P(( Ri * ));
54
55
56 /* External references */
57 #ifdef DECL_SYS_ERRLIST
58 extern char *sys_errlist[];
59 #endif /* DECL_SYS_ERRLIST */
60
61 extern char *ch_malloc( unsigned long );
62
63 static char *kattrs[] = {"kerberosName", NULL };
64 static struct timeval kst = {30L, 0L};
65
66
67
68 /*
69  * Determine the type of ldap operation being performed and call the
70  * appropriate routine.
71  * - If successful, returns ERR_DO_LDAP_OK
72  * - If a retryable error occurs, ERR_DO_LDAP_RETRYABLE is returned.
73  *   The caller should wait a while and retry the operation.
74  * - If a fatal error occurs, ERR_DO_LDAP_FATAL is returned.  The caller
75  *   should reject the operation and continue with the next replication
76  *   entry.
77  */
78 int
79 do_ldap(
80     Ri          *ri,
81     Re          *re,
82     char        **errmsg
83 )
84 {
85     int rc = 0;
86     int lderr = LDAP_SUCCESS;
87     int retry = 2;
88     char *msg;
89
90     *errmsg = NULL;
91
92     while ( retry > 0 ) {
93         if ( ri->ri_ldp == NULL ) {
94             rc = do_bind( ri, &lderr );
95             if ( rc != BIND_OK ) {
96                 return DO_LDAP_ERR_RETRYABLE;
97             }
98         }
99
100         switch ( re->re_changetype ) {
101         case T_ADDCT:
102             lderr = op_ldap_add( ri, re, errmsg );
103             if ( lderr != LDAP_SUCCESS ) {
104                 Debug( LDAP_DEBUG_ANY,
105                         "Error: ldap_add_s failed adding \"%s\": %s\n",
106                         *errmsg ? *errmsg : ldap_err2string( lderr ),
107                         re->re_dn, 0 );
108             }
109             break;
110         case T_MODIFYCT:
111             lderr = op_ldap_modify( ri, re, errmsg );
112             if ( lderr != LDAP_SUCCESS ) {
113                 Debug( LDAP_DEBUG_ANY,
114                         "Error: ldap_modify_s failed modifying \"%s\": %s\n",
115                         *errmsg ? *errmsg : ldap_err2string( lderr ),
116                         re->re_dn, 0 );
117             }
118             break;
119         case T_DELETECT:
120             lderr = op_ldap_delete( ri, re, errmsg );
121             if ( lderr != LDAP_SUCCESS ) {
122                 Debug( LDAP_DEBUG_ANY,
123                         "Error: ldap_delete_s failed deleting \"%s\": %s\n",
124                         *errmsg ? *errmsg : ldap_err2string( lderr ),
125                         re->re_dn, 0 );
126             }
127             break;
128         case T_MODRDNCT:
129             lderr = op_ldap_modrdn( ri, re, errmsg );
130             if ( lderr != LDAP_SUCCESS ) {
131                 Debug( LDAP_DEBUG_ANY,
132                         "Error: ldap_modrdn_s failed modifying %s: %s\n",
133                         *errmsg ? *errmsg : ldap_err2string( lderr ),
134                         re->re_dn, 0 );
135             }
136             break;
137         default:
138             Debug( LDAP_DEBUG_ANY,
139                     "Error: do_ldap: bad op \"%d\", dn = \"%s\"\n",
140                     re->re_changetype, re->re_dn, 0 );
141             return DO_LDAP_ERR_FATAL;
142         }
143
144         /*
145          * Analyze return code.  If ok, just return.  If LDAP_SERVER_DOWN,
146          * we may have been idle long enough that the remote slapd timed
147          * us out.  Rebind and try again.
148          */
149         if ( lderr == LDAP_SUCCESS ) {
150             return DO_LDAP_OK;
151         } else if ( lderr == LDAP_SERVER_DOWN ) {
152             /* The LDAP server may have timed us out - rebind and try again */
153             (void) do_unbind( ri );
154             retry--;
155         } else {
156             return DO_LDAP_ERR_FATAL;
157         }
158     }
159     return DO_LDAP_ERR_FATAL;
160 }
161
162
163
164
165 /*
166  * Perform an ldap add operation.
167  */
168 static int
169 op_ldap_add(
170     Ri          *ri,
171     Re          *re,
172     char        **errmsg
173 )
174 {
175     Mi          *mi;
176     int         nattrs, rc = 0, i;
177     LDAPMod     *ldm, **ldmarr;
178     int         lderr = 0;
179
180     nattrs = i = 0;
181     ldmarr = NULL;
182
183     /*
184      * Construct a null-terminated array of LDAPMod structs.
185      */
186     mi = re->re_mods;
187     while ( mi[ i ].mi_type != NULL ) {
188         ldm = alloc_ldapmod();
189         ldmarr = ( LDAPMod ** ) ch_realloc( ldmarr,
190                 ( nattrs + 2 ) * sizeof( LDAPMod * ));
191         ldmarr[ nattrs ] = ldm;
192         ldm->mod_op = LDAP_MOD_BVALUES;
193         ldm->mod_type = mi[ i ].mi_type;
194         ldm->mod_bvalues =
195                 make_singlevalued_berval( mi[ i ].mi_val, mi[ i ].mi_len );
196         i++;
197         nattrs++;
198     }
199
200     if ( ldmarr != NULL ) {
201         ldmarr[ nattrs ] = NULL;
202
203         /* Perform the operation */
204         Debug( LDAP_DEBUG_ARGS, "replica %s:%d - add dn \"%s\"\n",
205                 ri->ri_hostname, ri->ri_port, re->re_dn );
206         rc = ldap_add_s( ri->ri_ldp, re->re_dn, ldmarr );
207         lderr = ri->ri_ldp->ld_errno;
208     } else {
209         *errmsg = "No modifications to do";
210         Debug( LDAP_DEBUG_ANY,
211                 "Error: op_ldap_add: no mods to do (%s)!", 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, *nldm, **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              1
363 #define GOT_DRDNFLAGSTR         2
364 #define GOT_ALLNEWRDNFLAGS      ( GOT_NEWRDN | GOT_DRDNFLAGSTR )
365 static int
366 op_ldap_modrdn(
367     Ri          *ri,
368     Re          *re,
369     char        **errmsg
370 )
371 {
372     int         rc = 0;
373     Mi          *mi;
374     int         i;
375     int         state = 0;
376     int         drdnflag = -1;
377     char        *newrdn;
378
379     if ( re->re_mods == NULL ) {
380         *errmsg = "No arguments given";
381         Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: no arguments\n",
382                 0, 0, 0 );
383             return -1;
384     }
385
386     /*
387      * Get the arguments: should see newrdn: and deleteoldrdn: args.
388      */
389     for ( mi = re->re_mods, i = 0; mi[ i ].mi_type != NULL; i++ ) {
390         if ( !strcmp( mi[ i ].mi_type, T_NEWRDNSTR )) {
391             newrdn = mi[ i ].mi_val;
392             state |= GOT_NEWRDN;
393         } else if ( !strcmp( mi[ i ].mi_type, T_DRDNFLAGSTR )) {
394             state |= GOT_DRDNFLAGSTR;
395             if ( !strcmp( mi[ i ].mi_val, "0" )) {
396                 drdnflag = 0;
397             } else if ( !strcmp( mi[ i ].mi_val, "1" )) {
398                 drdnflag = 1;
399             } else {
400                 Debug( LDAP_DEBUG_ANY,
401                         "Error: op_ldap_modrdn: bad deleteoldrdn arg \"%s\"\n",
402                         mi[ i ].mi_val, 0, 0 );
403                 *errmsg = "Incorrect argument to deleteoldrdn";
404                 return -1;
405             }
406         } else {
407             Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: bad type \"%s\"\n",
408                     mi[ i ].mi_type, 0, 0 );
409             *errmsg = "Bad value in replication log entry";
410             return -1;
411         }
412     }
413
414     /*
415      * Punt if we don't have all the args.
416      */
417     if ( state != GOT_ALLNEWRDNFLAGS ) {
418         Debug( LDAP_DEBUG_ANY, "Error: op_ldap_modrdn: missing arguments\n",
419                 0, 0, 0 );
420         *errmsg = "Missing argument: requires \"newrdn\" and \"deleteoldrdn\"";
421         return -1;
422     }
423
424 #ifdef LDAP_DEBUG
425     if ( ldap_debug & LDAP_DEBUG_ARGS ) {
426         char buf[ 256 ];
427         char *buf2;
428         sprintf( buf, "%s:%d", ri->ri_hostname, ri->ri_port );
429         buf2 = (char *) ch_malloc( strlen( re->re_dn ) + strlen( mi->mi_val )
430                 + 10 );
431         sprintf( buf2, "(\"%s\" -> \"%s\")", re->re_dn, mi->mi_val );
432         Debug( LDAP_DEBUG_ARGS,
433                 "replica %s - modify rdn %s (flag: %d)\n",
434                 buf, buf2, drdnflag );
435         free( buf2 );
436     }
437 #endif /* LDAP_DEBUG */
438
439     /* Do the modrdn */
440     rc = ldap_modrdn2_s( ri->ri_ldp, re->re_dn, mi->mi_val, drdnflag );
441
442     return( ri->ri_ldp->ld_errno );
443 }
444
445
446
447 /*
448  * Allocate and initialize an ldapmod struct.
449  */
450 static LDAPMod *
451 alloc_ldapmod()
452 {
453     LDAPMod     *ldm;
454
455     ldm = ( struct ldapmod * ) ch_malloc( sizeof ( struct ldapmod ));
456     ldm->mod_type = NULL;
457     ldm->mod_bvalues = ( struct berval ** ) NULL;
458     return( ldm );
459 }
460
461
462
463 /*
464  * Free an ldapmod struct associated mod_bvalues.  NOTE - it is assumed
465  * that mod_bvalues and mod_type contain pointers to the same block of memory
466  * pointed to by the repl struct.  Therefore, it's not freed here.
467  */
468 static void
469 free_ldapmod(
470 LDAPMod *ldm )
471 {
472     int         i;
473
474     if ( ldm == NULL ) {
475         return;
476     }
477     if ( ldm->mod_bvalues != NULL ) {
478         for ( i = 0; ldm->mod_bvalues[ i ] != NULL; i++ ) {
479             free( ldm->mod_bvalues[ i ] );
480         }
481         free( ldm->mod_bvalues );
482     }
483     free( ldm );
484     return;
485 }
486
487
488 /*
489  * Free an an array of LDAPMod pointers and the LDAPMod structs they point
490  * to.
491  */
492 static void
493 free_ldmarr(
494 LDAPMod **ldmarr )
495 {
496     int i;
497
498     for ( i = 0; ldmarr[ i ] != NULL; i++ ) {
499         free_ldapmod( ldmarr[ i ] );
500     }
501     free( ldmarr );
502 }
503
504
505 /*
506  * Create a berval with a single value. 
507  */
508 static struct berval **
509 make_singlevalued_berval( 
510 char    *value,
511 int     len )
512 {
513     struct berval **p;
514
515     p = ( struct berval ** ) ch_malloc( 2 * sizeof( struct berval * ));
516     p[ 0 ] = ( struct berval * ) ch_malloc( sizeof( struct berval ));
517     p[ 1 ] = NULL;
518     p[ 0 ]->bv_val = value;
519     p[ 0 ]->bv_len = len;
520     return( p );
521 }
522
523
524 /*
525  * Given a modification type (string), return an enumerated type.
526  * Avoids ugly copy in op_ldap_modify - lets us use a switch statement
527  * there.
528  */
529 static int
530 getmodtype( 
531 char *type )
532 {
533     if ( !strcmp( type, T_MODSEPSTR )) {
534         return( T_MODSEP );
535     }
536     if ( !strcmp( type, T_MODOPADDSTR )) {
537         return( T_MODOPADD );
538     }
539     if ( !strcmp( type, T_MODOPREPLACESTR )) {
540         return( T_MODOPREPLACE );
541     }
542     if ( !strcmp( type, T_MODOPDELETESTR )) {
543         return( T_MODOPDELETE );
544     }
545     return( T_ERR );
546 }
547
548
549 /*
550  * Perform an LDAP unbind operation.  If replica is NULL, or the
551  * repl_ldp is NULL, just return LDAP_SUCCESS.  Otherwise, unbind,
552  * set the ldp to NULL, and return the result of the unbind call.
553  */
554 static int
555 do_unbind(
556     Ri  *ri
557 )
558 {
559     int         rc = LDAP_SUCCESS;
560
561     if (( ri != NULL ) && ( ri->ri_ldp != NULL )) {
562         rc = ldap_unbind( ri->ri_ldp );
563         if ( rc != LDAP_SUCCESS ) {
564             Debug( LDAP_DEBUG_ANY,
565                     "Error: do_unbind: ldap_unbind failed for %s:%d: %s\n",
566                     ldap_err2string( rc ), ri->ri_hostname, ri->ri_port );
567         }
568         ri->ri_ldp = NULL;
569     }
570     return rc;
571 }
572
573
574
575 /*
576  * Perform an LDAP bind operation to the replication site given
577  * by replica.  If replica->repl_ldp is non-NULL, then we unbind
578  * from the replica before rebinding.  It should be safe to call
579  * this to re-connect if the replica's connection goes away
580  * for some reason.
581  *
582  * Returns 0 on success, -1 if an LDAP error occurred, and a return
583  * code > 0 if some other error occurred, e.g. invalid bind method.
584  * If an LDAP error occurs, the LDAP error is returned in lderr.
585  */
586 static int
587 do_bind( 
588     Ri  *ri,
589     int *lderr
590 )
591 {
592     int         rc;
593     int         ldrc;
594     char        msgbuf[ 1024];
595 #ifdef KERBEROS
596     int retval = 0;
597     int kni, got_tgt;
598     char **krbnames;
599     char *skrbnames[ 2 ];
600     char realm[ REALM_SZ ];
601     char name[ ANAME_SZ ];
602     char instance[ INST_SZ ];
603 #endif /* KERBEROS */
604
605     *lderr = 0;
606
607     if ( ri == NULL ) {
608         Debug( LDAP_DEBUG_ANY, "Error: do_bind: null ri ptr\n", 0, 0, 0 );
609         return( BIND_ERR_BADRI );
610     }
611
612     if ( ri->ri_ldp != NULL ) {
613         ldrc = ldap_unbind( ri->ri_ldp );
614         if ( ldrc != LDAP_SUCCESS ) {
615             Debug( LDAP_DEBUG_ANY,
616                     "Error: do_bind: ldap_unbind failed: %s\n",
617                     ldap_err2string( ldrc ), 0, 0 );
618         }
619         ri->ri_ldp = NULL;
620     }
621
622     Debug( LDAP_DEBUG_ARGS, "Open connection to %s:%d\n",
623             ri->ri_hostname, ri->ri_port, 0 );
624     ri->ri_ldp = ldap_open( ri->ri_hostname, ri->ri_port );
625     if ( ri->ri_ldp == NULL ) {
626         Debug( LDAP_DEBUG_ANY, "Error: ldap_open(%s, %d) failed: %s\n",
627                 ri->ri_hostname, ri->ri_port, sys_errlist[ errno ] );
628         return( BIND_ERR_OPEN );
629     }
630
631     /*
632      * Set ldap library options to (1) not follow referrals, and 
633      * (2) restart the select() system call.
634      */
635 #ifdef LDAP_REFERRALS
636     ri->ri_ldp->ld_options &= ~LDAP_OPT_REFERRALS;
637 #endif /* LDAP_REFERRALS */
638     ri->ri_ldp->ld_options |= LDAP_OPT_RESTART;
639
640     switch ( ri->ri_bind_method ) {
641     case AUTH_KERBEROS:
642 #ifndef KERBEROS
643         Debug( LDAP_DEBUG_ANY,
644             "Error: Kerberos bind for %s:%d, but not compiled w/kerberos\n",
645             ri->ri_hostname, ri->ri_port, 0 );
646         return( BIND_ERR_KERBEROS_FAILED );
647 #else /* KERBEROS */
648         /*
649          * Bind using kerberos.
650          * If "bindprincipal" was given in the config file, then attempt
651          * to get a TGT for that principal (via the srvtab file).  If only
652          * a binddn was given, then we need to read that entry to get
653          * the kerberosName attributes, and try to get a TGT for one
654          * of them.  All are tried.  The first one which succeeds is
655          * returned.  XXX It might be a good idea to just require a
656          * bindprincipal.  Reading the entry every time might be a significant
657          * amount of overhead, if the connection is closed between most
658          * updates.
659          */
660
661         if ( ri->ri_principal != NULL ) {
662             skrbnames[ 0 ] = ri->ri_principal;
663             skrbnames[ 1 ] = NULL;
664             krbnames = skrbnames;
665         } else {
666             krbnames = read_krbnames( ri );
667         }       
668             
669         if (( krbnames == NULL ) || ( krbnames[ 0 ] == NULL )) {
670             Debug( LDAP_DEBUG_ANY,
671                     "Error: Can't find krbname for binddn \"%s\"\n",
672                     ri->ri_bind_dn, 0, 0 );
673             retval = BIND_ERR_KERBEROS_FAILED;
674             goto kexit;
675         }
676         /*
677          * Now we've got one or more kerberos principals.  See if any
678          * of them are in the srvtab file.
679          */
680         got_tgt = 0;
681         for ( kni = 0; krbnames[ kni ] != NULL; kni++ ) {
682             rc = kname_parse( name, instance, realm, krbnames[ kni ]);
683             if ( rc != KSUCCESS ) {
684                 continue;
685             }
686             upcase( realm );
687             rc = krb_get_svc_in_tkt( name, instance, realm, "krbtgt", realm,
688                     1, ri->ri_srvtab );
689             if ( rc != KSUCCESS) {
690                 Debug( LDAP_DEBUG_ANY, "Error: Can't get TGT for %s: %s\n",
691                         krbnames[ kni ], krb_err_txt[ rc ], 0 );
692             } else {
693                 got_tgt = 1;
694                 break;
695             }
696         }
697         if (!got_tgt) {
698             Debug( LDAP_DEBUG_ANY,
699                     "Error: Could not obtain TGT for DN \"%s\"\n", 
700                     ri->ri_bind_dn, 0, 0 );
701             retval = BIND_ERR_KERBEROS_FAILED;
702             goto kexit;
703         }
704         /*
705          * We've got a TGT.  Do a kerberos bind.
706          */
707         Debug( LDAP_DEBUG_ARGS, "bind to %s:%d as %s (kerberos)\n",
708                 ri->ri_hostname, ri->ri_port, ri->ri_bind_dn );
709         ldrc = ldap_kerberos_bind_s( ri->ri_ldp, ri->ri_bind_dn );
710         ri->ri_principal = strdup( krbnames[ kni ] );
711         if ( ldrc != LDAP_SUCCESS ) {
712             Debug( LDAP_DEBUG_ANY, "Error: kerberos bind for %s:%dfailed: %s\n",
713                 ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
714             *lderr = ldrc;
715             retval = BIND_ERR_KERBEROS_FAILED;
716             goto kexit;
717         }
718 kexit:  if ( krbnames != NULL ) {
719             ldap_value_free( krbnames );
720         }
721         return( retval);
722         break;
723 #endif /* KERBEROS */
724     case AUTH_SIMPLE:
725         /*
726          * Bind with a plaintext password.
727          */
728         Debug( LDAP_DEBUG_ARGS, "bind to %s:%d as %s (simple)\n",
729                 ri->ri_hostname, ri->ri_port, ri->ri_bind_dn );
730         ldrc = ldap_simple_bind_s( ri->ri_ldp, ri->ri_bind_dn,
731                 ri->ri_password );
732         if ( ldrc != LDAP_SUCCESS ) {
733             Debug( LDAP_DEBUG_ANY,
734                     "Error: ldap_simple_bind_s for %s:%d failed: %s\n",
735                     ri->ri_hostname, ri->ri_port, ldap_err2string( ldrc ));
736             *lderr = ldrc;
737             return( BIND_ERR_SIMPLE_FAILED );
738         } else {
739             return( BIND_OK );
740         }
741         break;
742     default:
743         Debug(  LDAP_DEBUG_ANY,
744                 "Error: do_bind: unknown auth type \"%d\" for %s:%d\n",
745                 ri->ri_bind_method, ri->ri_hostname, ri->ri_port );
746         return( BIND_ERR_BAD_ATYPE );
747     }
748 }
749
750
751
752
753
754 /*
755  * For debugging.  Print the contents of an ldmarr array.
756  */
757 static void
758 dump_ldm_array(
759 LDAPMod **ldmarr )
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 (%d): *** ldmarr[ %d ] contents:\n",
770                 getpid(), i, 0 );
771         Debug( LDAP_DEBUG_TRACE,
772                 "Trace (%d): *** ldm->mod_op: %d\n",
773                 getpid(), ldm->mod_op, 0 );
774         Debug( LDAP_DEBUG_TRACE,
775                 "Trace (%d): *** ldm->mod_type: %s\n",
776                 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 = %d, val = <%s>",
781                         j, b->bv_len, b->bv_val );
782                 Debug( LDAP_DEBUG_TRACE,
783                         "Trace (%d):%s\n", 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     char *p;
858
859     for ( p = s; ( p != NULL ) && ( *p != '\0' ); p++ ) {
860         if ( islower( *p )) {
861             *p = toupper( *p );
862         }
863     }
864 }