~ubuntu-branches/ubuntu/precise/nss-pam-ldapd/precise-security

« back to all changes in this revision

Viewing changes to nslcd/myldap.c

  • Committer: Package Import Robot
  • Author(s): Arthur de Jong
  • Date: 2011-09-04 21:00:00 UTC
  • mfrom: (14.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20110904210000-pe3u91iga88vtr16
Tags: 0.8.4
* Upload to unstable
* switch to using the member attribute by default instead of
  uniqueMember (backwards incompatible change)
* only return "x" as a password hash when the object has the shadowAccount
  objectClass and nsswitch.conf is configured to do shadow lookups using
  LDAP (this avoids some problems with pam_unix)
* fix problem with partial attribute name matches in DN (thanks Timothy
  White)
* fix a problem with objectSid mappings with recent versions of OpenLDAP
  (patch by Wesley Mason)
* set the socket timeout in a connection callback to avoid timeout
  issues during the SSL handshake (patch by Stefan Völkel)
* check for unknown variables in pam_authz_search
* only check password expiration when authenticating, only check account
  expiration when doing authorisation
* make buffer sizes consistent and grow all buffers holding string
  representations of numbers to be able to hold 64-bit numbers
* update AX_PTHREAD from autoconf-archive
* support querying DNS SRV records from a different domain than the current
  one (based on a patch by James M. Leddy)
* fix a problem with uninitialised memory while parsing the tls_ciphers
  option (closes: #638872) (but doesn't work yet due to #640384)
* implement bounds checking of numeric values read from LDAP (patch by
  Jakub Hrozek)
* correctly support large uid and gid values from LDAP (patch by Jakub
  Hrozek)
* improvements to the configure script (patch by Jakub Hrozek)
* switch to dh for debian/rules and bump debhelper compatibility to 8
* build Debian packages with multiarch support
* ship shlibs (but still no symbol files) for libnss-ldapd since that was
  the easiest way to support multiarch
* fix output in init script when restarting nslcd (closes: #637132)
* correctly handle leading and trailing spaces in preseeded debconf uri
  option (patch by Andreas B. Mundt) (closes: #637863)
* support spaces around database names in /etc/nsswitch.conf while
  configuring package (closes: #640185)
* updated Russian debconf translation by Yuri Kozlov (closes: #637751)
* updated French debconf translation by Christian Perrier (closes: #637756)
* added Slovak debconf translation by Slavko (closes: #637759)
* updated Danish debconf translation by Joe Hansen (closes :#637763)
* updated Brazilian Portuguese debconf translation by Denis Doria
* updated Portuguese debconf translation by Américo Monteiro
* updated Japanese debconf translation by Kenshi Muto (closes: #638195)
* updated Czech debconf translation by Miroslav Kure (closes: #639026)
* updated German debconf translation by Chris Leick (closes: #639107)
* updated Spanish debconf translation by Francisco Javier Cuadrado
  (closes: #639236)
* updated Dutch debconf translation by Arthur de Jong with help from Paul
  Gevers and Jeroen Schot

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
   Copyright (C) 1997-2006 Luke Howard
7
7
   Copyright (C) 2006, 2007 West Consulting
8
 
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Arthur de Jong
 
8
   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Arthur de Jong
9
9
 
10
10
   This library is free software; you can redistribute it and/or
11
11
   modify it under the terms of the GNU Lesser General Public
35
35
 
36
36
#include "config.h"
37
37
 
38
 
/* also include deprecated LDAP functions for now */
39
 
#define LDAP_DEPRECATED 1
40
 
 
41
 
/* for compatibility on Solaris */
42
 
#define LDAP_REFERRALS 1
43
 
 
44
38
#include <stdio.h>
45
39
#include <stdlib.h>
46
40
#include <unistd.h>
62
56
#ifdef HAVE_GSSSASL_H
63
57
#include <gsssasl.h>
64
58
#endif
65
 
/* Try to handle systems with both SASL libraries installed */
66
 
#if defined(HAVE_SASL_SASL_H) && defined(HAVE_SASL_AUXPROP_REQUEST)
 
59
#ifdef HAVE_SASL_SASL_H
67
60
#include <sasl/sasl.h>
68
 
#elif defined(HAVE_SASL_H)
 
61
#endif
 
62
#ifdef HAVE_SASL_H
69
63
#include <sasl.h>
70
64
#endif
71
65
#include <ctype.h>
130
124
 
131
125
/* The maximum number of ranged attribute values that may be stoted
132
126
   per entry. */
133
 
#define MAX_RANGED_ATTRIBUTES_PER_ENTRY 2
 
127
#define MAX_RANGED_ATTRIBUTES_PER_ENTRY 8
134
128
 
135
129
/* A single entry from the LDAP database as returned by
136
130
   myldap_get_entry(). */
372
366
  }
373
367
 
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
 
371
   code. */
 
372
static int do_bind(LDAP *ld,const char *binddn,const char *bindpw,const char *uri)
377
373
{
378
 
#ifdef LDAP_OPT_X_TLS
379
374
  int rc;
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;
389
383
  {
390
384
    log_log(LOG_DEBUG,"ldap_start_tls_s()");
391
385
    errno=0;
392
 
    rc=ldap_start_tls_s(session->ld,NULL,NULL);
 
386
    rc=ldap_start_tls_s(ld,NULL,NULL);
393
387
    if (rc!=LDAP_SUCCESS)
394
388
    {
395
389
      log_log(LOG_WARNING,"ldap_start_tls_s() failed: %s%s%s (uri=\"%s\")",
400
394
  }
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'))
404
398
  {
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);
409
403
  }
410
404
  /* perform SASL bind if requested and available on platform */
411
405
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
416
410
    if (nslcd_cfg->ldc_sasl_secprops!=NULL)
417
411
    {
418
412
      log_log(LOG_DEBUG,"ldap_set_option(LDAP_OPT_X_SASL_SECPROPS,\"%s\")",nslcd_cfg->ldc_sasl_secprops);
419
 
      LDAP_SET_OPTION(session->ld,LDAP_OPT_X_SASL_SECPROPS,(void *)nslcd_cfg->ldc_sasl_secprops);
 
413
      LDAP_SET_OPTION(ld,LDAP_OPT_X_SASL_SECPROPS,(void *)nslcd_cfg->ldc_sasl_secprops);
420
414
    }
421
415
#ifdef HAVE_SASL_INTERACT_T
422
416
    if (nslcd_cfg->ldc_binddn!=NULL)
425
419
    else
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,
429
423
                                        LDAP_SASL_QUIET,
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 */
452
446
  }
453
447
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
458
452
  else
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);
462
456
}
463
457
 
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)
470
464
{
 
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);
473
468
}
474
469
#endif /* HAVE_LDAP_SET_REBIND_PROC */
475
470
 
 
471
/* set a recieve and send timeout on a socket */
 
472
static int set_socket_timeout(LDAP *ld,time_t sec,suseconds_t usec)
 
473
{
 
474
  struct timeval tv;
 
475
  int rc=LDAP_SUCCESS;
 
476
  int sd;
 
477
  log_log(LOG_DEBUG,"set_socket_timeout(%lu,%lu)",sec,usec);
 
478
  /* get the socket */
 
479
  if ((rc=ldap_get_option(ld,LDAP_OPT_DESC,&sd))!=LDAP_SUCCESS)
 
480
  {
 
481
    log_log(LOG_ERR,"ldap_get_option(LDAP_OPT_DESC) failed: %s",ldap_err2string(rc));
 
482
    return rc;
 
483
  }
 
484
  /* ignore invalid (probably closed) file descriptors */
 
485
  if (sd<=0)
 
486
    return LDAP_SUCCESS;
 
487
  /* set timeouts */
 
488
  memset(&tv,0,sizeof(tv));
 
489
  tv.tv_sec=sec;
 
490
  tv.tv_usec=usec;
 
491
  if (setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv)))
 
492
  {
 
493
    log_log(LOG_ERR,"setsockopt(%d,SO_RCVTIMEO) failed: %s",sd,strerror(errno));
 
494
    rc=LDAP_LOCAL_ERROR;
 
495
  }
 
496
  if (setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv)))
 
497
  {
 
498
    log_log(LOG_ERR,"setsockopt(%d,SO_RCVTIMEO) failed: %s",sd,strerror(errno));
 
499
    rc=LDAP_LOCAL_ERROR;
 
500
  }
 
501
  return rc;
 
502
}
 
503
 
 
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))
 
510
{
 
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);
 
516
  return LDAP_SUCCESS;
 
517
}
 
518
 
 
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))
 
