~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to nsswitch/libwbclient/wbc_util.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
   Unix SMB/CIFS implementation.
3
3
 
4
 
   Winbind client API
 
4
   Winbind client asynchronous API, utility functions
5
5
 
6
6
   Copyright (C) Gerald (Jerry) Carter 2007-2008
7
7
 
24
24
 
25
25
#include "replace.h"
26
26
#include "libwbclient.h"
27
 
 
28
 
 
 
27
#include "../winbind_client.h"
29
28
 
30
29
/** @brief Ping winbindd to see if the daemon is running
31
30
 *
32
31
 * @return #wbcErr
33
32
 **/
34
 
 
35
33
wbcErr wbcPing(void)
36
34
{
37
35
        struct winbindd_request request;
45
43
        return wbcRequestResponse(WINBINDD_PING, &request, &response);
46
44
}
47
45
 
 
46
static void wbcInterfaceDetailsDestructor(void *ptr)
 
47
{
 
48
        struct wbcInterfaceDetails *i = (struct wbcInterfaceDetails *)ptr;
 
49
        free(i->winbind_version);
 
50
        free(i->netbios_name);
 
51
        free(i->netbios_domain);
 
52
        free(i->dns_domain);
 
53
}
 
54
 
 
55
/**
 
56
 * @brief Query useful information about the winbind service
 
57
 *
 
58
 * @param *_details     pointer to hold the struct wbcInterfaceDetails
 
59
 *
 
60
 * @return #wbcErr
 
61
 */
 
62
 
48
63
wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
49
64
{
50
65
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
58
73
        ZERO_STRUCT(request);
59
74
        ZERO_STRUCT(response);
60
75
 
61
 
        info = talloc(NULL, struct wbcInterfaceDetails);
 
76
        info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
 
77
                1, sizeof(struct wbcInterfaceDetails),
 
78
                wbcInterfaceDetailsDestructor);
62
79
        BAIL_ON_PTR_ERROR(info, wbc_status);
63
80
 
64
81
        /* first the interface version */
70
87
        wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
71
88
        BAIL_ON_WBC_ERROR(wbc_status);
72
89
 
73
 
        info->winbind_version = talloc_strdup(info,
74
 
                                              response.data.info.samba_version);
 
90
        info->winbind_version = strdup(response.data.info.samba_version);
75
91
        BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
76
92
        info->winbind_separator = response.data.info.winbind_separator;
77
93
 
79
95
        wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
80
96
        BAIL_ON_WBC_ERROR(wbc_status);
81
97
 
82
 
        info->netbios_name = talloc_strdup(info,
83
 
                                           response.data.netbios_name);
 
98
        info->netbios_name = strdup(response.data.netbios_name);
84
99
        BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);
85
100
 
86
101
        /* then the local workgroup name */
87
102
        wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
88
103
        BAIL_ON_WBC_ERROR(wbc_status);
89
104
 
90
 
        info->netbios_domain = talloc_strdup(info,
91
 
                                        response.data.domain_name);
 
105
        info->netbios_domain = strdup(response.data.domain_name);
92
106
        BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);
93
107
 
94
108
        wbc_status = wbcDomainInfo(info->netbios_domain, &domain);
101
115
        }
102
116
 
103
117
        if (domain) {
104
 
                info->dns_domain = talloc_strdup(info,
105
 
                                                 domain->dns_name);
 
118
                info->dns_domain = strdup(domain->dns_name);
106
119
                wbcFreeMemory(domain);
107
120
                BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
108
121
        } else {
115
128
        wbc_status = WBC_ERR_SUCCESS;
116
129
 
117
130
done:
118
 
        talloc_free(info);
 
131
        wbcFreeMemory(info);
119
132
        return wbc_status;
120
133
}
121
134
 
122
 
 
123
 
/* Lookup the current status of a trusted domain */
 
135
static void wbcDomainInfoDestructor(void *ptr)
 
136
{
 
137
        struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
 
138
        free(i->short_name);
 
139
        free(i->dns_name);
 
140
}
 
141
 
 
142
/** @brief Lookup the current status of a trusted domain, sync wrapper
 
143
 *
 
144
 * @param domain      Domain to query
 
145
 * @param *dinfo       Pointer to returned struct wbcDomainInfo
 
146
 *
 
147
 * @return #wbcErr
 
148
 */
 
149
 
124
150
wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
125
151
{
126
152
        struct winbindd_request request;
146
172
                                        &response);
147
173
        BAIL_ON_WBC_ERROR(wbc_status);
148
174
 
