~ubuntu-branches/ubuntu/raring/autofs5/raring

« back to all changes in this revision

Viewing changes to modules/lookup_ldap.c

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2009-03-09 01:16:48 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090309011648-gjynlid883f0s2c4
Tags: 5.0.4-1
* New upstream version (5.0.4 plus patchset as of 2009/03/09).
  * Closes: #518728.
  * Remove dpatch 14, applied upstream.
* New dpatch 14 to avoid using the relatively young SOCK_CLOEXEC
  feature.
* Only invoke 'make clean' on clean target so ./configure isn't
  purged.
* Fix a typo in the postinst regarding the ucf conffile handling.
* Add 'set -e' to package maintenance scripts.
* Drop unnecessary /var/run/autofs from package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
        char *query, **attrs;
56
56
        struct berval *cookie;
57
57
        int morePages;
58
 
        unsigned int totalCount;
 
58
        ber_int_t totalCount;
59
59
        LDAPMessage *result;
60
60
        time_t age;
61
61
};
63
63
static LDAP *auth_init(unsigned logopt, const char *, struct lookup_context *);
64
64
 
65
65
#ifndef HAVE_LDAP_CREATE_PAGE_CONTROL
66
 
int ldap_create_page_control(LDAP *ldap, unsigned int pagesize,
 
66
int ldap_create_page_control(LDAP *ldap, ber_int_t pagesize,
67
67
                             struct berval *cookie, char isCritical,
68
68
                             LDAPControl **output)
69
69
{
93
93
 
94
94
#ifndef HAVE_LDAP_PARSE_PAGE_CONTROL
95
95
int ldap_parse_page_control(LDAP *ldap, LDAPControl **controls,
96
 
                            unsigned int *totalcount, struct berval **cookie)
 
96
                            ber_int_t *totalcount, struct berval **cookie)
97
97
{
98
98
        int i, rc;
99
99
        BerElement *theBer;
122
122
}
123
123
#endif /* HAVE_LDAP_PARSE_PAGE_CONTROL */
124
124
 
 
125
static void uris_mutex_lock(struct lookup_context *ctxt)
 
126
{
 
127
        int status = pthread_mutex_lock(&ctxt->uris_mutex);
 
128
        if (status)
 
129
                fatal(status);
 
130
        return;
 
131
}
 
132
 
 
133
static void uris_mutex_unlock(struct lookup_context *ctxt)
 
134
{
 
135
        int status = pthread_mutex_unlock(&ctxt->uris_mutex);
 
136
        if (status)
 
137
                fatal(status);
 
138
        return;
 
139
}
 
140
 
125
141
int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
126
142
{
127
143
        int rv;
599
615
 
600
616
                if (!do_bind(logopt, ldap, ctxt)) {
601
617
                        unbind_ldap_connection(logopt, ldap, ctxt);
602
 
                        autofs_sasl_done(ctxt);
 
618
                        autofs_sasl_dispose(ctxt);
603
619
                        error(logopt, MODPREFIX "cannot bind to server");
604
620
                        return NULL;
605
621
                }
627
643
        LIST_HEAD(tmp);
628
644
 
629
645
        /* Try each uri in list, add connect fails to tmp list */
 
646
        uris_mutex_lock(ctxt);
630
647
        p = ctxt->uri->next;
631
648
        while(p != ctxt->uri) {
632
649
                this = list_entry(p, struct ldap_uri, list);
633
 
                p = p->next;
 
650
                uris_mutex_unlock(ctxt);
634
651
                debug(logopt, "trying server %s", this->uri);
635
652
                ldap = connect_to_server(logopt, this->uri, ctxt);
636
653
                if (ldap) {
637
654
                        info(logopt, "connected to uri %s", this->uri);
 
655
                        uris_mutex_lock(ctxt);
638
656
                        break;
639
657
                }
 
658
                uris_mutex_lock(ctxt);
 
659
                p = p->next;
640
660
                list_del_init(&this->list);
641
661
                list_add_tail(&this->list, &tmp);
642
662
        }
648
668
        list_splice(ctxt->uri, &tmp);
649
669
        INIT_LIST_HEAD(ctxt->uri);
650
670
        list_splice(&tmp, ctxt->uri);
 
671
        uris_mutex_unlock(ctxt);
651
672
 
652
673
        return ldap;
653
674
}
662
683
                return ldap;
663
684
        }
664
685
 
 
686
        uris_mutex_lock(ctxt);
665
687
        this = list_entry(ctxt->uri->next, struct ldap_uri, list);
 
688
        uris_mutex_unlock(ctxt);