522
{
 
523
}
 
524
#endif /* LDAP_OPT_CONNECT_CB */
 
525
 
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. */
481
531
  /* FIXME: move this to a global initialisation routine */
482
532
  int rc;
483
533
  struct timeval tv;
 
534
#ifdef LDAP_OPT_CONNECT_CB
 
535
  /* make this static because OpenLDAP doesn't make it's own copy */
 
536
  static struct ldap_conncb cb;
 
537
#endif /* LDAP_OPT_CONNECT_CB */
484
538
#ifdef LDAP_OPT_X_TLS
485
539
  int i;
486
540
#endif /* LDAP_OPT_X_TLS */
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;
 
588
  cb.lc_arg=NULL;
 
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) ||
547
608
{
548
609
  int i;
549
610
  int rc;
550
 
  int sd=-1;
551
 
  struct timeval tv;
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)
556
 
  {
557
 
    /* ignore errors */
558
 
    tv.tv_sec=nslcd_cfg->ldc_timelimit/2;
559
 
    if (!tv.tv_sec) tv.tv_sec=1;
560
 
    tv.tv_usec=0;
561
 
    (void)setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv));
562
 
    (void)setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv));
563
 
  }
 
611
  time_t sec;
564
612
  /* if we had reachability problems with the server close the connection */