149
 
        info = talloc(NULL, struct wbcDomainInfo);
 
175
        info = (struct wbcDomainInfo *)wbcAllocateMemory(
 
176
                1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
150
177
        BAIL_ON_PTR_ERROR(info, wbc_status);
151
178
 
152
 
        info->short_name = talloc_strdup(info,
153
 
                                         response.data.domain_info.name);
 
179
        info->short_name = strdup(response.data.domain_info.name);
154
180
        BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
155
181
 
156
 
        info->dns_name = talloc_strdup(info,
157
 
                                       response.data.domain_info.alt_name);
 
182
        info->dns_name = strdup(response.data.domain_info.alt_name);
158
183
        BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
159
184
 
160
185
        wbc_status = wbcStringToSid(response.data.domain_info.sid,
169
194
                info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
170
195
 
171
196
        *dinfo = info;
 
197
        info = NULL;
172
198
 
173
199
        wbc_status = WBC_ERR_SUCCESS;
174
200
 
175
201
 done:
176
 
        if (!WBC_ERROR_IS_OK(wbc_status)) {
177
 
                talloc_free(info);
178
 
        }
179
 
 
180
 
        return wbc_status;
181
 
}
182
 
 
 
202
        wbcFreeMemory(info);
 
203
        return wbc_status;
 
204
}
 
205
 
 
206
/* Get the list of current DCs */
 
207
wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
 
208
                 const char ***dc_names, const char ***dc_ips)
 
209
{
 
210
        struct winbindd_request request;
 
211
        struct winbindd_response response;
 
212
        const char **names = NULL;
 
213
        const char **ips = NULL;
 
214
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 
215
        size_t extra_len;
 
216
        int i;
 
217
        char *p;
 
218
 
 
219
        /* Initialise request */
 
220
 
 
221
        ZERO_STRUCT(request);
 
222
        ZERO_STRUCT(response);
 
223
 
 
224
        if (domain != NULL) {
 
225
                strncpy(request.domain_name, domain,
 
226
                        sizeof(request.domain_name) - 1);
 
227
        }
 
228
 
 
229
        wbc_status = wbcRequestResponse(WINBINDD_DC_INFO,
 
230
                                        &request, &response);
 
231
        BAIL_ON_WBC_ERROR(wbc_status);
 
232
 
 
233
        names = wbcAllocateStringArray(response.data.num_entries);
 
234
        BAIL_ON_PTR_ERROR(names, wbc_status);
 
235
 
 
236
        ips = wbcAllocateStringArray(response.data.num_entries);
 
237
        BAIL_ON_PTR_ERROR(ips, wbc_status);
 
238
 
 
239
        wbc_status = WBC_ERR_INVALID_RESPONSE;
 
240
 
 
241
        p = (char *)response.extra_data.data;
 
242
 
 
243
        if (response.length < (sizeof(struct winbindd_response)+1)) {
 
244
                goto done;
 
245
        }
 
246
 
 
247
        extra_len = response.length - sizeof(struct winbindd_response);
 
248
 
 
249
        if (p[extra_len-1] != '\0') {
 
250
                goto done;
 
251
        }
 
252
 
 
253
        for (i=0; i<response.data.num_entries; i++) {
 
254
                char *q;
 
255
 
 
256
                q = strchr(p, '\n');
 
257
                if (q == NULL) {
 
258
                        goto done;
 
259
                }
 
260
                names[i] = strndup(p, q-p);
 
261
                BAIL_ON_PTR_ERROR(names[i], wbc_status);
 
262
                p = q+1;
 
263
 
 
264
                q = strchr(p, '\n');
 
265
                if (q == NULL) {
 
266
                        goto done;
 
267
                }
 
268
                ips[i] = strndup(p, q-p);
 
269
                BAIL_ON_PTR_ERROR(ips[i], wbc_status);
 
270
                p = q+1;
 
271
        }
 
272
        if (p[0] != '\0') {
 
273
                goto done;
 
274
        }
 
275
 
 
276
        wbc_status = WBC_ERR_SUCCESS;
 
277
done:
 
278
        if (response.extra_data.data)
 
279
                free(response.extra_data.data);
 
280
 
 
281
        if (WBC_ERROR_IS_OK(wbc_status)) {
 
282
                *num_dcs = response.data.num_entries;
 
283
                *dc_names = names;
 
284
                names = NULL;
 
285
                *dc_ips = ips;
 
286
                ips = NULL;
 
287
        }
 
288
        wbcFreeMemory(names);
 
289
        wbcFreeMemory(ips);
 
290
        return wbc_status;
 
291
}
183
292
 
