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