~ubuntu-branches/ubuntu/wily/libuser/wily

« back to all changes in this revision

Viewing changes to modules/ldap.c

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Habouzit
  • Date: 2006-09-03 21:58:15 UTC
  • mto: (2.1.1 edgy) (1.1.5 upstream) (3.1.1 lenny)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20060903215815-rtvvfzhaer8ymyp4
Tags: upstream-0.54.6-2.1.dfsg.1
ImportĀ upstreamĀ versionĀ 0.54.6-2.1.dfsg.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
17
 */
18
18
 
19
 
#ident "$Id: ldap.c,v 1.67 2005/09/12 18:21:34 mitr Exp $"
 
19
#ident "$Id: ldap.c,v 1.72 2006/03/11 23:11:12 mitr Exp $"
20
20
 
21
21
#ifdef HAVE_CONFIG_H
22
22
#include "config.h"
53
53
#define DISTINGUISHED_NAME "dn"
54
54
 
55
55
LU_MODULE_INIT(libuser_ldap_init)
56
 
#define LU_LDAP_USER    (1 << 0)
57
 
#define LU_LDAP_GROUP   (1 << 1)
58
 
#define LU_LDAP_SHADOW  (1 << 2)
59
56
 
60
57
enum lock_op { LO_LOCK, LO_UNLOCK, LO_UNLOCK_NONEMPTY };
61
58
 
73
70
        const char *lu_attribute;
74
71
        const char *ldap_attribute;
75
72
        const char *objectclass;
76
 
        int applicability;
 
73
        enum lu_entity_type type;
77
74
} ldap_attribute_map[] = {
78
 
        {LU_USERNAME, "uid", POSIXACCOUNT, LU_LDAP_USER},
79
 
        {LU_USERPASSWORD, "userPassword", POSIXACCOUNT, LU_LDAP_USER},
80
 
        {LU_UIDNUMBER, "uidNumber", POSIXACCOUNT, LU_LDAP_USER},
81
 
        {LU_GIDNUMBER, "gidNumber", POSIXACCOUNT, LU_LDAP_USER},
82
 
        {LU_GECOS, "gecos", POSIXACCOUNT, LU_LDAP_USER},
83
 
        {LU_HOMEDIRECTORY, "homeDirectory", POSIXACCOUNT, LU_LDAP_USER},
84
 
        {LU_LOGINSHELL, "loginShell", POSIXACCOUNT, LU_LDAP_USER},
85
 
        {LU_COMMONNAME, "cn", POSIXACCOUNT, LU_LDAP_USER},
86
 
 
87
 
        {LU_GROUPNAME, "cn", POSIXGROUP, LU_LDAP_GROUP},
88
 
        {LU_GROUPPASSWORD, "userPassword", POSIXGROUP, LU_LDAP_GROUP},
89
 
        {LU_GIDNUMBER, "gidNumber", POSIXGROUP, LU_LDAP_GROUP},
90
 
        {LU_MEMBERNAME, "memberUid", POSIXGROUP, LU_LDAP_GROUP},
91
 
 
92
 
        {LU_SHADOWLASTCHANGE, "shadowLastChange", SHADOWACCOUNT,
93
 
         LU_LDAP_SHADOW},
94
 
        {LU_SHADOWMIN, "shadowMin", SHADOWACCOUNT, LU_LDAP_SHADOW},
95
 
        {LU_SHADOWMAX, "shadowMax", SHADOWACCOUNT, LU_LDAP_SHADOW},
96
 
        {LU_SHADOWWARNING, "shadowWarning", SHADOWACCOUNT, LU_LDAP_SHADOW},
97
 
        {LU_SHADOWINACTIVE, "shadowInactive", SHADOWACCOUNT, LU_LDAP_SHADOW},
98
 
        {LU_SHADOWEXPIRE, "shadowExpire", SHADOWACCOUNT, LU_LDAP_SHADOW},
99
 
        {LU_SHADOWFLAG, "shadowFlag", SHADOWACCOUNT, LU_LDAP_SHADOW},
100
 
 
101
 
        {LU_GIVENNAME, "givenName", INETORGPERSON, LU_LDAP_USER},
102
 
        {LU_SN, "sn", INETORGPERSON, LU_LDAP_USER},
103
 
        {LU_ROOMNUMBER, "roomNumber", INETORGPERSON, LU_LDAP_USER},
104
 
        {LU_TELEPHONENUMBER, "telephoneNumber", INETORGPERSON, LU_LDAP_USER},
105
 
        {LU_HOMEPHONE, "homePhone", INETORGPERSON, LU_LDAP_USER},
 
75
        {LU_USERNAME, "uid", POSIXACCOUNT, lu_user},
 
76
        {LU_USERPASSWORD, "userPassword", POSIXACCOUNT, lu_user},
 
77
        {LU_UIDNUMBER, "uidNumber", POSIXACCOUNT, lu_user},
 
78
        {LU_GIDNUMBER, "gidNumber", POSIXACCOUNT, lu_user},
 
79
        {LU_GECOS, "gecos", POSIXACCOUNT, lu_user},
 
80
        {LU_HOMEDIRECTORY, "homeDirectory", POSIXACCOUNT, lu_user},
 
81
        {LU_LOGINSHELL, "loginShell", POSIXACCOUNT, lu_user},
 
82
        {LU_COMMONNAME, "cn", POSIXACCOUNT, lu_user},
 
83
 
 
84
        {LU_GROUPNAME, "cn", POSIXGROUP, lu_group},
 
85
        {LU_GROUPPASSWORD, "userPassword", POSIXGROUP, lu_group},
 
86
        {LU_GIDNUMBER, "gidNumber", POSIXGROUP, lu_group},
 
87
        {LU_MEMBERNAME, "memberUid", POSIXGROUP, lu_group},
 
88
 
 
89
        {LU_SHADOWLASTCHANGE, "shadowLastChange", SHADOWACCOUNT, lu_user},
 
90
        {LU_SHADOWMIN, "shadowMin", SHADOWACCOUNT, lu_user},
 
91
        {LU_SHADOWMAX, "shadowMax", SHADOWACCOUNT, lu_user},
 
92
        {LU_SHADOWWARNING, "shadowWarning", SHADOWACCOUNT, lu_user},
 
93
        {LU_SHADOWINACTIVE, "shadowInactive", SHADOWACCOUNT, lu_user},
 
94
        {LU_SHADOWEXPIRE, "shadowExpire", SHADOWACCOUNT, lu_user},
 
95
        {LU_SHADOWFLAG, "shadowFlag", SHADOWACCOUNT, lu_user},
 
96
 
 
97
        {LU_GIVENNAME, "givenName", INETORGPERSON, lu_user},
 
98
        {LU_SN, "sn", INETORGPERSON, lu_user},
 
99
        {LU_ROOMNUMBER, "roomNumber", INETORGPERSON, lu_user},
 
100
        {LU_TELEPHONENUMBER, "telephoneNumber", INETORGPERSON, lu_user},
 
101
        {LU_HOMEPHONE, "homePhone", INETORGPERSON, lu_user},
106
102
};
107
103
 
108
104
static const char *const lu_ldap_user_attributes[] = {
150
146
        struct lu_module *module;               /* The module's structure. */
151
147
        struct lu_prompt prompts[LU_LDAP_MAX];  /* Questions and answers. */
152
148
        gboolean bind_simple, bind_sasl;        /* What kind of bind to use. */
 
149
        const char *user_branch, *group_branch; /* Cached config values */
153
150
        char **mapped_user_attributes, **mapped_group_attributes;
154
151
        LDAP *ldap;                             /* The connection. */
155
152
};
157
154
static void
158
155
close_server(LDAP *ldap)
159
156
{
160
 
        ldap_unbind_s(ldap);
 
157
        ldap_unbind_ext(ldap, NULL, NULL);
161
158
}
162
159
 