184
293
/* Resolve a NetbiosName via WINS */
185
294
wbcErr wbcResolveWinsByName(const char *name, char **ip)
204
313
 
205
314
        /* Display response */
206
315
 
207
 
        ipaddr = talloc_strdup(NULL, response.data.winsresp);
 
316
        ipaddr = wbcStrDup(response.data.winsresp);
208
317
        BAIL_ON_PTR_ERROR(ipaddr, wbc_status);
209
318
 
210
319
        *ip = ipaddr;
237
346
 
238
347
        /* Display response */
239
348
 
240
 
        name_str = talloc_strdup(NULL, response.data.winsresp);
 
349
        name_str = wbcStrDup(response.data.winsresp);
241
350
        BAIL_ON_PTR_ERROR(name_str, wbc_status);
242
351
 
243
352
        *name = name_str;
250
359
/**
251
360
 */
252
361
 
253
 
static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
254
 
                                         struct wbcDomainInfo *info,
 
362
static wbcErr process_domain_info_string(struct wbcDomainInfo *info,
255
363
                                         char *info_string)
256
364
{
257
365
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
258
366
        char *r = NULL;
259
367
        char *s = NULL;
260
368
 
261
 
        if (!info || !info_string) {
262
 
                wbc_status = WBC_ERR_INVALID_PARAM;
263
 
                BAIL_ON_WBC_ERROR(wbc_status);
264
 
        }
265
 
 
266
 
        ZERO_STRUCTP(info);
267
 
 
268
369
        r = info_string;
269
370
 
270
371
        /* Short Name */
275
376
        *s = '\0';
276
377
        s++;
277
378
 
278
 
        info->short_name = talloc_strdup(ctx, r);
 
379
        info->short_name = strdup(r);
279
380
        BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
280
381
 
281
382
 
288
389
        *s = '\0';
289
390
        s++;
290
391
 
291
 
        info->dns_name = talloc_strdup(ctx, r);
 
392
        info->dns_name = strdup(r);
292
393
        BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
293
394
 
294
395
        /* SID */
381
482
        return wbc_status;
382
483
}
383
484
 
 
485
static void wbcDomainInfoListDestructor(void *ptr)
 
486
{
 
487
        struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
 
488
 
 
489
        while (i->short_name != NULL) {
 
490
                free(i->short_name);
 
491
                free(i->dns_name);
 
492
                i += 1;
 
493
        }
 
494
}
 
495
 
384
496
/* Enumerate the domain trusts known by Winbind */
385
497
wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
386
498
{
387
499
        struct winbindd_response response;
388
500
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
389
501
        char *p = NULL;
390
 
        char *q = NULL;
391
502
        char *extra_data = NULL;
392
 
        int count = 0;
393
503
        struct wbcDomainInfo *d_list = NULL;
394
504
        int i = 0;
395
505
 
417
527
                BAIL_ON_WBC_ERROR(wbc_status);
418
528
        }
419
529
 
420
 
        /* Count number of domains */
421
 
 
422
 
        count = 0;
423
 
        while (p) {
424
 
                count++;
425
 
 
426
 
                if ((q = strchr(p, '\n')) != NULL)
427
 
                        q++;
428
 
                p = q;
429
 
        }
430
 
 
431
 
        d_list = talloc_array(NULL, struct wbcDomainInfo, count);
 
530
        d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
 
531
                response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
 
532
                wbcDomainInfoListDestructor);
432
533
        BAIL_ON_PTR_ERROR(d_list, wbc_status);
433
534
 
434
535
        extra_data = strdup((char*)response.extra_data.data);
438
539
 
439
540
        /* Outer loop processes the list of domain information */
440
541
 
441
 
        for (i=0; i<count && p; i++) {
 
542
        for (i=0; i<response.data.num_entries && p; i++) {
442
543
                char *next = strchr(p, '\n');
443
544
 
444
545
                if (next) {
446
547
                        next++;
447
548
                }
448
549
 
449
 
                wbc_status = process_domain_info_string(d_list, &d_list[i], p);
 
550
                wbc_status = process_domain_info_string(&d_list[i], p);
450
551
                BAIL_ON_WBC_ERROR(wbc_status);
451
552
 
452
553
                p = next;
453
554
        }
454
555
 
455
556
        *domains = d_list;
 
557
        d_list = NULL;
456
558
        *num_domains = i;
457
559
 
458
560
 done:
459
 
        if (!WBC_ERROR_IS_OK(wbc_status)) {
460
 
                if (d_list)
461
 
                        talloc_free(d_list);
462
 
                if (extra_data)
463
 
                        free(extra_data);
464
 
        }
465
 
 
 
561
        winbindd_free_response(&response);
 
562
        wbcFreeMemory(d_list);
 
563
        free(extra_data);
466
564
        return wbc_status;
467
565
}
468
566
 
 
567
static void wbcDomainControllerInfoDestructor(void *ptr)
 
