374
368
/* This function performs the authentication phase of opening a connection.
375
This returns an LDAP result code. */
376
static int do_bind(MYLDAP_SESSION *session,const char *uri)
369
The binddn and bindpw parameters may be used to override the authentication
370
mechanism defined in the configuration. This returns an LDAP result
372
static int do_bind(LDAP *ld,const char *binddn,const char *bindpw,const char *uri)
378
#ifdef LDAP_OPT_X_TLS
380
#endif /* LDAP_OPT_X_TLS */
381
375
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
382
376
#ifndef HAVE_SASL_INTERACT_T
383
377
struct berval cred;
401
395
#endif /* LDAP_OPT_X_TLS */
402
396
/* check if the binddn and bindpw are overwritten in the session */
403
if (session->binddn[0]!='\0')
397
if ((binddn!=NULL)&(binddn[0]!='\0'))
405
399
/* do a simple bind */
406
log_log(LOG_DEBUG,"ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",session->binddn,
407
(session->bindpw[0]!='\0')?"\"***\"":"\"\"",uri);
408
return ldap_simple_bind_s(session->ld,session->binddn,session->bindpw);
400
log_log(LOG_DEBUG,"ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",binddn,
401
((bindpw!=NULL)&&(bindpw[0]!='\0'))?"\"***\"":"\"\"",uri);
402
return ldap_simple_bind_s(ld,binddn,bindpw);
410
404
/* perform SASL bind if requested and available on platform */
411
405
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
426
420
log_log(LOG_DEBUG,"ldap_sasl_interactive_bind_s(NULL,\"%s\") (uri=\"%s\")",
427
421
nslcd_cfg->ldc_sasl_mech,uri);
428
return ldap_sasl_interactive_bind_s(session->ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,NULL,NULL,
422
return ldap_sasl_interactive_bind_s(ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,NULL,NULL,
430
424
do_sasl_interact,(void *)nslcd_cfg);
431
425
#else /* HAVE_SASL_INTERACT_T */
447
441
log_log(LOG_DEBUG,"ldap_sasl_bind_s(NULL,\"%s\",%s) (uri=\"%s\")",
448
442
nslcd_cfg->ldc_sasl_mech,
449
443
nslcd_cfg->ldc_bindpw?"\"***\"":"NULL",uri);
450
return ldap_sasl_bind_s(session->ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,&cred,NULL,NULL,NULL);
444
return ldap_sasl_bind_s(ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,&cred,NULL,NULL,NULL);
451
445
#endif /* not HAVE_SASL_INTERACT_T */
453
447
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
459
453
log_log(LOG_DEBUG,"ldap_simple_bind_s(NULL,%s) (uri=\"%s\")",
460
454
nslcd_cfg->ldc_bindpw?"\"***\"":"NULL",uri);
461
return ldap_simple_bind_s(session->ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_bindpw);
455
return ldap_simple_bind_s(ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_bindpw);
464
458
#ifdef HAVE_LDAP_SET_REBIND_PROC
465
459
/* This function is called by the LDAP library when chasing referrals.
466
460
It is configured with the ldap_set_rebind_proc() below. */
467
static int do_rebind(LDAP *UNUSED(ld),LDAP_CONST char *url,
461
static int do_rebind(LDAP *ld,LDAP_CONST char *url,
468
462
ber_tag_t UNUSED(request),
469
463
ber_int_t UNUSED(msgid),void *arg)
465
MYLDAP_SESSION *session=(MYLDAP_SESSION *)arg;
471
466
log_log(LOG_DEBUG,"rebinding to %s",url);
472
return do_bind((MYLDAP_SESSION *)arg,url);
467
return do_bind(ld,session->binddn,session->bindpw,url);
474
469
#endif /* HAVE_LDAP_SET_REBIND_PROC */
471
/* set a recieve and send timeout on a socket */
472
static int set_socket_timeout(LDAP *ld,time_t sec,suseconds_t usec)
477
log_log(LOG_DEBUG,"set_socket_timeout(%lu,%lu)",sec,usec);
479
if ((rc=ldap_get_option(ld,LDAP_OPT_DESC,&sd))!=LDAP_SUCCESS)
481
log_log(LOG_ERR,"ldap_get_option(LDAP_OPT_DESC) failed: %s",ldap_err2string(rc));
484
/* ignore invalid (probably closed) file descriptors */
488
memset(&tv,0,sizeof(tv));
491
if (setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv)))
493
log_log(LOG_ERR,"setsockopt(%d,SO_RCVTIMEO) failed: %s",sd,strerror(errno));
496
if (setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv)))
498
log_log(LOG_ERR,"setsockopt(%d,SO_RCVTIMEO) failed: %s",sd,strerror(errno));
504
#ifdef LDAP_OPT_CONNECT_CB
505
/* This function is called by the LDAP library once a connection was made to the server. We
506
set a timeout on the socket here, to catch netzwork timeouts during the ssl
507
handshake phase. It is configured with LDAP_OPT_CONNECT_CB. */
508
static int connect_cb(LDAP *ld,Sockbuf UNUSED(*sb),LDAPURLDesc UNUSED(*srv),
509
struct sockaddr UNUSED(*addr),struct ldap_conncb UNUSED(*ctx))
511
/* set timeout options on socket to avoid hang in some cases (a little
512
more than the normal timeout so this should only be triggered in cases
513
where the library behaves incorrectly) */
514
if (nslcd_cfg->ldc_timelimit)
515
set_socket_timeout(ld,nslcd_cfg->ldc_timelimit,500000);
519
/* We have an empty disconnect callback because LDAP_OPT_CONNECT_CB expects
520
both functions to be available. */
521
static void disconnect_cb(LDAP UNUSED(*ld),Sockbuf UNUSED(*sb),struct ldap_conncb UNUSED(*ctx))
524
#endif /* LDAP_OPT_CONNECT_CB */
476
526
/* This function sets a number of properties on the connection, based
477
527
what is configured in the configfile. This function returns an
478
528
LDAP status code. */
527
581
LDAP_SET_OPTION(session->ld,LDAP_OPT_REFERRALS,nslcd_cfg->ldc_referrals?LDAP_OPT_ON:LDAP_OPT_OFF);
528
582
log_log(LOG_DEBUG,"ldap_set_option(LDAP_OPT_RESTART,%s)",nslcd_cfg->ldc_restart?"LDAP_OPT_ON":"LDAP_OPT_OFF");
529
583
LDAP_SET_OPTION(session->ld,LDAP_OPT_RESTART,nslcd_cfg->ldc_restart?LDAP_OPT_ON:LDAP_OPT_OFF);
584
#ifdef LDAP_OPT_CONNECT_CB
585
/* register a connection callback */
586
cb.lc_add=connect_cb;
587
cb.lc_del=disconnect_cb;
589
LDAP_SET_OPTION(session->ld,LDAP_OPT_CONNECT_CB,(void *)&cb);
590
#endif /* LDAP_OPT_CONNECT_CB */
530
591
#ifdef LDAP_OPT_X_TLS
531
592
/* if SSL is desired, then enable it */
532
593
if ( (nslcd_cfg->ldc_ssl_on==SSL_LDAPS) ||
552
/* set timeout options on socket to avoid hang in some cases
553
(we set a short timeout because we don't care too much about properly
554
shutting down the connection) */
555
if (ldap_get_option(session->ld,LDAP_OPT_DESC,&sd)==LDAP_SUCCESS)
558
tv.tv_sec=nslcd_cfg->ldc_timelimit/2;
559
if (!tv.tv_sec) tv.tv_sec=1;
561
(void)setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv));
562
(void)setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv));
564
612
/* if we had reachability problems with the server close the connection */
565
613
if (session->ld!=NULL)
615
/* set timeout options on socket to avoid hang in some cases
616
(we set a short timeout because we don't care too much about properly
617
shutting down the connection) */
618
if (nslcd_cfg->ldc_timelimit)
620
sec=nslcd_cfg->ldc_timelimit/2;
622
set_socket_timeout(session->ld,sec,0);
567
624
/* go over the other searches and partially close them */
568
625
for (i=0;i<MAX_SEARCHES_IN_SESSION;i++)
1476
/* Convert the bervalues to a simple list of strings that can be freed
1477
with one call to free(). */
1478
static const char **bervalues_to_values(struct berval **bvalues)
1485
/* figure out how much memory to allocate */
1486
num_values=ldap_count_values_len(bvalues);
1487
sz=(num_values+1)*sizeof(char *);
1488
for (i=0;i<num_values;i++)
1489
sz+=bvalues[i]->bv_len+1;
1490
/* allocate the needed memory */
1491
buf=(char *)malloc(sz);
1494
log_log(LOG_CRIT,"myldap_get_values_len(): malloc() failed to allocate memory");
1495
ldap_value_free_len(bvalues);
1498
values=(char **)buf;
1499
buf+=(num_values+1)*sizeof(char *);
1500
/* copy from bvalues */
1501
for (i=0;i<num_values;i++)
1504
memcpy(values[i],bvalues[i]->bv_val,bvalues[i]->bv_len);
1505
values[i][bvalues[i]->bv_len]='\0';
1506
buf+=bvalues[i]->bv_len+1;
1509
return (const char **)values;
1512
/* Simple wrapper around ldap_get_values(). */
1513
const char **myldap_get_values_len(MYLDAP_ENTRY *entry,const char *attr)
1515
const char **values;
1516
struct berval **bvalues;
1520
/* check parameters */
1521
if (!is_valid_entry(entry))
1523
log_log(LOG_ERR,"myldap_get_values_len(): invalid result entry passed");
1527
else if (attr==NULL)
1529
log_log(LOG_ERR,"myldap_get_values_len(): invalid attribute name passed");
1533
if (!entry->search->valid)
1534
return NULL; /* search has been stopped */
1536
bvalues=ldap_get_values_len(entry->search->session->ld,entry->search->msg,attr);
1539
if (ldap_get_option(entry->search->session->ld,LDAP_OPT_ERROR_NUMBER,&rc)!=LDAP_SUCCESS)
1540
rc=LDAP_UNAVAILABLE;
1541
/* ignore decoding errors as they are just nonexisting attribute values */
1542
if (rc==LDAP_DECODING_ERROR)
1545
ldap_set_option(entry->search->session->ld,LDAP_OPT_ERROR_NUMBER,&rc);
1547
else if (rc==LDAP_SUCCESS)
1549
/* we have a success code but no values, let's try to get ranged
1551
set=myldap_get_ranged_values(entry,attr);
1554
values=set_tolist(set);
1557
log_log(LOG_WARNING,"myldap_get_values_len() of attribute \"%s\" on entry \"%s\" returned NULL: %s",
1558
attr,myldap_get_dn(entry),ldap_err2string(rc));
1563
values=bervalues_to_values(bvalues);
1564
ldap_value_free_len(bvalues);
1566
/* store values entry so we can free it later on */
1567
for (i=0;i<MAX_RANGED_ATTRIBUTES_PER_ENTRY;i++)
1568
if (entry->rangedattributevalues[i]==NULL)
1570
entry->rangedattributevalues[i]=(char **)values;
1573
/* we found no room to store the values */
1574
log_log(LOG_ERR,"myldap_get_values_len() couldn't store results, increase MAX_RANGED_ATTRIBUTES_PER_ENTRY");
1430
1579
/* Go over the entries in exploded_rdn and see if any start with
1431
1580
the requested attribute. Return a reference to the value part of
1432
1581
the DN (does not modify exploded_rdn). */