666
689
        ldap = do_connect(logopt, this->uri, ctxt);
667
690
        if (ldap)
668
691
                return ldap;
669
692
 
670
693
        /* Failed to connect, put at end of list */
 
694
        uris_mutex_lock(ctxt);
671
695
        list_del_init(&this->list);
672
696
        list_add_tail(&this->list, ctxt->uri);
 
697
        uris_mutex_unlock(ctxt);
673
698
 
674
699
#ifdef WITH_SASL
675
 
        autofs_sasl_done(ctxt);
 
700
        autofs_sasl_dispose(ctxt);
676
701
#endif
677
702
 
678
703
        /* Current server failed connect, try the rest */
1203
1228
 
1204
1229
static void free_context(struct lookup_context *ctxt)
1205
1230
{
 
1231
        int ret;
 
1232
 
1206
1233
        if (ctxt->schema) {
1207
1234
                free(ctxt->schema->map_class);
1208
1235
                free(ctxt->schema->map_attr);
1235
1262
                free(ctxt->base);
1236
1263
        if (ctxt->uri)
1237
1264
                defaults_free_uris(ctxt->uri);
 
1265
        ret = pthread_mutex_destroy(&ctxt->uris_mutex);
 
1266
        if (ret)
 
1267
                fatal(ret);
1238
1268
        if (ctxt->sdns)
1239
1269
                defaults_free_searchdns(ctxt->sdns);
1240
1270
        free(ctxt);
1286
1316
        }
1287
1317
        memset(ctxt, 0, sizeof(struct lookup_context));
1288
1318
 
 
1319
        ret = pthread_mutex_init(&ctxt->uris_mutex, NULL);
 
1320
        if (ret) {
 
1321
                error(LOGOPT_ANY, MODPREFIX "failed to init uris mutex");
 
1322
                free(ctxt);
 
1323
                return 1;
 
1324
        }
 
1325
 
1289
1326
        /* If a map type isn't explicitly given, parse it like sun entries. */
1290
1327
        if (mapfmt == NULL)
1291
1328
                mapfmt = MAPFMT_DEFAULT;
1330
1367
                free_context(ctxt);
1331
1368
                return 1;
1332
1369
        }
 
1370
 
 
1371
        /* Init the sasl callbacks */
 
1372
        if (!autofs_sasl_client_init(LOGOPT_NONE)) {
 
1373
                error(LOGOPT_ANY, "failed to init sasl client");
 
1374
                free_context(ctxt);
 
1375
                return 1;
 
1376
        }
1333
1377
#endif
1334
1378
 
1335
1379
        if (ctxt->server || !ctxt->uri) {
1505
1549
        return NSS_STATUS_SUCCESS;
1506
1550
}
1507
1551
 
 
1552
static int get_percent_decoded_len(const char *name)
 
1553
{
 
1554
        int escapes = 0;
 
1555
        int escaped = 0;
 
1556
        char *tmp = name;
 
1557
        int look_for_close = 0;
 
1558
 
 
1559
        while (*tmp) {
 
1560
                if (*tmp == '%') {
 
1561
                        /* assume escapes aren't interpreted inside brackets */
 
1562
                        if (look_for_close) {
 
1563
                                tmp++;
 
1564
                                continue;
 
1565
                        }
 
1566
                        /* check for escaped % */
 
1567
                        if (escaped) {
 
1568
                                tmp++;
 
1569
                                escaped = 0;
 
1570
                                continue;
 
1571
                        }
 
1572
                        escapes++;
 
1573
                        tmp++;
 
1574
                        if (*tmp == '[') {
 
1575
                                escapes++;
 
1576
                                tmp++;
 
1577
                                look_for_close = 1;
 
1578
                        } else
 
1579
                                escaped = 1;
 
1580
                } else if (*tmp == ']' && look_for_close) {
 
1581
                        escaped = 0;
 
1582
                        escapes++;
 
1583
                        tmp++;
 
1584
                        look_for_close = 0;
 
1585
                } else {
 
1586
                        tmp++;
 
1587
                        escaped = 0;
 
1588
                }
 
1589
        }
 
1590
 
 
1591
        assert(strlen(name) > escapes);
 
1592
        return strlen(name) - escapes;
 
1593
}
 
1594
 
 
1595
/*
 
1596
 * Try to catch heap corruption if our logic happens to be incorrect.
 
1597
 */
 
1598
static void validate_string_len(const char *orig, char *start,
 
1599
                                char *end, unsigned int len)
 