568
{
 
569
        struct wbcDomainControllerInfo *i =
 
570
                (struct wbcDomainControllerInfo *)ptr;
 
571
        free(i->dc_name);
 
572
}
 
573
 
469
574
/* Enumerate the domain trusts known by Winbind */
470
575
wbcErr wbcLookupDomainController(const char *domain,
471
576
                                 uint32_t flags,
491
596
 
492
597
        request.flags = flags;
493
598
 
494
 
        dc = talloc(NULL, struct wbcDomainControllerInfo);
 
599
        dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
 
600
                 1, sizeof(struct wbcDomainControllerInfo),
 
601
                wbcDomainControllerInfoDestructor);
495
602
        BAIL_ON_PTR_ERROR(dc, wbc_status);
496
603
 
497
604
        /* Send request */
501
608
                                        &response);
502
609
        BAIL_ON_WBC_ERROR(wbc_status);
503
610
 
504
 
        dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
 
611
        dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
505
612
        BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
506
613
 
507
614
        *dc_info = dc;
 
615
        dc = NULL;
508
616
 
509
617
done:
510
 
        if (!WBC_ERROR_IS_OK(wbc_status)) {
511
 
                talloc_free(dc);
512
 
        }
513
 
 
 
618
        wbcFreeMemory(dc);
514
619
        return wbc_status;
515
620
}
516
621
 
517
 
static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
518
 
                                                   const struct winbindd_response *resp,
 
622
static void wbcDomainControllerInfoExDestructor(void *ptr)
 
623
{
 
624
        struct wbcDomainControllerInfoEx *i =
 
625
                (struct wbcDomainControllerInfoEx *)ptr;
 
626
        free((char *)(i->dc_unc));
 
627
        free((char *)(i->dc_address));
 
628
        free((char *)(i->domain_guid));
 
629
        free((char *)(i->domain_name));
 
630
        free((char *)(i->forest_name));
 
631
        free((char *)(i->dc_site_name));
 
632
        free((char *)(i->client_site_name));
 
633
}
 
634
 
 
635
static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
519
636
                                                   struct wbcDomainControllerInfoEx **_i)
520
637
{
521
638
        wbcErr wbc_status = WBC_ERR_SUCCESS;
522
639
        struct wbcDomainControllerInfoEx *i;
523
640
        struct wbcGuid guid;
524
641
 
525
 
        i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
 
642
        i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
 
643
                1, sizeof(struct wbcDomainControllerInfoEx),
 
644
                wbcDomainControllerInfoExDestructor);
526
645
        BAIL_ON_PTR_ERROR(i, wbc_status);
527
646
 
528
 
        i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
 
647
        i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
529
648
        BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
530
649
 
531
 
        i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
 
650
        i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
532
651
        BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
533
652
 
534
653
        i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
535
654
 
536
655
        wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
537
656
        if (WBC_ERROR_IS_OK(wbc_status)) {
538
 
                i->domain_guid = talloc(i, struct wbcGuid);
 
657
                i->domain_guid = (struct wbcGuid *)malloc(
 
658
                        sizeof(struct wbcGuid));
539
659
                BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
540
660
 
541
661
                *i->domain_guid = guid;
542
 
        } else {
543
 
                i->domain_guid = NULL;
544
662
        }
545
663
 
546
 
        i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
 
664
        i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
547
665
        BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
548
666
 
549
667
        if (resp->data.dsgetdcname.forest_name[0] != '\0') {
550
 
                i->forest_name = talloc_strdup(i,
551
 
                        resp->data.dsgetdcname.forest_name);
 
668
                i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
552
669
                BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
553
 
        } else {
554
 
                i->forest_name = NULL;
555
670
        }
556
671
 
557
672
        i->dc_flags = resp->data.dsgetdcname.dc_flags;
558
673
 
559
674
        if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
560
 
                i->dc_site_name = talloc_strdup(i,
561
 
                        resp->data.dsgetdcname.dc_site_name);
 
675
                i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
562
676
                BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
563
 
        } else {
564
 
                i->dc_site_name = NULL;
565
677
        }
566
678
 
567
679
        if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