565
613
  if (session->ld!=NULL)
566
614
  {
 
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)
 
619
    {
 
620
      sec=nslcd_cfg->ldc_timelimit/2;
 
621
      if (!sec) sec=1;
 
622
      set_socket_timeout(session->ld,sec,0);
 
623
    }
567
624
    /* go over the other searches and partially close them */
568
625
    for (i=0;i<MAX_SEARCHES_IN_SESSION;i++)
569
626
    {
581
638
          log_log(LOG_DEBUG,"ldap_abandon()");
582
639
          if (ldap_abandon(session->searches[i]->session->ld,session->searches[i]->msgid))
583
640
          {
584
 
            if (ldap_get_option(session->ld,LDAP_OPT_ERROR_NUMBER,&rc)==LDAP_SUCCESS)
 
641
            if (ldap_get_option(session->ld,LDAP_OPT_ERROR_NUMBER,&rc)!=LDAP_SUCCESS)
585
642
              rc=LDAP_OTHER;
586
643
            log_log(LOG_WARNING,"ldap_abandon() failed to abandon search: %s",ldap_err2string(rc));
587
644
          }
600
657
  }
601
658
}
602
659
 
603
 
/* This checks the timeout value of the session and closes the connection
604
 
   to the LDAP server if the timeout has expired and there are no pending
605
 
   searches. */
606
 
static void myldap_session_check(MYLDAP_SESSION *session)
 
660
void myldap_session_check(MYLDAP_SESSION *session)
607
661
{
608
662
  int i;
609
663
  time_t current_time;
636
690
static int do_open(MYLDAP_SESSION *session)
637
691
{
638
692
  int rc;
639
 
  int sd=-1;
640
 
  int off=0;
641
693
  /* if the connection is still there (ie. ldap_unbind() wasn't
642
694
     called) then we can return the cached connection */
643
695
  if (session->ld!=NULL)
673
725
  }
674
726
  /* bind to the server */
675
727
  errno=0;
676
 
  rc=do_bind(session,nslcd_cfg->ldc_uris[session->current_uri].uri);
 
728
  rc=do_bind(session->ld,session->binddn,session->bindpw,
 
729
             nslcd_cfg->ldc_uris[session->current_uri].uri);
677
730
  if (rc!=LDAP_SUCCESS)
678
731
  {
679
732
    /* log actual LDAP error code */
685
738
    do_close(session);
686
739
    return rc;
687
740
  }
688
 
  /* disable keepalive on the LDAP connection socket (why?) */
689
 
  if (ldap_get_option(session->ld,LDAP_OPT_DESC,&sd)==LDAP_SUCCESS)
690
 
  {
691
 
    /* ignore errors */
692
 
    (void)setsockopt(sd,SOL_SOCKET,SO_KEEPALIVE,(void *)&off,sizeof(off));
693
 
  }
694
741
  /* update last activity and finish off state */
695
742
  time(&(session->lastactivity));
696
743
  return LDAP_SUCCESS;
878
925
        if ((rc==LDAP_INVALID_CREDENTIALS)||(rc==LDAP_INSUFFICIENT_ACCESS)||
879
926
            (rc==LDAP_AUTH_METHOD_NOT_SUPPORTED))
880
927
          dotry[search->session->current_uri]=0;
881
 
        /* check whether we should try this URI again */
 
928
        /* check when we should try this URI again */
882
929
        else if (t <= (current_uri->firstfail+nslcd_cfg->ldc_reconnect_retrytime))
883
930
        {
884
931
          t+=nslcd_cfg->ldc_reconnect_sleeptime;
897
944
    if (nexttry>=endtime)
898
945
    {
899
946
      if (search->session->binddn[0]=='\0')
900
 
        log_log(LOG_ERR,"no available LDAP server found");
 
947
        log_log(LOG_ERR,"no available LDAP server found: %s",ldap_err2string(rc));
901
948
      return rc;
902
949
    }
903
950
    /* sleep between tries */
1216
1263
        if (rcp!=NULL)
1217
1264
          *rcp=rc;
1218
1265
        return NULL;
1219
 
 
1220
1266
    }
1221
1267
  }
1222
1268
}
1427
1473
  return NULL;
1428
1474
}
1429
1475
 
 
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)
 