1600
{
 
1601
        debug(LOGOPT_NONE, MODPREFIX "string %s encoded as %s", orig, start);
 
1602
        /* make sure we didn't overflow the allocated space */
 
1603
        if (end - start > len + 1) {
 
1604
                crit(LOGOPT_ANY, MODPREFIX "orig %s, len %d", orig, len);
 
1605
                crit(LOGOPT_ANY, MODPREFIX "en/decoded %s, len %d", start,
 
1606
                     end - start);
 
1607
        }
 
1608
        assert(end-start <= len + 1);
 
1609
}
 
1610
 
1508
1611
/*
1509
1612
 * Deal with encode and decode of % hack.
1510
1613
 * Return
1512
1615
 * -1 => syntax error or alloc fail.
1513
1616
 * 1 transofrmed value returned.
1514
1617
 */
 
1618
/*
 
1619
 * Assumptions: %'s must be escaped by %'s.  %'s are not used to escape
 
1620
 * anything else except capital letters (so you can't escape a closing
 
1621
 * bracket, for example).
 
1622
 */
1515
1623
static int decode_percent_hack(const char *name, char **key)
1516
1624
{
1517
1625
        const char *tmp;
1518
1626
        char *ptr, *new;
 
1627
        unsigned int len;
 
1628
        int escaped = 0, look_for_close = 0;
1519
1629
 
1520
1630
        if (!key)
1521
1631
                return -1;
1522
1632
 
1523
1633
        *key = NULL;
1524
1634
 
1525
 
        tmp = name;
1526
 
        while (*tmp && *tmp != '%' && *tmp != '[' && *tmp != ']')
1527
 
                tmp++;
1528
 
        if (!*tmp)
1529
 
                return 0;
1530
 
 
1531
 
        tmp = name;
1532
 
        while (*tmp) {
1533
 
                if (*tmp == '%') {
1534
 
                        tmp++;
1535
 
                        if (!*tmp)
1536
 
                                return -1;
1537
 
                        if (*tmp != '[')
1538
 
                                continue;
1539
 
                        tmp++;
1540
 
                        while (*tmp && *tmp != ']') {
1541
 
                                if (*tmp == '%')
1542
 
                                        tmp++;
1543
 
                                tmp++;
1544
 
                        }
1545
 
                        if (!tmp)
1546
 
                                return -1;
1547
 
                }
1548
 
                tmp++;
1549
 
        }
1550
 
 
1551
 
        new = malloc(strlen(name) + 1);
 
1635
        len = get_percent_decoded_len(name);
 
1636
        new = malloc(len + 1);
1552
1637
        if (!new)
1553
1638
                return -1;
1554
1639
 
1555
1640
        ptr = new;
1556
1641
        tmp = name;
1557
1642
        while (*tmp) {
1558
 
                if (*tmp == '%' || *tmp == '[' || *tmp == ']') {
1559
 
                        tmp++;
1560
 
                        if (*tmp && *tmp != '%')
 
1643
                if (*tmp == '%') {
 
1644
                        if (escaped) {
 
1645
                                *ptr++ = *tmp++;
 
1646
                                if (!look_for_close)
 
1647
                                        escaped = 0;
1561
1648
                                continue;
 
1649
                        }
 
1650
                        tmp++;
 
1651
                        if (*tmp == '[') {
 
1652
                                tmp++;
 
1653
                                look_for_close = 1;
 
1654
                                escaped = 1;
 
1655
                        } else
 
1656
                                escaped = 1;
 
1657
                } else if (*tmp == ']' && look_for_close) {
 
1658
                        tmp++;
 
1659
                        look_for_close = 0;
 
1660
                } else {
 
1661
                        escaped = 0;
 
1662
                        *ptr++ = *tmp++;
1562
1663
                }
1563
 
                *ptr++ = *tmp++;
1564
1664
        }
1565
1665
        *ptr = '\0';
1566
 
 
1567
1666
        *key = new;
1568
1667
 
 
1668
        validate_string_len(name, new, ptr, len);
1569
1669
        return strlen(new);
1570
1670
}
1571
1671
 
 
1672
/*
 
1673
 * Calculate the length of a string replacing all capital letters with %letter.
 
1674
 * For example:
 
1675
 * Sale -> %Sale
 
1676
 * SALE -> %S%A%L%E
 
1677
 */
 
1678
static int get_encoded_len_escaping_every_cap(const char *name)
 
1679
{
 
1680
        const char *tmp;
 
1681
        unsigned int escapes = 0; /* number of % escape characters */
 
1682
 
 
1683
        tmp = name;
 
1684
        while (*tmp) {
 
1685
                /* We'll need to escape percents */
 
1686
                if (*tmp == '%' || isupper(*tmp))
 
1687
                        escapes++;
 
1688
                tmp++;
 
1689
        }
 
1690
 
 
1691
        return strlen(name) + escapes;
 
1692
}
 
1693
 
 
1694
/*
 
1695
 * Calculate the length of a string replacing sequences (1 or more) of capital
 
1696
 * letters with %[letters].  For example:
 
1697
 * FOO ->  %[FOO]
 
1698
 * Work -> %[W]ork
 
1699
 * WorksForMe -> %[W]orks%[F]or%[M]e
 
1700
 * aaBBaa -> aa%[BB]aa
 
1701
 */
 
1702
static int get_encoded_len_escaping_sequences(const char *name)
 
1703
{
 
1704
        const char *tmp;
 
1705
        unsigned int escapes = 0;
 
1706
 
 
1707
        tmp = name;
 
1708
        while (*tmp) {
 
1709
                /* escape percents */
 
1710
                if (*tmp == '%')
 
1711
                        escapes++;
 
1712
                else if (isupper(*tmp)) {
 
1713
                        /* start an escape block %[...] */
 
1714
                        escapes += 3;  /* %[] */
 
1715
                        while (*tmp && isupper(*tmp))
 
1716
                                tmp++;
 
1717
                        continue;
 
1718
                }
 
1719
                tmp++;
 
1720
        }
 
1721
 
 
1722
        return strlen(name) + escapes;
 
1723
}
 
1724
 
 
1725
static void encode_individual(const char *name, char *new, unsigned int len)
 
1726
{
 
1727
        const char *tmp;
 
1728
        char *ptr;
 
1729
 
 
1730
        ptr = new;
 
1731
        tmp = name;
 
1732
        while (*tmp) {
 
1733
                if (*tmp == '%' || isupper(*tmp))
 
1734
                        *ptr++ = '%';
 
1735
                *ptr++ = *tmp++;
 
1736
        }
 
1737
        *ptr = '\0';
 
1738
        validate_string_len(name, new, ptr, len);
 
1739
}
 
1740
 
 
1741
static void encode_sequence(const char *name, char *new, unsigned int len)
 
1742
{
 
1743
        const char *tmp;
 
1744
        char *ptr;
 
1745
 
 
1746
        ptr = new;
 
1747
        tmp = name;
 
1748
        while (*tmp) {
 
1749
                if (*tmp == '%') {
 
1750
                        *ptr++ = '%';
 
1751
                        *ptr++ = *tmp++;
 
1752
                } else if (isupper(*tmp)) {
 
1753
                        *ptr++ = '%';
 
1754
                        *ptr++ = '[';
 
1755
                        *ptr++ = *tmp++;
 
1756
 
 
1757
                        while (*tmp && isupper(*tmp)) {
 
1758
                                *ptr++ = *tmp;
 
1759
                                tmp++;
 
1760
                        }
 
1761
                        *ptr++ = ']';
 
1762
                } else
 
1763
                        *ptr++ = *tmp++;
 
1764
        }
 
1765
        *ptr = '\0';
 
1766
        validate_string_len(name, new, ptr, len);
 
1767
}
 
1768
 
 
1769
/*
 
1770
 * use_class:  1 means encode string as %[CAPITALS], 0 means encode as
 
1771
 * %C%A%P%I%T%A%L%S
 
1772
 */
1572
1773
static int encode_percent_hack(const char *name, char **key, unsigned int use_class)
1573
1774
{
1574
 
        const char *tmp;
1575
1775
        unsigned int len = 0;
1576
 
        char *ptr, *new;
1577
1776
 
1578
1777
        if (!key)
1579
1778
                return -1;
1580
1779
 
1581
 
        *key = NULL;
 
1780
        if (use_class)
 
1781
                len = get_encoded_len_escaping_sequences(name);
 
1782
        else
 
1783
                len = get_encoded_len_escaping_every_cap(name);
1582
1784
 
1583
 
        tmp = name;
1584
 
        while (*tmp) {
1585
 
                if (*tmp == '%')
1586
 
                        len++;
1587
 
                else if (isupper(*tmp)) {
1588
 
                        tmp++;
1589
 
                        len++;
1590
 
                        if (!use_class)
1591
 
                                len++;
1592
 
                        else {
1593
 
                                if (*tmp && isupper(*tmp))
1594
 
                                        len += 2;
1595
 
                                else
1596
 
                                        return 0;
1597
 
                                while (*tmp && isupper(*tmp)) {
1598
 
                                        len++;
1599
 
                                        tmp++;
1600
 
                                }
1601
 
                        }
1602
 
                        continue;
1603
 
                }
1604
 
                len++;
1605
 
                tmp++;
1606
 
        }
 
1785
        /* If there is no escaping to be done, return 0 */
1607
1786
        if (len == strlen(name))
1608
1787
                return 0;
1609
1788
 
1610
 
        new = malloc(len + 1);
1611
 
        if (!new)
 
1789
        *key = malloc(len + 1);
 
1790
        if (!*key)
1612
1791
                return -1;
1613
1792
 
1614
 
        ptr = new;
1615
 
        tmp = name;
1616
 
        while (*tmp) {
1617
 
                if (*tmp == '%')
1618
 
                        *ptr++ = '%';
1619
 
                else if (isupper(*tmp)) {
1620
 
                        char next = *tmp++;
1621
 
                        *ptr++ = '%';
1622
 
                        if (*tmp && (!isupper(*tmp) || !use_class))
1623
 
                                *ptr++ = next;
1624
 
                        else {
1625
 
                                *ptr++ = '[';
1626
 
                                *ptr++ = next;
1627
 
                                while (*tmp && isupper(*tmp))
1628
 
                                        *ptr++ = *tmp++;
1629
 
                                *ptr++ = ']';
1630
 
                        }
1631
 
                        continue;
1632
 
                }
1633
 
                *ptr++ = *tmp++;
1634
 
        }
1635
 
        *ptr = '\0';
1636
 
 
1637
 
        *key = new;
1638
 
 
1639
 
        return strlen(new);
 
1793
        if (use_class)
 
1794
                encode_sequence(name, *key, len);
 
1795
        else
 
1796
                encode_individual(name, *key, len);
 
1797
 
 
1798
        if (strlen(*key) != len)
 
1799
                crit(LOGOPT_ANY, MODPREFIX "encoded key length mismatch: key "
 
1800
                     "%s len %d strlen %d", *key, len, strlen(*key));
 
1801
 
 
1802
        return strlen(*key);
1640
1803
}
1641
1804
 
1642
1805
static int do_paged_query(struct ldap_search_params *sp, struct lookup_context *ctxt)
1644
1807
        struct autofs_point *ap = sp->ap;
1645
1808
        LDAPControl *pageControl=NULL, *controls[2] = { NULL, NULL };
1646
1809
        LDAPControl **returnedControls = NULL;
1647
 
        static unsigned long pageSize = 1000;
 
1810
        static ber_int_t pageSize = 1000;
1648
1811
        static char pagingCriticality = 'T';
1649
1812
        int rv, scope = LDAP_SCOPE_SUBTREE;
1650
1813
 
2579
2742
 
2580
2743
                status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
2581
2744
                free(lkp_key);
2582
 
                if (status) {
2583
 
                        error(ap->logopt,
2584
 
                              MODPREFIX "key \"%s\" not found in map",
2585
 
                              name);
 
2745
                if (status)
2586
2746
                        return status;
2587
 
                }
2588
2747
        }