568
 
                i->client_site_name = talloc_strdup(i,
 
680
                i->client_site_name = strdup(
569
681
                        resp->data.dsgetdcname.client_site_name);
570
682
                BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
571
 
        } else {
572
 
                i->client_site_name = NULL;
573
683
        }
574
684
 
575
685
        *_i = i;
576
686
        i = NULL;
577
687
 
578
688
done:
579
 
        talloc_free(i);
 
689
        if (i != NULL) {
 
690
                wbcFreeMemory(i);
 
691
        }
580
692
        return wbc_status;
581
693
}
582
694
 
631
743
        BAIL_ON_WBC_ERROR(wbc_status);
632
744
 
633
745
        if (dc_info) {
634
 
                wbc_status = wbc_create_domain_controller_info_ex(NULL,
635
 
                                                                  &response,
 
746
                wbc_status = wbc_create_domain_controller_info_ex(&response,
636
747
                                                                  dc_info);
637
748
                BAIL_ON_WBC_ERROR(wbc_status);
638
749
        }
642
753
        return wbc_status;
643
754
}
644
755
 
 
756
static void wbcNamedBlobDestructor(void *ptr)
 
757
{
 
758
        struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
 
759
 
 
760
        while (b->name != NULL) {
 
761
                free((char *)(b->name));
 
762
                free(b->blob.data);
 
763
                b += 1;
 
764
        }
 
765
}
 
766
 
645
767
/* Initialize a named blob and add to list of blobs */
646
768
wbcErr wbcAddNamedBlob(size_t *num_blobs,
647
 
                       struct wbcNamedBlob **blobs,
 
769
                       struct wbcNamedBlob **pblobs,
648
770
                       const char *name,
649
771
                       uint32_t flags,
650
772
                       uint8_t *data,
651
773
                       size_t length)
652
774
{
653
775
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
654
 
        struct wbcNamedBlob blob;
655
 
 
656
 
        *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
657
 
                                *(num_blobs)+1);
658
 
        BAIL_ON_PTR_ERROR(*blobs, wbc_status);
659
 
 
660
 
        blob.name               = talloc_strdup(*blobs, name);
661
 
        BAIL_ON_PTR_ERROR(blob.name, wbc_status);
662
 
        blob.flags              = flags;
663
 
        blob.blob.length        = length;
664
 
        blob.blob.data          = (uint8_t *)talloc_memdup(*blobs, data, length);
665
 
        BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
666
 
 
667
 
        (*(blobs))[*num_blobs] = blob;
668
 
        *(num_blobs) += 1;
 
776
        struct wbcNamedBlob *blobs, *blob;
 
777
 
 
778
        if (name == NULL) {
 
779
                return WBC_ERR_INVALID_PARAM;
 
780
        }
 
781
 
 
782
        /*
 
783
         * Overallocate the b->name==NULL terminator for
 
784
         * wbcNamedBlobDestructor
 
785
         */
 
786
        blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
 
787
                *num_blobs + 2, sizeof(struct wbcNamedBlob),
 
788
                wbcNamedBlobDestructor);
 
789
 
 
790
        if (blobs == NULL) {
 
791
                return WBC_ERR_NO_MEMORY;
 
792
        }
 
793
 
 
794
        if (*pblobs != NULL) {
 
795
                struct wbcNamedBlob *old = *pblobs;
 
796
                memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
 
797
                if (*num_blobs != 0) {
 
798
                        /* end indicator for wbcNamedBlobDestructor */
 
799
                        old[0].name = NULL;
 
800
                }
 
801
                wbcFreeMemory(old);
 
802
        }
 
803
        *pblobs = blobs;
 
804
 
 
805
        blob = &blobs[*num_blobs];
 
806
 
 
807
        blob->name = strdup(name);
 
808
        BAIL_ON_PTR_ERROR(blob->name, wbc_status);
 
809
        blob->flags = flags;
 
810
 
 
811
        blob->blob.length = length;
 
812
        blob->blob.data = (uint8_t *)malloc(length);
 
813
        BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
 
814
        memcpy(blob->blob.data, data, length);
 
815
 
 
816
        *num_blobs += 1;
 
817
        *pblobs = blobs;
 
818
        blobs = NULL;
669
819
 
670
820
        wbc_status = WBC_ERR_SUCCESS;
671
821
done:
672
 
        if (!WBC_ERROR_IS_OK(wbc_status) && blobs) {
673
 
                wbcFreeMemory(*blobs);
674
 
        }
 
822
        wbcFreeMemory(blobs);
675
823
        return wbc_status;
676
824
}