1479
{
 
1480
  int num_values;
 
1481
  int i;
 
1482
  size_t sz;
 
1483
  char *buf;
 
1484
  char **values;
 
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);
 
1492
  if (buf==NULL)
 
1493
  {
 
1494
    log_log(LOG_CRIT,"myldap_get_values_len(): malloc() failed to allocate memory");
 
1495
    ldap_value_free_len(bvalues);
 
1496
    return NULL;
 
1497
  }
 
1498
  values=(char **)buf;
 
1499
  buf+=(num_values+1)*sizeof(char *);
 
1500
  /* copy from bvalues */
 
1501
  for (i=0;i<num_values;i++)
 
1502
  {
 
1503
    values[i]=buf;
 
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;
 
1507
  }
 
1508
  values[i]=NULL;
 
1509
  return (const char **)values;
 
1510
}
 
1511
 
 
1512
/* Simple wrapper around ldap_get_values(). */
 
1513
const char **myldap_get_values_len(MYLDAP_ENTRY *entry,const char *attr)
 
1514
{
 
1515
  const char **values;
 
1516
  struct berval **bvalues;
 
1517
  int rc;
 
1518
  int i;
 
1519
  SET *set;
 
1520
  /* check parameters */
 
1521
  if (!is_valid_entry(entry))
 
1522
  {
 
1523
    log_log(LOG_ERR,"myldap_get_values_len(): invalid result entry passed");
 
1524
    errno=EINVAL;
 
1525
    return NULL;
 
1526
  }
 
1527
  else if (attr==NULL)
 
1528
  {
 
1529
    log_log(LOG_ERR,"myldap_get_values_len(): invalid attribute name passed");
 
1530
    errno=EINVAL;
 
1531
    return NULL;
 
1532
  }
 
1533
  if (!entry->search->valid)
 
1534
    return NULL; /* search has been stopped */
 
1535
  /* get from LDAP */
 
1536
  bvalues=ldap_get_values_len(entry->search->session->ld,entry->search->msg,attr);
 
1537
  if (bvalues==NULL)
 
1538
  {
 
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)
 
1543
    {
 
1544
      rc=LDAP_SUCCESS;
 
1545
      ldap_set_option(entry->search->session->ld,LDAP_OPT_ERROR_NUMBER,&rc);
 
1546
    }
 
1547
    else if (rc==LDAP_SUCCESS)
 
1548
    {
 
1549
      /* we have a success code but no values, let's try to get ranged
 
1550
         values */
 
1551
      set=myldap_get_ranged_values(entry,attr);
 
1552
      if (set==NULL)
 
1553
        return NULL;
 
1554
      values=set_tolist(set);
 
1555
    }
 
1556
    else
 
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));
 
1559
    return NULL;
 
1560
  }
 
1561
  else
 
1562
  {
 
1563
    values=bervalues_to_values(bvalues);
 
1564
    ldap_value_free_len(bvalues);
 
1565
  }
 
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)
 
1569
    {
 
1570
      entry->rangedattributevalues[i]=(char **)values;
 
1571
      return values;
 
1572
    }
 
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");
 
1575
  free(values);
 
1576
  return NULL;
 
1577
}
 
1578
 
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). */
1443
1592
    /* check that RDN starts with attr */
1444
1593
    if (strncasecmp(exploded_rdn[i],attr,l)!=0)
1445
1594
      continue;
 
1595
    j=l;
1446
1596
    /* skip spaces */
1447
 
    for (j=l;isspace(exploded_rdn[i][j]);j++)
1448
 
      /* nothing here */;
 
1597
    while (isspace(exploded_rdn[i][j])) j++;
1449
1598
    /* ensure that we found an equals sign now */
1450
1599
    if (exploded_rdn[i][j]!='=')
 
1600
      continue;
1451
1601
    j++;
1452
1602
    /* skip more spaces */
1453
 
    for (j++;isspace(exploded_rdn[i][j]);j++)
1454
 
      /* nothing here */;
 
1603
    while (isspace(exploded_rdn[i][j])) j++;
1455
1604
    /* ensure that we're not at the end of the string */
1456
1605
    if (exploded_rdn[i][j]=='\0')
1457
1606
      continue;
1698
1847
  }
1699
1848
  return rc;
1700
1849
}
 
1850
 
 
1851
int myldap_modify(MYLDAP_SESSION *session,const char *dn,LDAPMod *mods[])
 
1852
{
 
1853
  if (!is_valid_session(session)||(dn==NULL))
 
1854
  {
 
1855
    log_log(LOG_ERR,"myldap_passwd(): invalid parameter passed");
 
1856
    errno=EINVAL;
 
1857
    return LDAP_OTHER;
 
1858
  }
 
1859
  return ldap_modify_ext_s(session->ld,dn,mods,NULL,NULL);
 
1860
}