2589
2748
 
2590
2749
        cache_readlock(mc);
2591
2750
        me = cache_lookup(mc, key);
2592
 
        /* Stale mapent => check for wildcard */
2593
 
        if (me && !me->mapent)
2594
 
                me = cache_lookup_distinct(mc, "*");
 
2751
        /* Stale mapent => check for entry in alternate source or wildcard */
 
2752
        if (me && !me->mapent) {
 
2753
                while ((me = cache_lookup_key_next(me)))
 
2754
                        if (me->source == source)
 
2755
                                break;
 
2756
                if (!me)
 
2757
                        me = cache_lookup_distinct(mc, "*");
 
2758
        }
2595
2759
        if (me && (me->source == source || *me->key == '/')) {
2596
2760
                mapent_len = strlen(me->mapent);
2597
2761
                mapent = alloca(mapent_len + 1);
2621
2785
                        }
2622
2786
                        cache_unlock(mc);
2623
2787
                }
2624
 
        } else
2625
 
                error(ap->logopt,
2626
 
                      MODPREFIX "key \"%s\" not found in map", name);
 
2788
        }
2627
2789
 
2628
2790
        if (ret)
2629
2791
                return NSS_STATUS_TRYAGAIN;
2640
2802
        struct lookup_context *ctxt = (struct lookup_context *) context;
2641
2803
        int rv = close_parse(ctxt->parse);
2642
2804
#ifdef WITH_SASL
2643
 
        autofs_sasl_done(ctxt);
 
2805
        autofs_sasl_dispose(ctxt);
 
2806
        autofs_sasl_done();
2644
2807
#endif
2645
2808
        free_context(ctxt);
2646
2809
        return rv;