163
160
/* Get the name of the user running the calling application. */
182
179
connect_server(struct lu_ldap_context *context, struct lu_error **error)
183
180
{
184
181
        LDAP *ldap = NULL;
185
 
        LDAPControl *server = NULL, *client = NULL;
186
182
        int version, ret, start_tls;
187
183
 
188
184
        g_assert(context != NULL);
193
189
        if (ret == LDAP_SUCCESS)
194
190
                start_tls = FALSE;
195
191
        else {
196
 
                ldap = ldap_open(context->prompts[LU_LDAP_SERVER].value,
197
 
                                 LDAP_PORT);
 
192
                if (ldap_create(&ldap) != LDAP_SUCCESS)
 
193
                        ldap = NULL;
 
194
                else if (ldap_set_option(ldap, LDAP_OPT_HOST_NAME,
 
195
                                         context->prompts[LU_LDAP_SERVER]
 
196
                                         .value) != LDAP_SUCCESS) {
 
197
                        close_server(ldap);
 
198
                        ldap = NULL;
 
199
                }
198
200
                start_tls = TRUE;
199
201
        }
200
202
        if (ldap == NULL) {
217
219
        }
218
220
 
219
221
        /* Try to start TLS. */
220
 
        ret = ldap_start_tls_s(ldap, &server, &client);
 
222
        ret = ldap_start_tls_s(ldap, NULL, NULL);
221
223
        /* Note that TLS is not required for ldap:// URLs (unlike simple server
222
224
           names). */
223
225
        if (ret != LDAP_SUCCESS && start_tls) {
240
242
 
241
243
        (void)ld;
242
244
        (void)flags;
243
 
        for(i = 0, retval = LDAP_SUCCESS, interact_data = xinteract_data;
244
 
            interact_data && (interact_data[i].id != SASL_CB_LIST_END);
 
245
        interact_data = xinteract_data;
 
246
        for(i = 0; interact_data && (interact_data[i].id != SASL_CB_LIST_END);
245
247
            i++) {
246
248
                interact_data[i].result = NULL;
247
249
                interact_data[i].len = 0;
271
273
static LDAP *
272
274
bind_server(struct lu_ldap_context *context, struct lu_error **error)
273
275
{
274
 
        LDAP *ldap = NULL;
275
 
        LDAPControl *server = NULL, *client = NULL;
 
276
        LDAP *ldap;
276
277
        int ret, first_failure;
277
 
        const char *generated_binddn = "", *first_binddn;
278
 
        char *binddn, *tmp, *key;
 
278
        const char *generated_binddn, *first_binddn;
 
279
        char *binddn, *tmp;
279
280
        char *user;
280
281
        char *password;
281
282
        struct lu_string_cache *scache = NULL;
300
301
        if (nonempty(context->prompts[LU_LDAP_AUTHUSER].value)) {
301
302
                user = context->prompts[LU_LDAP_AUTHUSER].value;
302
303
        }
303
 
        key = g_strdup_printf("%s/%s", context->module->name, "userBranch");
304
 
        tmp = g_strdup_printf("uid=%s,%s,%s", user,
305
 
                              lu_cfg_read_single(context->global_context,
306
 
                                                 key,
307
 
                                                 USERBRANCH),
 
304
        tmp = g_strdup_printf("uid=%s,%s,%s", user, context->user_branch,
308
305
                              context->prompts[LU_LDAP_BASEDN].value);
309
306
        generated_binddn = scache->cache(scache, tmp);
310
 
        g_free(key);
311
307
        g_free(tmp);
312
308
 
313
309
        /* Try to bind to the server using SASL. */
340
336
                        g_print("Attempting SASL bind to `%s'.\n", binddn);
341
337
#endif
342
338
                        ret = ldap_sasl_interactive_bind_s(ldap, binddn, NULL,
343
 
                                                           &server, &client,
 
339
                                                           NULL, NULL,
344
340
                                                           LDAP_SASL_INTERACTIVE |
345
341
                                                           LDAP_SASL_QUIET,
346
342
                                                           interact,
357
353
#endif
358
354
                        ret = ldap_sasl_interactive_bind_s(ldap,
359
355
                                                           generated_binddn,
360
 
                                                           NULL, &server,
361
 
                                                           &client,
 
356
                                                           NULL, NULL, NULL,
362
357
                                                           LDAP_SASL_INTERACTIVE |
363
358
                                                           LDAP_SASL_QUIET,
364
359
                                                           interact, context);
372
367
        if (ret != LDAP_SUCCESS && context->bind_simple) {
373
368
                /* try to bind using a password, and if that fails... */
374
369
                if ((password != NULL) && (strlen(password) > 0)) {
 
370
                        BerValue cred;
 
371
 
 
372
                        cred.bv_val = password;
 
373
                        cred.bv_len = strlen(password);
375
374
                        if (binddn != NULL) {
376
375
#ifdef DEBUG
377
376
                                g_print("Attempting simple bind to `%s'.\n",
378
377
                                        binddn);
379
378
#endif
380
 
                                ret = ldap_simple_bind_s(ldap, binddn,
381
 
                                                         password);
 
379
                                ret = ldap_sasl_bind_s(ldap, binddn,
 
380
                                                       LDAP_SASL_SIMPLE, &cred,
 
381
                                                       NULL, NULL, NULL);
382
382
                                if (ret != LDAP_SUCCESS
383
383
                                    && first_failure == LDAP_SUCCESS) {
384
384
                                        first_failure = ret;
390
390
                                g_print("Attempting simple bind to `%s'.\n",
391
391
                                        generated_binddn);
392
392
#endif
393
 
                                ret = ldap_simple_bind_s(ldap,
394
 
                                                         generated_binddn,
395
 
                                                         password);
 
393
                                ret = ldap_sasl_bind_s(ldap, generated_binddn,
 
394
                                                       LDAP_SASL_SIMPLE, &cred,
 
395
                                                       NULL, NULL, NULL);
396
396
                                if (ret != LDAP_SUCCESS
397
397
                                    && first_failure == LDAP_SUCCESS) {
398
398
                                        first_failure = ret;
415
415
                return NULL;
416
416
        }
417
417
        return ldap;
418
 
#if 0
419
 
        /* Check if there are any supported SASL mechanisms. */
420
 
        if (ldap_search_ext_s(ldap, LDAP_ROOT_DSE, LDAP_SCOPE_BASE,
421
 
                              NULL, saslmechs, FALSE,
422
 
                              &server, &client,
423
 
                              NULL, 0, &results) != LDAP_SUCCESS) {
424
 
                lu_error_new(error, lu_error_init,
425
 
                             _("could not search LDAP server"));
426
 
                close_server(ldap);
427
 
                return NULL;
428
 
        }
429
 
 
430
 
        /* Get the DSE entry. */
431
 
        entry = ldap_first_entry(ldap, results);
432
 
        if (entry == NULL) {
433
 
                lu_error_new(error, lu_error_init,
434
 
                             _("LDAP server appears to have no root DSE"));
435
 
                close_server(ldap);
436
 
                return NULL;
437
 
        }
438
 
 
439
 
        /* Get the list of supported mechanisms. */
440
 
        values = ldap_get_values(ldap, entry, saslmechs[0]);
441
 
        if ((values != NULL) && (strlen(values[0]) > 0)) {
442
 
                sasl = TRUE;
443
 
        }
444
 
 
445
 
        if (ldap_sasl_interactive_bind_s(ldap, NULL, NULL, NULL, NULL,
446
 
                                         LDAP_SASL_AUTOMATIC |
447
 
                                         LDAP_SASL_QUIET, interact,
448
 
                                         context) != LDAP_SUCCESS)
449
 
                if (ldap_simple_bind_s
450
 
                    (ldap, context->prompts[LU_LDAP_BINDDN].value,
451
 
                     context->prompts[LU_LDAP_PASSWORD].value) !=
452
 
                    LDAP_SUCCESS)
453
 
                        if (ldap_simple_bind_s
454
 
                            (ldap, generated_binddn,
455
 
                             context->prompts[LU_LDAP_PASSWORD].value) !=
456
 
                            LDAP_SUCCESS) {
457
 
                        }
458
 
 
459
 
        return ldap;
460
 
#endif
461
418
}
462
419
 
463
420
/* Map an attribute name from an internal name to an LDAP atribute name. */
480
437
/* Generate the distinguished name which corresponds to the container where
481
438
 * the lu_ent structure's entry would be found. */
482
439
static const char *
483
 
lu_ldap_base(struct lu_module *module, const char *configKey,
484
 
             const char *def)
 
440
lu_ldap_base(struct lu_module *module, const char *branch)
485
441
{
486
 
        struct lu_ldap_context *context = module->module_context;
487
 
        const char *branch = NULL;
488
 
        char *tmp = NULL, *ret = NULL;
 
442
        struct lu_ldap_context *context;
 
443
        char *tmp, *ret;
489
444
 
490
445
        g_assert(module != NULL);
491
 
        g_assert(configKey != NULL);
492
 
        g_assert(strlen(configKey) > 0);
493
 
 
494
 
        /* Read the branch of the tree we want to look in. */
495
 
        tmp = g_strdup_printf("%s/%s", module->name, configKey);
496
 
        branch = lu_cfg_read_single(module->lu_context, tmp, def);
497
 
        g_free(tmp);
 
446
        context = module->module_context;
498
447
 
499
448
        /* Generate the branch DN. */
500
 
        if (branch) {
 
449
        if (strlen(branch) != 0)
501
450
                tmp = g_strdup_printf("%s,%s", branch,
502
 
                                      context->prompts[LU_LDAP_BASEDN].
503
 
                                      value);
504
 
        } else {
 
451
                                      context->prompts[LU_LDAP_BASEDN].value);
 
452
        else
505
453
                tmp = g_strdup(context->prompts[LU_LDAP_BASEDN].value);
506
 
        }
507
454
 
508
455
        ret = module->scache->cache(module->scache, tmp);
509
456
 
515
462
/* Discover the distinguished name which corresponds to an account. */
516
463
static const char *
517
464
lu_ldap_ent_to_dn(struct lu_module *module, const char *namingAttr,
518
 
                  const char *name, const char *configKey, const char *def)
 
465
                  const char *name, const char *branch)
519
466
{
520
 
        const char *branch = NULL;
521
 
        char *tmp = NULL, *ret = NULL, *filter;
522
 
        char *noattrs[] = {NULL};
523
 
        const char *base = NULL;
524
 
        struct lu_ldap_context *ctx = NULL;
525
 
        LDAPMessage *messages = NULL, *entry = NULL;
 
467
        static char *noattrs[] = { NULL };
 
468
 
 
469
        const char *base, *mapped_naming_attr;
 
470
        char *tmp, *ret = NULL, *filter;
 
471
        struct lu_ldap_context *ctx;
 
472
        LDAPMessage *messages = NULL;
526
473
 
527
474
        g_assert(module != NULL);
528
475
        g_assert(namingAttr != NULL);
529
476
        g_assert(strlen(namingAttr) > 0);
530
477
        g_assert(name != NULL);
531
478
        g_assert(strlen(name) > 0);
532
 
        g_assert(configKey != NULL);
533
 
        g_assert(strlen(configKey) > 0);
534
479
 
535
480
        /* Search for the right object using the entity's current name. */
536
 
        branch = lu_ldap_base(module, configKey, def);
 
481
        base = lu_ldap_base(module, branch);
537
482
        ctx = module->module_context;
538
 
        base = ctx->prompts[LU_LDAP_BASEDN].value;
539
 
 
540
 
        filter = g_strdup_printf("(%s=%s)",
541
 
                                 map_to_ldap(module->scache, namingAttr),
542
 
                                 name);
543
 
        if (ldap_search_s(ctx->ldap, branch, LDAP_SCOPE_SUBTREE, filter,
544
 
                          noattrs, FALSE, &messages) == LDAP_SUCCESS) {
 
483
 
 
484
        mapped_naming_attr = map_to_ldap(module->scache, namingAttr);
 
485
        filter = g_strdup_printf("(%s=%s)", mapped_naming_attr, name);
 
486
        if (ldap_search_ext_s(ctx->ldap, base, LDAP_SCOPE_SUBTREE, filter,
 
487
                              noattrs, FALSE, NULL, NULL, NULL, LDAP_NO_LIMIT,
 
488
                              &messages) == LDAP_SUCCESS) {
 
489
                LDAPMessage *entry;
 
490
 
545
491
                entry = ldap_first_entry(ctx->ldap, messages);
546
492
                if (entry != NULL) {
547
493
                        tmp = ldap_get_dn(ctx->ldap, entry);
548
494
                        ret = module->scache->cache(module->scache, tmp);
549
495
                        if (tmp)
550
 
                          ldap_memfree(tmp);
 
496
                                ldap_memfree(tmp);
551
497
                }
552
498
                ldap_msgfree(messages);
553
499
        }
555
501
 
556
502
        if (ret == NULL) {
557
503
                /* Guess at the DN using the branch and the base. */
558
 
                if (branch) {
559
 
                        tmp = g_strdup_printf("%s=%s,%s",
560
 
                                              map_to_ldap(module->scache,
561
 
                                                          namingAttr),
562
 
                                              name, branch);
563
 
                        ret = module->scache->cache(module->scache, tmp);
564
 
                        g_free(tmp);
565
 
                }
 
504
                tmp = g_strdup_printf("%s=%s,%s", mapped_naming_attr, name,
 
505
                                      base);
 
506
                ret = module->scache->cache(module->scache, tmp);
 
507
                g_free(tmp);
566
508
        }
567
509
 
568
510
        return ret;
572
514
static gboolean
573
515
lu_ldap_lookup(struct lu_module *module,
574
516
               const char *namingAttr, const char *name,
575
 
               struct lu_ent *ent, GPtrArray *ent_array,
576
 
               const char *configKey, const char *def,
 
517
               struct lu_ent *ent, GPtrArray *ent_array, const char *branch,
577
518
               const char *filter, const char *const *attributes,
578
 
               int applicability, struct lu_error **error)
 
519
               enum lu_entity_type type, struct lu_error **error)
579
520
{
580
521
        LDAPMessage *messages = NULL, *entry = NULL;
581
 
        GValueArray *array;
582
 
        GValue value, *val;
583
 
        const char *attr;
584
 
        char *filt = NULL, **values = NULL, *p, **mapped_attributes;
 
522
        char *filt, **mapped_attributes;
585
523
        const char *dn = NULL;
586
 
        const char *base = NULL;
587
 
        size_t i, j;
 
524
        const char *base;
588
525
        gboolean ret = FALSE;
589
526
        struct lu_ldap_context *ctx;
590
527
 
596
533
        if (ent != NULL) {
597
534
                g_assert(ent->magic == LU_ENT_MAGIC);
598
535
        }
599
 
        g_assert(configKey != NULL);
600
 
        g_assert(strlen(configKey) > 0);
601
536
        g_assert(attributes != NULL);
602
537
        g_assert(attributes[0] != NULL);
603
538
        LU_ERROR_CHECK(error);
605
540
        ctx = module->module_context;
606
541
 
607
542
        if (ent != NULL) {
 
543
                GValueArray *array;
608
544
                /* Try to use the dn the object already knows about. */
609
 
                dn = NULL;
610
 
 
611
 
                if (dn == NULL) {
612
 
                        array = lu_ent_get(ent, DISTINGUISHED_NAME);
613
 
                        if (array != NULL) {
614
 
                                val = g_value_array_get_nth(array, 0);
615
 
                                if (G_VALUE_HOLDS_STRING(val))
616
 
                                        dn = g_value_get_string(val);
617
 
                        }
 
545
 
 
546
                array = lu_ent_get(ent, DISTINGUISHED_NAME);
 
547
                if (array != NULL) {
 
548
                        GValue *val;
 
549
 
 
550
                        val = g_value_array_get_nth(array, 0);
 
551
                        if (G_VALUE_HOLDS_STRING(val))
 
552
                                dn = g_value_get_string(val);
618
553
                }
619
554
 
620
555
                if (dn == NULL)
621
556
                        /* Map the user or group name to an LDAP object name. */
622
557
                        dn = lu_ldap_ent_to_dn(module, namingAttr, name,
623
 
                                               configKey, def);
624
 
 
625
 
                if (dn == NULL) {
626
 
                        lu_error_new(error, lu_error_generic,
627
 
                                     _("error mapping name to LDAP distinguished name"));
628
 
                        return FALSE;
629
 
                }
 
558
                                               branch);
630
559
        }
631
560
 
632
561
        /* Get the entry in the directory under which we'll search for this
633
562
         * entity. */
634
 
        base = lu_ldap_base(module, configKey, def);
635
 
        if (base == NULL) {
636
 
                lu_error_new(error, lu_error_generic,
637
 
                             _("error mapping name to LDAP base distinguished name"));
638
 
                return FALSE;
639
 
        }
 
563
        base = lu_ldap_base(module, branch);
640
564
 
641
565
        /* Generate an LDAP filter, optionally including a filter supplied
642
566
         * by the caller. */
663
587
        if (ent != NULL) {
664
588
                /* Perform the search and read the first (hopefully only)
665
589
                 * entry. */
666
 
                if (ldap_search_s(ctx->ldap, dn, LDAP_SCOPE_BASE, filt,
667
 
                                  mapped_attributes, FALSE,
668
 
                                  &messages) == LDAP_SUCCESS) {
 
590
                if (ldap_search_ext_s(ctx->ldap, dn, LDAP_SCOPE_BASE, filt,
 
591
                                      mapped_attributes, FALSE, NULL, NULL,
 
592
                                      NULL, LDAP_NO_LIMIT, &messages)
 
593
                    == LDAP_SUCCESS) {
669
594
                        entry = ldap_first_entry(ctx->ldap, messages);
670
595
                }
671
596
        }
681
606
                        ldap_msgfree(messages);
682
607
                        messages = NULL;
683
608
                }
684
 
                if (ldap_search_s(ctx->ldap, base, LDAP_SCOPE_SUBTREE, filt,
685
 
                                  mapped_attributes, FALSE, &messages) == LDAP_SUCCESS) {
 
609
                if (ldap_search_ext_s(ctx->ldap, base, LDAP_SCOPE_SUBTREE,
 
610
                                      filt, mapped_attributes, FALSE, NULL,
 
611
                                      NULL, NULL, LDAP_NO_LIMIT, &messages)
 
612
                    == LDAP_SUCCESS) {
686
613
                        entry = ldap_first_entry(ctx->ldap, messages);
687
614
                }
688
615
        }
692
619
 
693
620
        /* If we got an entry, read its contents into an entity structure. */
694
621
        while (entry != NULL) {
 
622
                GValue value;
 
623
                size_t i;
 
624
                char *p;
 
625
 
695
626
                /* Mark that the search succeeded. */
696
627
                ret = TRUE;
697
628
                /* If we need to add the data to the array, then create a new
698
629
                 * data item to hold the data. */
699
 
                if (ent_array != NULL) {
700
 
                        if (applicability & LU_LDAP_USER) {
701
 
                                ent = lu_ent_new_typed(lu_user);
702
 
                        } else
703
 
                        if (applicability & LU_LDAP_GROUP) {
704
 
                                ent = lu_ent_new_typed(lu_group);
705
 
                        } else {
706
 
                                g_assert_not_reached();
707
 
                        }
708
 
                }
 
630
                if (ent_array != NULL)
 
631
                        ent = lu_ent_new_typed(type);
709
632
                /* Set the distinguished name. */
710
633
                memset(&value, 0, sizeof(value));
711
634
                g_value_init(&value, G_TYPE_STRING);
718
641
 
719
642
                /* Read each of the attributes we asked for. */
720
643
                for (i = 0; attributes[i]; i++) {
 
644
                        BerValue **values;
 
645
                        const char *attr;
 
646
 
721
647
                        /* Get the values which correspond to this attribute. */
722
648
                        attr = attributes[i];
723
 
                        values = ldap_get_values(ctx->ldap, entry,
724
 
                                                 mapped_attributes[i]);
 
649
                        values = ldap_get_values_len(ctx->ldap, entry,
 
650
                                                     mapped_attributes[i]);
725
651
                        /* If we got answers, add them. */
726
652
                        if (values) {
 
653
                                size_t j;
 
654
 
727
655
                                lu_ent_clear_current(ent, attr);
728
656
                                for (j = 0; values[j]; j++) {
 
657
                                        char *val;
729
658
                                        intmax_t imax;
730
659
 
 
660
                                        val = g_strndup(values[j]->bv_val,
 
661
                                                        values[j]->bv_len);
731
662
#ifdef DEBUG
732
 
                                        g_print("Got `%s' = `%s'.\n",
733
 
                                                attr, values[j]);
 
663
                                        g_print("Got `%s' = `%s'.\n", attr,
 
664
                                                val);
734
665
#endif
735
666
                                        /* Check if the value is numeric. */
736
667
                                        errno = 0;
737
 
                                        imax = strtoimax(values[j], &p, 10);
 
668
                                        imax = strtoimax(val, &p, 10);
738
669
                                        if (errno == 0 && *p == '\0'
739
 
                                            && p != values[j]
 
670
                                            && p != val
740
671
                                            && (long)imax == imax) {
741
672
                                                /* If it's a number, use a
742
673
                                                 * long. */
743
674
                                                g_value_init(&value, G_TYPE_LONG);
744
675
                                                g_value_set_long(&value, imax);
745
676
                                        } else if (errno == 0 && *p == '\0'
746
 
                                                   && p != values[j]
 
677
                                                   && p != val
747
678
                                                   && (id_t)imax == imax)
748
679
                                                lu_value_init_set_id(&value,
749
680
                                                                     imax);
750
681
                                        else {
751
682
                                                /* Otherwise it's a string. */
752
683
                                                g_value_init(&value, G_TYPE_STRING);
753
 
                                                g_value_set_string(&value, values[j]);
 
684
                                                g_value_set_string(&value, val);
754
685
                                        }
755
686
                                        /* Add this value, and then clear the
756
687
                                         * value structure. */
757
688
                                        lu_ent_add_current(ent, attr, &value);
758
689
                                        g_value_unset(&value);
 
690
                                        g_free(val);
759
691
                                }
760
 
                                ldap_value_free(values);
 
692
                                ldap_value_free_len(values);
761
693
                        }
762
694
                }
763
695
                /* Stash the data in the array if we need to. */
784
716
lu_ldap_user_lookup_name(struct lu_module *module, const char *name,
785
717
                         struct lu_ent *ent, struct lu_error **error)
786
718
{
 
719
        struct lu_ldap_context *ctx;
 
720
 
787
721
        LU_ERROR_CHECK(error);
788
 
        return lu_ldap_lookup(module, map_to_ldap(ent->cache, LU_USERNAME),
789
 
                              name, ent, NULL, "userBranch", USERBRANCH,
 
722
        ctx = module->module_context;
 
723
        return lu_ldap_lookup(module, "uid", name, ent, NULL, ctx->user_branch,
790
724
                              "("OBJECTCLASS"="POSIXACCOUNT")",
791
 
                              lu_ldap_user_attributes,
792
 
                              LU_LDAP_USER | LU_LDAP_SHADOW, error);
 
725
                              lu_ldap_user_attributes, lu_user, error);
793
726
}
794
727
 
795
728
/* Look up a user by ID. */
797
730
lu_ldap_user_lookup_id(struct lu_module *module, uid_t uid,
798
731
                       struct lu_ent *ent, struct lu_error **error)
799
732
{
800
 
        gboolean ret = FALSE;
801
 
 
802
 
        gchar *uid_string = NULL;
 
733
        struct lu_ldap_context *ctx;
 
734
        gboolean ret;
 
735
        gchar *uid_string;
803
736
 
804
737
        LU_ERROR_CHECK(error);
 
738
        ctx = module->module_context;
805
739
        uid_string = g_strdup_printf("%jd", (intmax_t)uid);
806
 
        ret = lu_ldap_lookup(module, map_to_ldap(ent->cache, LU_UIDNUMBER),
807
 
                             uid_string, ent, NULL, "userBranch", USERBRANCH,
 
740
        ret = lu_ldap_lookup(module, "uidNumber",
 
741
                             uid_string, ent, NULL, ctx->user_branch,
808
742
                             "("OBJECTCLASS"="POSIXACCOUNT")",
809
 
                             lu_ldap_user_attributes,
810
 
                             LU_LDAP_USER | LU_LDAP_SHADOW, error);
 
743
                             lu_ldap_user_attributes, lu_user, error);
811
744
        g_free(uid_string);
812
745
 
813
746
        return ret;
818
751
lu_ldap_group_lookup_name(struct lu_module *module, const char *name,
819
752
                          struct lu_ent *ent, struct lu_error **error)
820
753
{
 
754
        struct lu_ldap_context *ctx;
 
755
 
821
756
        LU_ERROR_CHECK(error);
822
 
        return lu_ldap_lookup(module, map_to_ldap(ent->cache, LU_GROUPNAME),
823
 
                              name, ent, NULL,
824
 
                              "groupBranch", GROUPBRANCH,
 
757
        ctx = module->module_context;
 
758
        return lu_ldap_lookup(module, "cn", name, ent, NULL, ctx->group_branch,
825
759
                              "("OBJECTCLASS"="POSIXGROUP")",
826
 
                              lu_ldap_group_attributes, LU_LDAP_GROUP, error);
 
760
                              lu_ldap_group_attributes, lu_group, error);
827
761
}
828
762
 
829
763
/* Look up a group by ID. */
831
765
lu_ldap_group_lookup_id(struct lu_module *module, gid_t gid,
832
766
                        struct lu_ent *ent, struct lu_error **error)
833
767
{
834
 
        gboolean ret = FALSE;
835
 
        gchar *gid_string = NULL;
 
768
        struct lu_ldap_context *ctx;
 
769
        gboolean ret;
 
770
        gchar *gid_string;
836
771
 
837
772
        LU_ERROR_CHECK(error);
838
 
 
 
773
        ctx = module->module_context;
839
774
        gid_string = g_strdup_printf("%jd", (intmax_t)gid);
840
 
        ret = lu_ldap_lookup(module, map_to_ldap(ent->cache, LU_GIDNUMBER),
841
 
                             gid_string, ent, NULL,
842
 
                             "groupBranch", GROUPBRANCH,
843
 
                             "("OBJECTCLASS"="POSIXGROUP")",
844
 
                             lu_ldap_group_attributes, LU_LDAP_GROUP, error);
 
775
        ret = lu_ldap_lookup(module, "gidNumber", gid_string, ent, NULL,
 
776
                             ctx->group_branch, "("OBJECTCLASS"="POSIXGROUP")",
 
777
                             lu_ldap_group_attributes, lu_group, error);
845
778
        g_free(gid_string);
846
779
 
847
780
        return ret;
889
822
 
890
823
/* Check whether class is among old_values or new_values */
891
824
static int
892
 
objectclass_present(const char *dn, const char *class, char *const *old_values,
893
 
                    size_t old_count, char *const *new_values,
894
 
                    size_t new_count)
 
825
objectclass_present(const char *dn, const char *class,
 
826
                    BerValue *const *old_values, size_t old_count,
 
827
                    BerValue *const *new_values, size_t new_count)
895
828
{
896
 
        size_t i;
897
 
        
 
829
        size_t i, len;
 
830
 
 
831
        (void)dn;
 
832
        len = strlen(class);
898
833
        for (i = 0; i < old_count; i++) {
899
 
                if (strcmp(class, old_values[i]) == 0) {
 
834
                const BerValue *val;
 
835
 
 
836
                val = old_values[i];
 
837
                if (val->bv_len == len
 
838
                    && memcmp(class, val->bv_val, len) == 0) {
900
839
#ifdef DEBUG
901
 
                        g_print("Entity `%s' is already a `%s'.\n", dn,
902
 
                                old_values[i]);
 
840
                        g_print("Entity `%s' is already a `%.*s'.\n", dn,
 
841
                                (int)val->bv_len, val->bv_val);
903
842
#endif
904
843
                        return 1;
905
844
                }
906
845
        }
907
846
        for (i = 0; i < new_count; i++) {
908
 
                if (strcmp(class, new_values[i]) == 0) {
 
847
                const BerValue *val;
 
848
 
 
849
                val = new_values[i];
 
850
                if (val->bv_len == len
 
851
                    && memcmp(class, val->bv_val, len) == 0) {
909
852
#ifdef DEBUG
910
853
                        g_print("Entity `%s' was already determined to be a "
911
 
                                "`%s'.\n", dn, new_values[i]);
 
854
                                "`%.*s'.\n", dn, (int)val->bv_len,
 
855
                                val->bv_val);
912
856
#endif
913
857
                        return 1;
914
858
                }
920
864
 * assuming old_values (may be NULL).
921
865
 *
922
866
 * Returns NULL if no new object classes are needed. */
923
 
static char **
 
867
static BerValue **
924
868
lu_ldap_needed_objectclasses(const char *dn, struct lu_ent *ent,
925
 
                             char **old_values)
 
869
                             BerValue **old_values)
926
870
{
927
 
        char **new_values;
 
871
        BerValue **new_values;
928
872
        size_t old_count, new_count;
929
873
        GList *attributes, *a;
930
 
        int applicability;
931
874
 
932
875
        if (old_values)
933
 
                old_count = ldap_count_values(old_values);
 
876
                old_count = ldap_count_values_len(old_values);
934
877
        else
935
878
                old_count = 0;
936
879
 
937
 
        if (ent->type == lu_user)
938
 
                applicability = LU_LDAP_USER | LU_LDAP_SHADOW;
939
 
        else
940
 
                applicability = LU_LDAP_GROUP;
941
 
 
942
880
        new_values = g_malloc(sizeof(*new_values) *
943
881
                              (G_N_ELEMENTS(ldap_attribute_map) + 1 + 1));
944
882
        new_count = 0;
948
886
        for (a = attributes; a != NULL; a = a->next) {
949
887
                size_t i;
950
888
                const char *attr;
 
889
                BerValue *bv;
951
890
 
952
891
                attr = a->data;
953
892
#ifdef DEBUG
956
895
                /* Get the name of the next object class the object needs
957
896
                 * to be a member of. */
958
897
                for (i = 0; i < G_N_ELEMENTS(ldap_attribute_map); i++) {
959
 
                        if ((ldap_attribute_map[i].applicability
960
 
                             & applicability) != 0
 
898
                        if (ldap_attribute_map[i].type == ent->type
961
899
                            && strcasecmp(ldap_attribute_map[i].lu_attribute,
962
900
                                          attr) == 0) {
963
901
#ifdef DEBUG
979
917
                        continue;
980
918
 
981
919
                /* Add it to the class. */
982
 
                new_values[new_count]
983
 
                        = (char *)ldap_attribute_map[i].objectclass;
 
920
                bv = g_malloc(sizeof (*bv));
 
921
                bv->bv_val = (char *)ldap_attribute_map[i].objectclass;
 
922
                bv->bv_len = strlen(bv->bv_val);
 
923
                new_values[new_count] = bv;
984
924
#ifdef DEBUG
985
925
                g_print("Adding entity `%s' to class `%s'.\n", dn,
986
926
                        new_values[new_count]);
996
936
            && !objectclass_present(dn, INETORGPERSON, old_values, old_count,
997
937
                                    new_values, new_count)
998
938
            && !objectclass_present(dn, ACCOUNT, old_values, old_count,
999
 
                                    new_values, new_count))
1000
 
                new_values[new_count++] = ACCOUNT;
 
939
                                    new_values, new_count)) {
 
940
                BerValue *bv;
 
941
 
 
942
                bv = g_malloc(sizeof (*bv));
 
943
                bv->bv_val = ACCOUNT;
 
944
                bv->bv_len = strlen(ACCOUNT);
 
945
                new_values[new_count++] = bv;
 
946
        }
1001
947
        if (new_count != 0)
1002
948
                new_values[new_count] = NULL;
1003
949
        else {
1007
953
        return new_values;
1008
954
}
1009
955
 
 
956
/* Free the (non-NULL) result of ldap_needed_objectclasses */
 
957
static void
 
958
free_needed_objectclasses(BerValue **values)
 
959
{
 
960
        size_t i;
 
961
 
 
962
        for (i = 0; values[i] != NULL; i++)
 
963
                g_free(values[i]);
 
964
        g_free(values);
 
965
}
 
966
 
 
967
 
1010
968
/* Build a list of LDAPMod structures for adding the entity object. */
1011
969
static LDAPMod **
1012
970
get_ent_adds(const char *dn, struct lu_ent *ent)
1021
979
        /* If there are no attributes, then this is EASY. */
1022
980
        attrs = lu_ent_get_attributes(ent);
1023
981
        if (attrs) {
1024
 
                char **classes;
 
982
                BerValue **classes;
1025
983
                size_t mod_count, i;
1026
984
                LDAPMod *mod;
1027
985
                GValueArray *vals;
1065
1023
                        mod->mod_op = LDAP_MOD_ADD;
1066
1024
                        mod->mod_type = OBJECTCLASS;
1067
1025
                        mod->mod_values
1068
 
                                = g_malloc0((ldap_count_values(classes) + 1)
1069
 
                                            * sizeof(*mod->mod_values));
 
1026
                                = g_malloc0((ldap_count_values_len(classes)
 
1027
                                             + 1) * sizeof(*mod->mod_values));
1070
1028
                        for (i = 0; classes[i] != NULL; i++)
1071
 
                                mod->mod_values[i] = g_strdup(classes[i]);
1072
 
                        g_free(classes);
 
1029
                                mod->mod_values[i]
 
1030
                                        = g_strdup(classes[i]->bv_val);
 
1031
                        free_needed_objectclasses(classes);
1073
1032
                        mods[mod_count++] = mod;
1074
1033
                }
1075
1034
                /* Ugly hack:
1097
1056
                        }
1098
1057
                        mod = g_malloc0(sizeof(*mod));
1099
1058
                        mod->mod_op = LDAP_MOD_ADD;
1100
 
                        mod->mod_type = (char *)map_to_ldap(ent->cache,
1101
 
                                                            LU_COMMONNAME);
 
1059
                        mod->mod_type = (char *)"cn";
1102
1060
                        mod->mod_values
1103
1061
                                = g_malloc0(2 * sizeof (*mod->mod_values));
1104
1062
                        mod->mod_values[0] = cn;
1111
1069
/* Build a list of LDAPMod structures based on the differences between the
1112
1070
 * pending and current values in the entity object. */
1113
1071
static LDAPMod **
1114
 
get_ent_mods(struct lu_module *module, struct lu_ent *ent,
1115
 
             const char *namingAttr)
 
1072
get_ent_mods(struct lu_ent *ent, const char *namingAttr)
1116
1073
{
1117
1074
        LDAPMod **mods = NULL;
1118
 
        GList *attrs = NULL;
 
1075
        GList *attrs;
1119
1076
 
1120
1077
        g_assert(ent != NULL);
1121
1078
        g_assert(ent->magic == LU_ENT_MAGIC);
1240
1197
static void
1241
1198
free_ent_mods(LDAPMod ** mods)
1242
1199
{
1243
 
        int i, j;
 
1200
        size_t i;
 
1201
 
1244
1202
        g_assert(mods != NULL);
1245
1203
        for (i = 0; mods && mods[i]; i++) {
1246
1204
                if (mods[i]->mod_values) {
 
1205
                        size_t j;
 
1206
 
1247
1207
                        for (j = 0; mods[i]->mod_values[j] != NULL; j++) {
1248
1208
                                g_free(mods[i]->mod_values[j]);
1249
1209
                        }
1259
1219
static void
1260
1220
dump_mods(LDAPMod ** mods)
1261
1221
{
1262
 
        int i, j;
 
1222
        size_t i;
1263
1223
        g_assert(mods != NULL);
1264
1224
        for (i = 0; mods[i]; i++) {
1265
1225
                g_print("%s (%d)\n", mods[i]->mod_type, mods[i]->mod_op);
1266
1226
                if (mods[i]->mod_values) {
 
1227
                        size_t j;
 
1228
 
1267
1229
                        for (j = 0; mods[i]->mod_values[j]; j++) {
1268
1230
                                g_print(" = `%s'\n",
1269
1231
                                        mods[i]->mod_values[j]);
1280
1242
                            const char *dn,
1281
1243
                            struct lu_ent *ent)
1282
1244
{
1283
 
        char *attrs[] = {
 
1245
        static char *attrs[] = {
1284
1246
                OBJECTCLASS,
1285
1247
                NULL,
1286
1248
        };
1287
 
        char **old_values, **new_values;
 
1249
 
 
1250
        BerValue **old_values, **new_values;
1288
1251
        LDAPMessage *res = NULL;
1289
1252
        LDAPMessage *entry;
1290
1253
 
1291
1254
        /* Pull up this object's entry. */
1292
 
        if (ldap_search_s(ctx->ldap, dn, LDAP_SCOPE_BASE, NULL,
1293
 
                          attrs, FALSE, &res) != LDAP_SUCCESS) {
 
1255
        if (ldap_search_ext_s(ctx->ldap, dn, LDAP_SCOPE_BASE, NULL, attrs,
 
1256
                              FALSE, NULL, NULL, NULL, LDAP_NO_LIMIT, &res)
 
1257
            != LDAP_SUCCESS) {
1294
1258
                return;
1295
1259
        }
1296
1260
 
1301
1265
        }
1302
1266
 
1303
1267
        /* Get the list of object classes the object is in now. */
1304
 
        old_values = ldap_get_values(ctx->ldap, entry, OBJECTCLASS);
 
1268
        old_values = ldap_get_values_len(ctx->ldap, entry, OBJECTCLASS);
1305
1269
 
1306
1270
        new_values = lu_ldap_needed_objectclasses(dn, ent, old_values);
1307
1271
        if (new_values != NULL) {
1313
1277
#endif
1314
1278
                /* Set up the modify request. */
1315
1279
                memset(&mod, 0, sizeof(mod));
1316
 
                mod.mod_op = LDAP_MOD_ADD;
 
1280
                mod.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
1317
1281
                mod.mod_type = OBJECTCLASS;
1318
 
                mod.mod_values = new_values;
 
1282
                mod.mod_bvalues = new_values;
1319
1283
 
1320
1284
                /* Give it the old try. */
1321
1285
#ifdef DEBUG
1322
1286
                dump_mods(mods);
1323
1287
#endif
1324
 
                err = ldap_modify_s(ctx->ldap, dn, mods);
 
1288
                err = ldap_modify_ext_s(ctx->ldap, dn, mods, NULL, NULL);
1325
1289
#ifdef DEBUG
1326
1290
                g_message("Fudged: `%s'.\n", ldap_err2string(err));
1327
1291
#endif
1328
 
                g_free (new_values);
 
1292
                free_needed_objectclasses(new_values);
1329
1293
        }
1330
 
        ldap_value_free(old_values);
 
1294
        ldap_value_free_len(old_values);
1331
1295
 
1332
1296
        ldap_msgfree(res);
1333
1297
}
1335
1299
/* Apply the changes to a given entity structure, or add a new entitty. */
1336
1300
static gboolean
1337
1301
lu_ldap_set(struct lu_module *module, enum lu_entity_type type, int add,
1338
 
            struct lu_ent *ent, const char *configKey, const char *def,
1339
 
            struct lu_error **error)
 
1302
            struct lu_ent *ent, const char *branch, struct lu_error **error)
1340
1303
{
1341
 
        LDAPMod **mods = NULL;
1342
 
        LDAPControl *server = NULL, *client = NULL;
1343
 
        GValueArray *name = NULL, *old_name = NULL;
 
1304
        LDAPMod **mods;
 
1305
        GValueArray *name, *old_name;
1344
1306
        GValue *value;
1345
1307
        char *name_string;
1346
 
        const char *dn = NULL, *namingAttr = NULL;
 
1308
        const char *dn, *namingAttr;
1347
1309
        int err;
1348
1310
        gboolean ret = FALSE;
1349
1311
        struct lu_ldap_context *ctx;
1352
1314
        g_assert((type == lu_user) || (type == lu_group));
1353
1315
        g_assert(ent != NULL);
1354
1316
        g_assert(ent->magic == LU_ENT_MAGIC);
1355
 
        g_assert(configKey != NULL);
1356
 
        g_assert(strlen(configKey) > 0);
1357
1317
        LU_ERROR_CHECK(error);
1358
1318
 
1359
1319
        ctx = module->module_context;
1385
1345
        /* Get the object's current object name. */
1386
1346
        value = g_value_array_get_nth(add ? name : old_name, 0);
1387
1347
        name_string = lu_value_strdup(value);
1388
 
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, configKey,
1389
 
                               def);
 
1348
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, branch);
1390
1349
        g_free(name_string);
1391
 
        if (dn == NULL) {
1392
 
                lu_error_new(error, lu_error_generic,
1393
 
                             _
1394
 
                             ("error mapping name to LDAP distinguished name"));
1395
 
                return FALSE;
1396
 
        }
1397
1350
 
1398
1351
        /* Get the list of changes needed. */
1399
1352
        if (add)
1400
1353
                mods = get_ent_adds(dn, ent);
1401
1354
        else
1402
 
                mods = get_ent_mods(module, ent, namingAttr);
 
1355
                mods = get_ent_mods(ent, namingAttr);
1403
1356
        if (mods == NULL) {
1404
1357
                lu_error_new(error, lu_error_generic,
1405
1358
                             _("could not convert internal data to LDAPMods"));
1410
1363
                dump_mods(mods);
1411
1364
                g_message("Adding `%s'.\n", dn);
1412
1365
#endif
1413
 
                err = ldap_add_ext_s(ctx->ldap, dn, mods, &server, &client);
 
1366
                err = ldap_add_ext_s(ctx->ldap, dn, mods, NULL, NULL);
1414
1367
                if (err == LDAP_SUCCESS)
1415
1368
                        ret = TRUE;
1416
1369
                else {
1425
1378
                g_message("Modifying `%s'.\n", dn);
1426
1379
#endif
1427
1380
                /* Attempt the modify operation. */
1428
 
                err = ldap_modify_ext_s(ctx->ldap, dn, mods, &server, &client);
 
1381
                err = ldap_modify_ext_s(ctx->ldap, dn, mods, NULL, NULL);
1429
1382
                if (err == LDAP_SUCCESS)
1430
1383
                        ret = TRUE;
1431
1384
                else {
1435
1388
                                 * control.... */
1436
1389
                                lu_ldap_fudge_objectclasses(ctx, dn, ent);
1437
1390
                                err = ldap_modify_ext_s(ctx->ldap, dn, mods,
1438
 
                                                        &server, &client);
 
1391
                                                        NULL, NULL);
1439
1392
                        }
1440
1393
                        if (err == LDAP_SUCCESS)
1441
1394
                                ret = TRUE;
1462
1415
                        g_free (tmp1);
1463
1416
                        /* Attempt the rename. */
1464
1417
                        err = ldap_rename_s(ctx->ldap, dn, tmp2, NULL, TRUE,
1465
 
                                            &server, &client);
 
1418
                                            NULL, NULL);
1466
1419
                        g_free(tmp2);
1467
1420
                        if (err == LDAP_SUCCESS)
1468
1421
                                ret = TRUE;
1485
1438
/* Remove an entry from the directory. */
1486
1439
static gboolean
1487
1440
lu_ldap_del(struct lu_module *module, enum lu_entity_type type,
1488
 
            struct lu_ent *ent, const char *configKey, const char *def,
1489
 
            struct lu_error **error)
 
1441
            struct lu_ent *ent, const char *branch, struct lu_error **error)
1490
1442
{
1491
 
        LDAPControl *server = NULL, *client = NULL;
1492
 
        GValueArray *name = NULL;
 
1443
        GValueArray *name;
1493
1444
        GValue *value;
1494
1445
        char *name_string;
1495
 
        const char *dn = NULL, *namingAttr = NULL;
 
1446
        const char *dn, *namingAttr;
1496
1447
        int err;
1497
1448
        gboolean ret = FALSE;
1498
1449
        struct lu_ldap_context *ctx;
1501
1452
        g_assert((type == lu_user) || (type == lu_group));
1502
1453
        g_assert(ent != NULL);
1503
1454
        g_assert(ent->magic == LU_ENT_MAGIC);
1504
 
        g_assert(configKey != NULL);
1505
 
        g_assert(strlen(configKey) > 0);
1506
1455
        LU_ERROR_CHECK(error);
1507
1456
 
1508
1457
        ctx = module->module_context;
1524
1473
        /* Convert the name to a distinguished name. */
1525
1474
        value = g_value_array_get_nth(name, 0);
1526
1475
        name_string = lu_value_strdup(value);
1527
 
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, configKey,
1528
 
                               def);
 
1476
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, branch);
1529
1477
        g_free(name_string);
1530
 
        if (dn == NULL) {
1531
 
                lu_error_new(error, lu_error_generic,
1532
 
                             _("error mapping name to LDAP distinguished name"));
1533
 
                return FALSE;
1534
 
        }
1535
1478
        /* Process the removal. */
1536
1479
#ifdef DEBUG
1537
1480
        g_message("Removing `%s'.\n", dn);
1538
1481
#endif
1539
 
        err = ldap_delete_ext_s(ctx->ldap, dn, &server, &client);
 
1482
        err = ldap_delete_ext_s(ctx->ldap, dn, NULL, NULL);
1540
1483
        if (err == LDAP_SUCCESS) {
1541
1484
                ret = TRUE;
1542
1485
        } else {
1553
1496
static gboolean
1554
1497
lu_ldap_handle_lock(struct lu_module *module, struct lu_ent *ent,
1555
1498
                    const char *namingAttr, enum lock_op op,
1556
 
                    const char *configKey, const char *def,
1557
 
                    struct lu_error **error)
 
1499
                    const char *branch, struct lu_error **error)
1558
1500
{
1559
1501
        const char *dn;
1560
1502
        gboolean ret = FALSE;
1561
1503
        LDAPMod mod[2], *mods[3];
1562
 
        LDAPControl *server = NULL, *client = NULL;
1563
1504
        GValueArray *name, *password;
1564
1505
        GValue *value;
1565
1506
        char *result, *name_string, *oldpassword, *values[2][2];
1566
1507
        const char *tmp, *attribute;
1567
 
        struct lu_ldap_context *ctx = module->module_context;
1568
 
        size_t scheme_len = strlen(LU_CRYPTED);
 
1508
        struct lu_ldap_context *ctx;
1569
1509
        int err;
1570
1510
 
1571
1511
        g_assert(module != NULL);
1573
1513
        g_assert(namingAttr != NULL);
1574
1514
        g_assert(strlen(namingAttr) > 0);
1575
1515
        LU_ERROR_CHECK(error);
 
1516
        ctx = module->module_context;
1576
1517
 
1577
1518
        /* Get the entry's name. */
1578
1519
        name = lu_ent_get(ent, namingAttr);
1585
1526
        /* Convert the name to a distinguished name. */
1586
1527
        value = g_value_array_get_nth(name, 0);
1587
1528
        name_string = lu_value_strdup(value);
1588
 
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, configKey,
1589
 
                               def);
 
1529
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, branch);
1590
1530
        g_free(name_string);
1591
 
        if (dn == NULL) {
1592
 
                lu_error_new(error, lu_error_generic,
1593
 
                             _("error mapping name to LDAP distinguished name"));
1594
 
                return FALSE;
1595
 
        }
1596
1531
 
1597
1532
        attribute = ent->type == lu_user ? LU_USERPASSWORD : LU_GROUPPASSWORD;
1598
1533
 
1609
1544
 
1610
1545
        /* We only know how to lock crypted passwords, so crypt it if it
1611
1546
         * isn't already. */
1612
 
        if (strncmp(oldpassword, LU_CRYPTED, scheme_len) != 0) {
 
1547
        if (!g_str_has_prefix(oldpassword, LU_CRYPTED)) {
1613
1548
                tmp = lu_make_crypted(oldpassword,
1614
1549
                                      lu_common_default_salt_specifier(module));
1615
1550
                if (tmp == NULL) {
1618
1553
                        g_free(oldpassword);
1619
1554
                        return FALSE;
1620
1555
                }
1621
 
        } else {
1622
 
                tmp = ent->cache->cache(ent->cache, oldpassword + scheme_len);
1623
 
        }
 
1556
        } else
 
1557
                tmp = ent->cache->cache(ent->cache,
 
1558
                                        oldpassword + strlen(LU_CRYPTED));
1624
1559
        result = ent->cache->cache(ent->cache, tmp);
1625
1560
 
1626
1561
        /* Generate a new string with the modification applied. */
1674
1609
        mods[1] = &mod[1];
1675
1610
        mods[2] = NULL;
1676
1611
 
1677
 
        err = ldap_modify_ext_s(ctx->ldap, dn, mods, &server, &client);
 
1612
        err = ldap_modify_ext_s(ctx->ldap, dn, mods, NULL, NULL);
1678
1613
        if (err == LDAP_SUCCESS) {
1679
1614
                ret = TRUE;
1680
1615
        } else {
1692
1627
/* Check if an account is locked. */
1693
1628
static gboolean
1694
1629
lu_ldap_is_locked(struct lu_module *module, struct lu_ent *ent,
1695
 
                  const char *namingAttr, const char *configKey,
1696
 
                  const char *def, struct lu_error **error)
 
1630
                  const char *namingAttr, const char *branch,
 
1631
                  struct lu_error **error)
1697
1632
{
1698
 
        const char *dn, *mapped_password;
 
1633
        static const char mapped_password[] = "userPassword";
 
1634
 
 
1635
        const char *dn;
1699
1636
        GValueArray *name;
1700
1637
        GValue *value;
1701
1638
        char *name_string;
1702
1639
        struct lu_ldap_context *ctx = module->module_context;
1703
1640
        char *attributes[] = { NULL, NULL };
1704
 
        char **values = NULL;
 
1641
        BerValue **values;
1705
1642
        LDAPMessage *entry = NULL, *messages = NULL;
1706
1643
        int i;
1707
 
        gboolean locked = FALSE;
 
1644
        gboolean locked;
1708
1645
 
1709
1646
        /* Get the name of the user or group. */
1710
1647
        name = lu_ent_get(ent, namingAttr);
1717
1654
        /* Convert the name to a distinguished name. */
1718
1655
        value = g_value_array_get_nth(name, 0);
1719
1656
        name_string = lu_value_strdup(value);
1720
 
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, configKey,
1721
 
                               def);
 
1657
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, branch);
1722
1658
        g_free(name_string);
1723
 
        if (dn == NULL) {
1724
 
                lu_error_new(error, lu_error_generic,
1725
 
                             _
1726
 
                             ("error mapping name to LDAP distinguished name"));
1727
 
                return FALSE;
1728
 
        }
1729
1659
#ifdef DEBUG
1730
1660
        g_print("Looking up `%s'.\n", dn);
1731
1661
#endif
1732
1662
 
1733
 
        mapped_password = map_to_ldap(module->scache, ent->type == lu_user
1734
 
                                      ? LU_USERPASSWORD : LU_GROUPPASSWORD);
1735
 
 
1736
1663
        /* Read the entry data. */
1737
1664
        attributes[0] = (char *)mapped_password;
1738
 
        if (ldap_search_s(ctx->ldap, dn, LDAP_SCOPE_BASE, ent->type == lu_user
1739
 
                          ? "("OBJECTCLASS"="POSIXACCOUNT")"
1740
 
                          : "("OBJECTCLASS"="POSIXGROUP")", attributes,
1741
 
                          FALSE, &messages) == LDAP_SUCCESS) {
 
1665
        if (ldap_search_ext_s(ctx->ldap, dn, LDAP_SCOPE_BASE,
 
1666
                              ent->type == lu_user
 
1667
                              ? "("OBJECTCLASS"="POSIXACCOUNT")"
 
1668
                              : "("OBJECTCLASS"="POSIXGROUP")", attributes,
 
1669
                              FALSE, NULL, NULL, NULL, LDAP_NO_LIMIT,
 
1670
                              &messages) == LDAP_SUCCESS) {
1742
1671
                entry = ldap_first_entry(ctx->ldap, messages);
1743
1672
        }
1744
1673
        if (entry == NULL) {
1748
1677
        }
1749
1678
 
1750
1679
        /* Read the values for the attribute we want to change. */
1751
 
        values = ldap_get_values(ctx->ldap, entry, mapped_password);
 
1680
        values = ldap_get_values_len(ctx->ldap, entry, mapped_password);
1752
1681
        if (values == NULL) {
1753
1682
                ldap_msgfree(messages);
1754
1683
#ifdef DEBUG
1761
1690
        /* Check any of the possibly-multiple passwords. */
1762
1691
        locked = FALSE;
1763
1692
        for (i = 0; values[i] != NULL; i++) {
 
1693
                const BerValue *val;
 
1694
                size_t prefix_len;
 
1695
 
 
1696
                val = values[i];
 
1697
                prefix_len = strlen(LU_CRYPTED);
1764
1698
#ifdef DEBUG
1765
 
                g_print("Got `%s' = `%s'.\n", mapped_password, values[i]);
 
1699
                g_print("Got `%s' = `.*%s'.\n", mapped_password,
 
1700
                        (int)val->bv_len, val->bv_val);
1766
1701
#endif
1767
 
                if (strncmp(values[i], LU_CRYPTED, strlen(LU_CRYPTED)) == 0) {
1768
 
                        locked = (values[i][strlen(LU_CRYPTED)] == LOCKCHAR);
 
1702
                if (val->bv_len >= prefix_len
 
1703
                    && memcmp(val->bv_val, LU_CRYPTED, prefix_len) == 0) {
 
1704
                        locked = (val->bv_len > prefix_len
 
1705
                                  && val->bv_val[prefix_len] == LOCKCHAR);
1769
1706
                        break;
1770
1707
                }
1771
1708
        }
1772
1709
        /* Clean up and return. */
1773
 
        ldap_value_free(values);
 
1710
        ldap_value_free_len(values);
1774
1711
        if (messages != NULL) {
1775
1712
                ldap_msgfree(messages);
1776
1713
        }
1781
1718
/* Set the password for an account. */
1782
1719
static gboolean
1783
1720
lu_ldap_setpass(struct lu_module *module, const char *namingAttr,
1784
 
                struct lu_ent *ent, const char *configKey, const char *def,
 
1721
                struct lu_ent *ent, const char *branch,
1785
1722
                const char *password, struct lu_error **error)
1786
1723
{
1787
 
        const char *dn, *mapped_password;
 
1724
        static const char mapped_password[] = "userPassword";
 
1725
 
 
1726
        const char *dn;
1788
1727
        GValueArray *name;
1789
1728
        GValue *value;
1790
1729
        char *name_string;
1791
1730
        struct lu_ldap_context *ctx = module->module_context;
1792
1731
        char *attributes[] = { NULL, NULL };
1793
 
        char **values, *addvalues[] = { NULL, NULL }, *rmvalues[] = {
1794
 
        NULL, NULL};
1795
 
        char *tmp = NULL, *previous;
 
1732
        char *addvalues[] = { NULL, NULL }, *rmvalues[] = { NULL, NULL };
 
1733
        BerValue **values;
 
1734
        char *previous;
1796
1735
        int i;
1797
1736
        size_t j;
1798
 
        LDAPMessage *entry = NULL, *messages = NULL;
 
1737
        LDAPMessage *messages = NULL;
1799
1738
        LDAPMod addmod, rmmod;
1800
1739
        LDAPMod *mods[3];
1801
 
        LDAPControl *server = NULL, *client = NULL;
1802
1740
        char filter[LINE_MAX];
1803
1741
 
1804
1742
        /* Get the user or group's name. */
1815
1753
        /* Convert the name to a distinguished name. */
1816
1754
        value = g_value_array_get_nth(name, 0);
1817
1755
        name_string = lu_value_strdup(value);
1818
 
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, configKey,
1819
 
                               def);
1820
 
        if (dn == NULL) {
1821
 
                lu_error_new(error, lu_error_generic,
1822
 
                             _("error mapping name to LDAP distinguished "
1823
 
                               "name"));
1824
 
                g_free(name_string);
1825
 
                return FALSE;
1826
 
        }
 
1756
        dn = lu_ldap_ent_to_dn(module, namingAttr, name_string, branch);
1827
1757
#ifdef DEBUG
1828
1758
        g_print("Setting password for `%s'.\n", dn);
1829
1759
#endif
1831
1761
        snprintf(filter, sizeof(filter), "(%s=%s)",
1832
1762
                 map_to_ldap(module->scache, namingAttr), name_string);
1833
1763
        g_free(name_string);
1834
 
        mapped_password = map_to_ldap(module->scache, ent->type == lu_user
1835
 
                                      ? LU_USERPASSWORD : LU_GROUPPASSWORD);
1836
1764
 
1837
1765
        previous = NULL;
1838
1766
        values = NULL;
1839
1767
        attributes[0] = (char *)mapped_password;
1840
 
        if ((i = ldap_search_s(ctx->ldap, dn, LDAP_SCOPE_BASE, filter,
1841
 
                               attributes, FALSE,
1842
 
                               &messages)) == LDAP_SUCCESS) {
 
1768
        i = ldap_search_ext_s(ctx->ldap, dn, LDAP_SCOPE_BASE, filter,
 
1769
                              attributes, FALSE, NULL, NULL, NULL,
 
1770
                              LDAP_NO_LIMIT, &messages);
 
1771
        if (i == LDAP_SUCCESS) {
 
1772
                LDAPMessage *entry;
 
1773
 
1843
1774
                entry = ldap_first_entry(ctx->ldap, messages);
1844
1775
                if (entry != NULL) {
1845
 
                        values = ldap_get_values(ctx->ldap, entry,
1846
 
                                                 mapped_password);
 
1776
                        values = ldap_get_values_len(ctx->ldap, entry,
 
1777
                                                     mapped_password);
1847
1778
                        if (values) {
1848
1779
                                for (j = 0; values[j] != NULL; j++) {
 
1780
                                        char *val;
 
1781
 
 
1782
                                        val = g_strndup(values[j]->bv_val,
 
1783
                                                        values[j]->bv_len);
1849
1784
#ifdef DEBUG
1850
1785
                                        g_print("Got `%s' = `%s'.\n",
1851
 
                                                mapped_password, values[j]);
 
1786
                                                mapped_password, val);
1852
1787
#endif
1853
 
                                        if (strncmp
1854
 
                                            (values[j], LU_CRYPTED,
1855
 
                                             strlen(LU_CRYPTED)) == 0) {
 
1788
                                        if (g_str_has_prefix(val,
 
1789
                                                             LU_CRYPTED)) {
1856
1790
#ifdef DEBUG
1857
1791
                                                g_print
1858
1792
                                                    ("Previous entry was `%s'.\n",
1859
 
                                                     values[j]);
 
1793
                                                     val);
1860
1794
#endif
1861
 
                                                previous = g_strdup(values[j]);
 
1795
                                                previous = val;
1862
1796
                                                break;
1863
1797
                                        }
 
1798
                                        g_free(val);
1864
1799
                                }
1865
 
                                ldap_value_free(values);
 
1800
                                ldap_value_free_len(values);
1866
1801
                        }
1867
1802
                }
1868
1803
        } else {
1875
1810
                ldap_msgfree(messages);
1876
1811
        }
1877
1812
 
1878
 
        if (strncmp(password, LU_CRYPTED, strlen(LU_CRYPTED)) == 0) {
 
1813
        if (g_str_has_prefix(password, LU_CRYPTED))
1879
1814
                addvalues[0] = (char *)password;
1880
 
        } else {
 
1815
        else {
1881
1816
                const char *crypted;
 
1817
                char *tmp;
1882
1818
 
1883
1819
                crypted =
1884
1820
                    lu_make_crypted(password, previous
1900
1836
                if (previous)
1901
1837
                        rmvalues[0] = previous;
1902
1838
                /* else deletes all values */
1903
 
                
 
1839
 
1904
1840
                rmmod.mod_op = LDAP_MOD_DELETE;
1905
1841
                rmmod.mod_type = (char *)mapped_password;
1906
1842
                rmmod.mod_values = rmvalues;
1912
1848
        mods[j++] = &addmod;
1913
1849
        mods[j] = NULL;
1914
1850
 
1915
 
        i = ldap_modify_ext_s(ctx->ldap, dn, mods, &server, &client);
 
1851
        i = ldap_modify_ext_s(ctx->ldap, dn, mods, NULL, NULL);
1916
1852
        g_free(previous);
1917
1853
        if (i != LDAP_SUCCESS) {
1918
1854
                lu_error_new(error, lu_error_generic,
1929
1865
lu_ldap_user_removepass(struct lu_module *module, struct lu_ent *ent,
1930
1866
                        struct lu_error **error)
1931
1867
{
 
1868
        struct lu_ldap_context *ctx;
 
1869
 
1932
1870
        LU_ERROR_CHECK(error);
1933
 
        return lu_ldap_setpass(module, LU_USERNAME, ent, "userBranch",
1934
 
                               USERBRANCH, LU_CRYPTED, error);
 
1871
        ctx = module->module_context;
 
1872
        return lu_ldap_setpass(module, LU_USERNAME, ent, ctx->user_branch,
 
1873
                               LU_CRYPTED, error);
1935
1874
}
1936
1875
 
1937
1876
static gboolean
1938
1877
lu_ldap_group_removepass(struct lu_module *module, struct lu_ent *ent,
1939
1878
                         struct lu_error **error)
1940
1879
{
 
1880
        struct lu_ldap_context *ctx;
 
1881
 
1941
1882
        LU_ERROR_CHECK(error);
1942
 
        return lu_ldap_setpass(module, LU_GROUPNAME, ent, "groupBranch",
1943
 
                               GROUPBRANCH, LU_CRYPTED, error);
 
1883
        ctx = module->module_context;
 
1884
        return lu_ldap_setpass(module, LU_GROUPNAME, ent, ctx->group_branch,
 
1885
                               LU_CRYPTED, error);
1944
1886
}
1945
1887
 
1946
1888
static GValueArray *
1947
1889
lu_ldap_enumerate(struct lu_module *module,
1948
1890
                  const char *searchAttr, const char *pattern,
1949
 
                  const char *returnAttr,
1950
 
                  const char *configKey, const char *def,
 
1891
                  const char *returnAttr, const char *branch,
1951
1892
                  struct lu_error **error)
1952
1893
{
1953
 
        LDAPMessage *messages = NULL, *entry = NULL;
1954
 
        char **values = NULL;
1955
 
        char *base = NULL, *filt = NULL;
1956
 
        const char *branch;
1957
 
        int i;
 
1894
        LDAPMessage *messages = NULL;
 
1895
        char *base, *filt;
1958
1896
        GValue value;
1959
 
        GValueArray *ret = NULL;
 
1897
        GValueArray *ret;
1960
1898
        struct lu_ldap_context *ctx;
1961
1899
        char *attributes[] = { (char *) returnAttr, NULL };
1962
 
        char *tmp;
1963
1900
 
1964
1901
        g_assert(module != NULL);
1965
1902
        g_assert(searchAttr != NULL);
1966
1903
        g_assert(strlen(searchAttr) > 0);
1967
1904
        g_assert(returnAttr != NULL);
1968
1905
        g_assert(strlen(returnAttr) > 0);
1969
 
        g_assert(configKey != NULL);
1970
 
        g_assert(strlen(configKey) > 0);
1971
 
        g_assert(attributes != NULL);
1972
 
        g_assert(attributes[0] != NULL);
1973
1906
        LU_ERROR_CHECK(error);
1974
1907
 
1975
1908
        ctx = module->module_context;
1976
1909
 
1977
 
        /* Get the name of the key which tells us where to search. */
1978
 
        tmp = g_strdup_printf("%s/%s", module->name, configKey);
1979
 
        branch = lu_cfg_read_single(module->lu_context, tmp, def);
1980
 
        g_free(tmp);
1981
 
 
1982
1910
        /* Generate the base DN to search under. */
 
1911
        /* FIXME: this is inconsistent with lu_ldap_base() usage elsewhere */
1983
1912
        base = g_strdup_printf("%s,%s", branch,
1984
1913
                               ctx->prompts[LU_LDAP_BASEDN].value &&
1985
1914
                               strlen(ctx->prompts[LU_LDAP_BASEDN].value) ?
1995
1924
        ret = g_value_array_new(0);
1996
1925
        memset(&value, 0, sizeof(value));
1997
1926
        g_value_init(&value, G_TYPE_STRING);
1998
 
        if (ldap_search_s(ctx->ldap, base, LDAP_SCOPE_SUBTREE, filt, attributes,
1999
 
                          FALSE, &messages) == LDAP_SUCCESS) {
 
1927
        if (ldap_search_ext_s(ctx->ldap, base, LDAP_SCOPE_SUBTREE, filt,
 
1928
                              attributes, FALSE, NULL, NULL, NULL,
 
1929
                              LDAP_NO_LIMIT, &messages) == LDAP_SUCCESS) {
 
1930
                LDAPMessage *entry;
 
1931
 
2000
1932
                entry = ldap_first_entry(ctx->ldap, messages);
2001
1933
                if (entry != NULL) {
2002
1934
                        while (entry != NULL) {
2003
 
                                values = ldap_get_values(ctx->ldap, entry,
2004
 
                                                         returnAttr);
 
1935
                                BerValue **values;
 
1936
                                size_t i;
 
1937
 
 
1938
                                values = ldap_get_values_len(ctx->ldap, entry,
 
1939
                                                             returnAttr);
2005
1940
                                for (i = 0;
2006
1941
                                     (values != NULL) && (values[i] != NULL);
2007
1942
                                     i++) {
 
1943
                                        char *val;
 
1944
 
 
1945
                                        val = g_strndup(values[i]->bv_val,
 
1946
                                                        values[i]->bv_len);
2008
1947
#ifdef DEBUG
2009
1948
                                        g_print("Got `%s' = `%s'.\n",
2010
 
                                                returnAttr, values[i]);
 
1949
                                                returnAttr, val);
2011
1950
#endif
2012
 
                                        g_value_set_string(&value, values[i]);
 
1951
                                        g_value_take_string(&value, val);
2013
1952
                                        g_value_array_append(ret, &value);
2014
1953
                                }
2015
 
                                if (values != NULL) {
2016
 
                                        ldap_value_free(values);
2017
 
                                }
 
1954
                                ldap_value_free_len(values);
2018
1955
                                entry = ldap_next_entry(ctx->ldap, entry);
2019
1956
                        }
2020
1957
#ifdef DEBUG
2049
1986
lu_ldap_user_add(struct lu_module *module, struct lu_ent *ent,
2050
1987
                 struct lu_error **error)
2051
1988
{
 
1989
        struct lu_ldap_context *ctx;
 
1990
 
2052
1991
        LU_ERROR_CHECK(error);
2053
 
        return lu_ldap_set(module, lu_user, 1, ent, "userBranch", USERBRANCH,
2054
 
                           error);
 
1992
        ctx = module->module_context;
 
1993
        return lu_ldap_set(module, lu_user, 1, ent, ctx->user_branch, error);
2055
1994
}
2056
1995
 
2057
1996
/* Modify a user record in the directory. */
2059
1998
lu_ldap_user_mod(struct lu_module *module, struct lu_ent *ent,
2060
1999
                 struct lu_error **error)
2061
2000
{
 
2001
        struct lu_ldap_context *ctx;
 
2002
 
2062
2003
        LU_ERROR_CHECK(error);
2063
 
        return lu_ldap_set(module, lu_user, 0, ent, "userBranch", USERBRANCH,
2064
 
                           error);
 
2004
        ctx = module->module_context;
 
2005
        return lu_ldap_set(module, lu_user, 0, ent, ctx->user_branch, error);
2065
2006
}
2066
2007
 
2067
2008
/* Remove a user from the directory. */
2069
2010
lu_ldap_user_del(struct lu_module *module, struct lu_ent *ent,
2070
2011
                 struct lu_error **error)
2071
2012
{
 
2013
        struct lu_ldap_context *ctx;
 
2014
 
2072
2015
        LU_ERROR_CHECK(error);
2073
 
        return lu_ldap_del(module, lu_user, ent, "userBranch", USERBRANCH,
2074
 
                           error);
 
2016
        ctx = module->module_context;
 
2017
        return lu_ldap_del(module, lu_user, ent, ctx->user_branch, error);
2075
2018
}
2076
2019
 
2077
2020
/* Lock a user account in the directory. */
2079
2022
lu_ldap_user_lock(struct lu_module *module, struct lu_ent *ent,
2080
2023
                  struct lu_error **error)
2081
2024
{
 
2025
        struct lu_ldap_context *ctx;
 
2026
 
2082
2027
        LU_ERROR_CHECK(error);
 
2028
        ctx = module->module_context;
2083
2029
        return lu_ldap_handle_lock(module, ent, LU_USERNAME, LO_LOCK,
2084
 
                                   "userBranch", USERBRANCH, error);
 
2030
                                   ctx->user_branch, error);
2085
2031
}
2086
2032
 
2087
2033
/* Unlock a user account in the directory. */
2089
2035
lu_ldap_user_unlock(struct lu_module *module, struct lu_ent *ent,
2090
2036
                    struct lu_error **error)
2091
2037
{
 
2038
        struct lu_ldap_context *ctx;
 
2039
 
2092
2040
        LU_ERROR_CHECK(error);
 
2041
        ctx = module->module_context;
2093
2042
        return lu_ldap_handle_lock(module, ent, LU_USERNAME, LO_UNLOCK,
2094
 
                                   "userBranch", USERBRANCH, error);
 
2043
                                   ctx->user_branch, error);
2095
2044
}
2096
2045
 
2097
2046
static gboolean
2098
2047
lu_ldap_user_unlock_nonempty(struct lu_module *module, struct lu_ent *ent,
2099
2048
                             struct lu_error **error)
2100
2049
{
 
2050
        struct lu_ldap_context *ctx;
 
2051
 
2101
2052
        LU_ERROR_CHECK(error);
 
2053
        ctx = module->module_context;
2102
2054
        return lu_ldap_handle_lock(module, ent, LU_USERNAME,
2103
 
                                   LO_UNLOCK_NONEMPTY, "userBranch",
2104
 
                                   USERBRANCH, error);
 
2055
                                   LO_UNLOCK_NONEMPTY, ctx->user_branch,
 
2056
                                   error);
2105
2057
}
2106
2058
 
2107
2059
/* Check if a user account in the directory is locked. */
2109
2061
lu_ldap_user_is_locked(struct lu_module *module, struct lu_ent *ent,
2110
2062
                       struct lu_error **error)
2111
2063
{
 
2064
        struct lu_ldap_context *ctx;
 
2065
 
2112
2066
        LU_ERROR_CHECK(error);
2113
 
        return lu_ldap_is_locked(module, ent, LU_USERNAME, "userBranch",
2114
 
                                 USERBRANCH, error);
 
2067
        ctx = module->module_context;
 
2068
        return lu_ldap_is_locked(module, ent, LU_USERNAME, ctx->user_branch,
 
2069
                                 error);
2115
2070
}
2116
2071
 
2117
2072
/* Set a user's password in the directory. */
2119
2074
lu_ldap_user_setpass(struct lu_module *module, struct lu_ent *ent,
2120
2075
                     const char *password, struct lu_error **error)
2121
2076
{
 
2077
        struct lu_ldap_context *ctx;
 
2078
 
2122
2079
        LU_ERROR_CHECK(error);
2123
 
        return lu_ldap_setpass(module, LU_USERNAME, ent, "userBranch",
2124
 
                               USERBRANCH, password, error);
 
2080
        ctx = module->module_context;
 
2081
        return lu_ldap_setpass(module, LU_USERNAME, ent, ctx->user_branch,
 
2082
                               password, error);
2125
2083
}
2126
2084
 
2127
2085
/* Add a group entry to the directory. */
2139
2097
lu_ldap_group_add(struct lu_module *module, struct lu_ent *ent,
2140
2098
                  struct lu_error **error)
2141
2099
{
 
2100
        struct lu_ldap_context *ctx;
 
2101
 
2142
2102
        LU_ERROR_CHECK(error);
2143
 
        return lu_ldap_set(module, lu_group, 1, ent, "groupBranch",
2144
 
                           GROUPBRANCH, error);
 
2103
        ctx = module->module_context;
 
2104
        return lu_ldap_set(module, lu_group, 1, ent, ctx->group_branch, error);
2145
2105
}
2146
2106
 
2147
2107
/* Modify a group entry in the directory. */
2149
2109
lu_ldap_group_mod(struct lu_module *module, struct lu_ent *ent,
2150
2110
                  struct lu_error **error)
2151
2111
{
 
2112
        struct lu_ldap_context *ctx;
 
2113
 
2152
2114
        LU_ERROR_CHECK(error);
2153
 
        return lu_ldap_set(module, lu_group, 0, ent, "groupBranch",
2154
 
                           GROUPBRANCH, error);
 
2115
        ctx = module->module_context;
 
2116
        return lu_ldap_set(module, lu_group, 0, ent, ctx->group_branch, error);
2155
2117
}
2156
2118
 
2157
2119
/* Remove a group entry from the directory. */
2159
2121
lu_ldap_group_del(struct lu_module *module, struct lu_ent *ent,
2160
2122
                  struct lu_error **error)
2161
2123
{
 
2124
        struct lu_ldap_context *ctx;
 
2125
 
2162
2126
        LU_ERROR_CHECK(error);
2163
 
        return lu_ldap_del(module, lu_group, ent, "groupBranch",
2164
 
                           GROUPBRANCH, error);
 
2127
        ctx = module->module_context;
 
2128
        return lu_ldap_del(module, lu_group, ent, ctx->group_branch, error);
2165
2129
}
2166
2130
 
2167
2131
/* Lock a group account in the directory. */
2169
2133
lu_ldap_group_lock(struct lu_module *module, struct lu_ent *ent,
2170
2134
                   struct lu_error **error)
2171
2135
{
 
2136
        struct lu_ldap_context *ctx;
 
2137
 
2172
2138
        LU_ERROR_CHECK(error);
 
2139
        ctx = module->module_context;
2173
2140
        return lu_ldap_handle_lock(module, ent, LU_GROUPNAME, LO_LOCK,
2174
 
                                   "groupBranch", GROUPBRANCH, error);
 
2141
                                   ctx->group_branch, error);
2175
2142
}
2176
2143
 
2177
2144
/* Unlock a group account in the directory. */
2179
2146
lu_ldap_group_unlock(struct lu_module *module, struct lu_ent *ent,
2180
2147
                     struct lu_error **error)
2181
2148
{
 
2149
        struct lu_ldap_context *ctx;
 
2150
 
2182
2151
        LU_ERROR_CHECK(error);
 
2152
        ctx = module->module_context;
2183
2153
        return lu_ldap_handle_lock(module, ent, LU_GROUPNAME, LO_UNLOCK,
2184
 
                                   "groupBranch", GROUPBRANCH, error);
 
2154
                                   ctx->group_branch, error);
2185
2155
}
2186
2156
 
2187
2157
static gboolean
2188
2158
lu_ldap_group_unlock_nonempty(struct lu_module *module, struct lu_ent *ent,
2189
2159
                              struct lu_error **error)
2190
2160
{
 
2161
        struct lu_ldap_context *ctx;
 
2162
 
2191
2163
        LU_ERROR_CHECK(error);
 
2164
        ctx = module->module_context;
2192
2165
        return lu_ldap_handle_lock(module, ent, LU_GROUPNAME,
2193
 
                                   LO_UNLOCK_NONEMPTY, "groupBranch",
2194
 
                                   GROUPBRANCH, error);
 
2166
                                   LO_UNLOCK_NONEMPTY, ctx->group_branch,
 
2167
                                   error);
2195
2168
}
2196
2169
 
2197
2170
/* Check if a group account in the directory is locked. */
2199
2172
lu_ldap_group_is_locked(struct lu_module *module, struct lu_ent *ent,
2200
2173
                        struct lu_error **error)
2201
2174
{
 
2175
        struct lu_ldap_context *ctx;
 
2176
 
2202
2177
        LU_ERROR_CHECK(error);
2203
 
        return lu_ldap_is_locked(module, ent, LU_GROUPNAME, "groupBranch",
2204
 
                                 GROUPBRANCH, error);
 
2178
        ctx = module->module_context;
 
2179
        return lu_ldap_is_locked(module, ent, LU_GROUPNAME, ctx->group_branch,
 
2180
                                 error);
2205
2181
}
2206
2182
 
2207
2183
/* Set a group's password in the directory. */
2209
2185
lu_ldap_group_setpass(struct lu_module *module, struct lu_ent *ent,
2210
2186
                      const char *password, struct lu_error **error)
2211
2187
{
 
2188
        struct lu_ldap_context *ctx;
 
2189
 
2212
2190
        LU_ERROR_CHECK(error);
2213
 
        return lu_ldap_setpass(module, LU_GROUPNAME, ent, "groupBranch",
2214
 
                               GROUPBRANCH, password, error);
 
2191
        ctx = module->module_context;
 
2192
        return lu_ldap_setpass(module, LU_GROUPNAME, ent, ctx->group_branch,
 
2193
                               password, error);
2215
2194
}
2216
2195
 
2217
2196
/* Populate user or group structures with the proper defaults. */
2238
2217
lu_ldap_users_enumerate(struct lu_module *module, const char *pattern,
2239
2218
                        struct lu_error **error)
2240
2219
{
 
2220
        struct lu_ldap_context *ctx;
 
2221
 
2241
2222
        LU_ERROR_CHECK(error);
2242
 
        return lu_ldap_enumerate(module,
2243
 
                                 map_to_ldap(module->scache, LU_USERNAME),
2244
 
                                 pattern,
2245
 
                                 map_to_ldap(module->scache, LU_USERNAME),
2246
 
                                 "userBranch", USERBRANCH, error);
 
2223
        ctx = module->module_context;
 
2224
        return lu_ldap_enumerate(module, "uid", pattern, "uid",
 
2225
                                 ctx->user_branch, error);
2247
2226
}
2248
2227
 
2249
2228
static GPtrArray *
2250
2229
lu_ldap_users_enumerate_full(struct lu_module *module, const char *pattern,
2251
2230
                             struct lu_error **error)
2252
2231
{
 
2232
        struct lu_ldap_context *ctx;
2253
2233
        GPtrArray *array = g_ptr_array_new();
 
2234
 
2254
2235
        LU_ERROR_CHECK(error);
2255
 
        lu_ldap_lookup(module,
2256
 
                       map_to_ldap(module->scache, LU_USERNAME), pattern,
2257
 
                       NULL, array,
2258
 
                       "userBranch", USERBRANCH,
 
2236
        ctx = module->module_context;
 
2237
        lu_ldap_lookup(module, "uid", pattern, NULL, array, ctx->user_branch,
2259
2238
                       "("OBJECTCLASS"="POSIXACCOUNT")",
2260
 
                       lu_ldap_user_attributes, LU_LDAP_USER | LU_LDAP_SHADOW,
2261
 
                       error);
 
2239
                       lu_ldap_user_attributes, lu_user, error);
2262
2240
        return array;
2263
2241
}
2264
2242
 
2267
2245
lu_ldap_groups_enumerate(struct lu_module *module, const char *pattern,
2268
2246
                         struct lu_error **error)
2269
2247
{
 
2248
        struct lu_ldap_context *ctx;
 
2249
 
2270
2250
        LU_ERROR_CHECK(error);
2271
 
        return lu_ldap_enumerate(module,
2272
 
                                 map_to_ldap(module->scache, LU_GROUPNAME),
2273
 
                                 pattern,
2274
 
                                 map_to_ldap(module->scache, LU_GROUPNAME),
2275
 
                                 "groupBranch", GROUPBRANCH, error);
 
2251
        ctx = module->module_context;
 
2252
        return lu_ldap_enumerate(module, "cn", pattern, "cn",
 
2253
                                 ctx->group_branch, error);
2276
2254
}
2277
2255
 
2278
2256
static GPtrArray *
2279
2257
lu_ldap_groups_enumerate_full(struct lu_module *module, const char *pattern,
2280
2258
                              struct lu_error **error)
2281
2259
{
 
2260
        struct lu_ldap_context *ctx;
 
2261
 
2282
2262
        GPtrArray *array = g_ptr_array_new();
2283
2263
        LU_ERROR_CHECK(error);
2284
 
        lu_ldap_lookup(module,
2285
 
                       map_to_ldap(module->scache, LU_GROUPNAME), pattern,
2286
 
                       NULL, array,
2287
 
                       "groupBranch", GROUPBRANCH,
 
2264
        ctx = module->module_context;
 
2265
        lu_ldap_lookup(module, "cn", pattern, NULL, array, ctx->group_branch,
2288
2266
                       "("OBJECTCLASS"="POSIXGROUP")",
2289
 
                       lu_ldap_group_attributes, LU_LDAP_GROUP | LU_LDAP_SHADOW,
2290
 
                       error);
 
2267
                       lu_ldap_group_attributes, lu_group, error);
2291
2268
        return array;
2292
2269
}
2293
2270
 
2298
2275
                                 const char *group, gid_t gid,
2299
2276
                                 struct lu_error **error)
2300
2277
{
2301
 
        GValueArray *primaries = NULL, *secondaries = NULL;
 
2278
        struct lu_ldap_context *ctx;
 
2279
        GValueArray *primaries;
2302
2280
        GValue *value;
2303
2281
        char *grp;
2304
2282
        size_t i;
2305
2283
 
2306
2284
        LU_ERROR_CHECK(error);
 
2285
        ctx = module->module_context;
2307
2286
        grp = g_strdup_printf("%jd", (intmax_t)gid);
2308
2287
 
2309
 
        primaries = lu_ldap_enumerate(module,
2310
 
                                      map_to_ldap(module->scache, LU_GIDNUMBER),
2311
 
                                      grp,
2312
 
                                      map_to_ldap(module->scache, LU_USERNAME),
2313
 
                                      "userBranch", USERBRANCH,
2314
 
                                      error);
 
2288
        primaries = lu_ldap_enumerate(module, "gidNumber", grp, "uid",
 
2289
                                      ctx->user_branch, error);
2315
2290
        if ((error == NULL) || (*error == NULL)) {
2316
 
                secondaries = lu_ldap_enumerate(module,
2317
 
                                                map_to_ldap(module->scache, LU_GROUPNAME),
2318
 
                                                group,
2319
 
                                                map_to_ldap(module->scache, LU_MEMBERNAME),
2320
 
                                                "groupBranch", GROUPBRANCH,
 
2291
                GValueArray *secondaries;
 
2292
 
 
2293
                secondaries = lu_ldap_enumerate(module, "cn", group,
 
2294
                                                "memberUid", ctx->group_branch,
2321
2295
                                                error);
2322
2296
                for (i = 0; i < secondaries->n_values; i++) {
2323
2297
                        value = g_value_array_get_nth(secondaries, i);
2357
2331
                                 uid_t uid,
2358
2332
                                 struct lu_error **error)
2359
2333
{
2360
 
        GValueArray *primaries = NULL, *secondaries = NULL, *values, *gids;
 
2334
        struct lu_ldap_context *ctx;
 
2335
        GValueArray *primaries, *gids;
2361
2336
        GValue *value;
2362
 
        size_t i, j;
2363
 
        gid_t gid;
2364
 
        struct lu_ent *ent = NULL;
 
2337
        size_t i;
2365
2338
 
2366
2339
        (void)uid;
2367
2340
        LU_ERROR_CHECK(error);
 
2341
        ctx = module->module_context;
2368
2342
 
2369
2343
        /* Create an array to hold the values returned. */
2370
2344
        primaries = g_value_array_new(0);
2371
2345
 
2372
2346
        /* Get the user's primary GID(s). */
2373
 
        gids = lu_ldap_enumerate(module,
2374
 
                                 map_to_ldap(module->scache, LU_USERNAME),
2375
 
                                 user,
2376
 
                                 map_to_ldap(module->scache, LU_GIDNUMBER),
2377
 
                                 "userBranch", USERBRANCH, error);
 
2347
        gids = lu_ldap_enumerate(module, "uid", user, "gidNumber",
 
2348
                                 ctx->user_branch, error);
2378
2349
        /* For each GID, look up the group.  Which has this GID. */
2379
2350
        for (i = 0; (gids != NULL) && (i < gids->n_values); i++) {
 
2351
                gid_t gid;
 
2352
                struct lu_ent *ent;
 
2353
 
2380
2354
                value = g_value_array_get_nth(gids, i);
2381
2355
                gid = lu_value_get_id(value);
2382
2356
                g_assert (gid != LU_VALUE_INVALID_ID);
2383
2357
                ent = lu_ent_new();
2384
2358
                if (lu_group_lookup_id(module->lu_context, gid,
2385
2359
                                       ent, error)) {
 
2360
                        GValueArray *values;
 
2361
                        size_t j;
 
2362
 
2386
2363
                        /* Get the group's names and add them to the list
2387
2364
                         * of values to return. */
2388
2365
                        values = lu_ent_get(ent, LU_GROUPNAME);
2397
2374
        /* Search for the supplemental groups which list this user as
2398
2375
         * a member. */
2399
2376
        if ((error == NULL) || (*error == NULL)) {
2400
 
                secondaries = lu_ldap_enumerate(module,
2401
 
                                                map_to_ldap(module->scache, LU_MEMBERNAME),
2402
 
                                                user,
2403
 
                                                map_to_ldap(module->scache, LU_GROUPNAME),
2404
 
                                                "groupBranch", GROUPBRANCH,
 
2377
                GValueArray *secondaries;
 
2378
 
 
2379
                secondaries = lu_ldap_enumerate(module, "memberUid", user,
 
2380
                                                "cn", ctx->group_branch,
2405
2381
                                                error);
2406
2382
                for (i = 0; i < secondaries->n_values; i++) {
2407
2383
                        value = g_value_array_get_nth(secondaries, i);
2442
2418
        g_assert(module != NULL);
2443
2419
 
2444
2420
        ctx = module->module_context;
2445
 
        ldap_unbind_s(ctx->ldap);
 
2421
        close_server(ctx->ldap);
2446
2422
 
2447
2423
        module->scache->free(module->scache);
2448
2424
        for (i = 0; i < sizeof(ctx->prompts) / sizeof(ctx->prompts[0]);
2471
2447
struct lu_module *
2472
2448
libuser_ldap_init(struct lu_context *context, struct lu_error **error)
2473
2449
{
2474
 
        struct lu_module *ret = NULL;
2475
 
        struct lu_ldap_context *ctx = NULL;
 
2450
        struct lu_module *ret;
 
2451
        struct lu_ldap_context *ctx;
2476
2452
        struct lu_prompt prompts[G_N_ELEMENTS(ctx->prompts)];
2477
2453
        char *user;
2478
2454
        const char *bind_type;
2479
2455
        char **bind_types;
2480
2456
        size_t i;
2481
 
        LDAP *ldap = NULL;
 
2457
        LDAP *ldap;
2482
2458
 
2483
2459
        g_assert(context != NULL);
2484
2460
        g_assert(context->prompter != NULL);
2583
2559
        ret->name = ret->scache->cache(ret->scache, "ldap");
2584
2560
        ctx->module = ret;
2585
2561
 
 
2562
        ctx->user_branch = lu_cfg_read_single(context, "ldap/userBranch",
 
2563
                                              USERBRANCH);
 
2564
        ctx->group_branch = lu_cfg_read_single(context, "ldap/groupBranch",
 
2565
                                               GROUPBRANCH);
 
2566
 
2586
2567
        /* Try to bind to the server to verify that we can. */
2587
2568
        ldap = bind_server(ctx, error);
2588
2569
        if (ldap == NULL) {
 
2570
                ret->scache->free(ret->scache);
2589
2571
                g_free(ret);
2590
2572
                g_free(ctx);
2591
2573
                return NULL;
2603
2585
                else
2604
2586
                        ctx->mapped_user_attributes[i] = NULL;
2605
2587
        }
2606
 
                        
 
2588
 
2607
2589
        ctx->mapped_group_attributes
2608
2590
                = g_malloc0(sizeof(*ctx->mapped_group_attributes)
2609
2591
                            * G_N_ELEMENTS(lu_ldap_group_attributes));