lsa: lsa_CreateTrustedDomainEx takes lsa_TrustDomainInfoAuthInfo, not
[samba.git] / nsswitch / libwbclient / wbc_util.c
index 38fd1c555928286949f28d19be58bafb68c972c1..af134ba7e5b410abb0c5388507704687c0e8794b 100644 (file)
@@ -74,7 +74,7 @@ wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
        ZERO_STRUCT(response);
 
        info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
-               sizeof(struct wbcInterfaceDetails), 1,
+               1, sizeof(struct wbcInterfaceDetails),
                wbcInterfaceDetailsDestructor);
        BAIL_ON_PTR_ERROR(info, wbc_status);
 
@@ -173,7 +173,7 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
        BAIL_ON_WBC_ERROR(wbc_status);
 
        info = (struct wbcDomainInfo *)wbcAllocateMemory(
-               sizeof(struct wbcDomainInfo), 1, wbcDomainInfoDestructor);
+               1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
        BAIL_ON_PTR_ERROR(info, wbc_status);
 
        info->short_name = strdup(response.data.domain_info.name);
@@ -203,6 +203,92 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
        return wbc_status;
 }
 
+/* Get the list of current DCs */
+wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
+                const char ***dc_names, const char ***dc_ips)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       const char **names = NULL;
+       const char **ips = NULL;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       size_t extra_len;
+       int i;
+       char *p;
+
+       /* Initialise request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       if (domain != NULL) {
+               strncpy(request.domain_name, domain,
+                       sizeof(request.domain_name) - 1);
+       }
+
+       wbc_status = wbcRequestResponse(WINBINDD_DC_INFO,
+                                       &request, &response);
+       BAIL_ON_WBC_ERROR(wbc_status);
+
+       names = wbcAllocateStringArray(response.data.num_entries);
+       BAIL_ON_PTR_ERROR(names, wbc_status);
+
+       ips = wbcAllocateStringArray(response.data.num_entries);
+       BAIL_ON_PTR_ERROR(ips, wbc_status);
+
+       wbc_status = WBC_ERR_INVALID_RESPONSE;
+
+       p = (char *)response.extra_data.data;
+
+       if (response.length < (sizeof(struct winbindd_response)+1)) {
+               goto done;
+       }
+
+       extra_len = response.length - sizeof(struct winbindd_response);
+
+       if (p[extra_len-1] != '\0') {
+               goto done;
+       }
+
+       for (i=0; i<response.data.num_entries; i++) {
+               char *q;
+
+               q = strchr(p, '\n');
+               if (q == NULL) {
+                       goto done;
+               }
+               names[i] = strndup(p, q-p);
+               BAIL_ON_PTR_ERROR(names[i], wbc_status);
+               p = q+1;
+
+               q = strchr(p, '\n');
+               if (q == NULL) {
+                       goto done;
+               }
+               ips[i] = strndup(p, q-p);
+               BAIL_ON_PTR_ERROR(ips[i], wbc_status);
+               p = q+1;
+       }
+       if (p[0] != '\0') {
+               goto done;
+       }
+
+        wbc_status = WBC_ERR_SUCCESS;
+done:
+       if (response.extra_data.data)
+               free(response.extra_data.data);
+
+       if (WBC_ERROR_IS_OK(wbc_status)) {
+               *num_dcs = response.data.num_entries;
+               *dc_names = names;
+               names = NULL;
+               *dc_ips = ips;
+               ips = NULL;
+       }
+       wbcFreeMemory(names);
+       wbcFreeMemory(ips);
+       return wbc_status;
+}
 
 /* Resolve a NetbiosName via WINS */
 wbcErr wbcResolveWinsByName(const char *name, char **ip)
@@ -260,7 +346,7 @@ wbcErr wbcResolveWinsByIP(const char *ip, char **name)
 
        /* Display response */
 
-       name_str = talloc_strdup(NULL, response.data.winsresp);
+       name_str = wbcStrDup(response.data.winsresp);
        BAIL_ON_PTR_ERROR(name_str, wbc_status);
 
        *name = name_str;
@@ -273,21 +359,13 @@ wbcErr wbcResolveWinsByIP(const char *ip, char **name)
 /**
  */
 
-static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
-                                        struct wbcDomainInfo *info,
+static wbcErr process_domain_info_string(struct wbcDomainInfo *info,
                                         char *info_string)
 {
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
        char *r = NULL;
        char *s = NULL;
 
-       if (!info || !info_string) {
-               wbc_status = WBC_ERR_INVALID_PARAM;
-               BAIL_ON_WBC_ERROR(wbc_status);
-       }
-
-       ZERO_STRUCTP(info);
-
        r = info_string;
 
        /* Short Name */
@@ -298,7 +376,7 @@ static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
        *s = '\0';
        s++;
 
-       info->short_name = talloc_strdup(ctx, r);
+       info->short_name = strdup(r);
        BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
 
 
@@ -311,7 +389,7 @@ static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
        *s = '\0';
        s++;
 
-       info->dns_name = talloc_strdup(ctx, r);
+       info->dns_name = strdup(r);
        BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
 
        /* SID */
@@ -404,15 +482,24 @@ static wbcErr process_domain_info_string(TALLOC_CTX *ctx,
        return wbc_status;
 }
 
+static void wbcDomainInfoListDestructor(void *ptr)
+{
+       struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
+
+       while (i->short_name != NULL) {
+               free(i->short_name);
+               free(i->dns_name);
+               i += 1;
+       }
+}
+
 /* Enumerate the domain trusts known by Winbind */
 wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
 {
        struct winbindd_response response;
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
        char *p = NULL;
-       char *q = NULL;
        char *extra_data = NULL;
-       int count = 0;
        struct wbcDomainInfo *d_list = NULL;
        int i = 0;
 
@@ -440,18 +527,9 @@ wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
                BAIL_ON_WBC_ERROR(wbc_status);
        }
 
-       /* Count number of domains */
-
-       count = 0;
-       while (p) {
-               count++;
-
-               if ((q = strchr(p, '\n')) != NULL)
-                       q++;
-               p = q;
-       }
-
-       d_list = talloc_array(NULL, struct wbcDomainInfo, count);
+       d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
+               response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
+               wbcDomainInfoListDestructor);
        BAIL_ON_PTR_ERROR(d_list, wbc_status);
 
        extra_data = strdup((char*)response.extra_data.data);
@@ -461,7 +539,7 @@ wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
 
        /* Outer loop processes the list of domain information */
 
-       for (i=0; i<count && p; i++) {
+       for (i=0; i<response.data.num_entries && p; i++) {
                char *next = strchr(p, '\n');
 
                if (next) {
@@ -469,7 +547,7 @@ wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
                        next++;
                }
 
-               wbc_status = process_domain_info_string(d_list, &d_list[i], p);
+               wbc_status = process_domain_info_string(&d_list[i], p);
                BAIL_ON_WBC_ERROR(wbc_status);
 
                p = next;
@@ -481,11 +559,18 @@ wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
 
  done:
        winbindd_free_response(&response);
-       talloc_free(d_list);
+       wbcFreeMemory(d_list);
        free(extra_data);
        return wbc_status;
 }
 
+static void wbcDomainControllerInfoDestructor(void *ptr)
+{
+       struct wbcDomainControllerInfo *i =
+               (struct wbcDomainControllerInfo *)ptr;
+       free(i->dc_name);
+}
+
 /* Enumerate the domain trusts known by Winbind */
 wbcErr wbcLookupDomainController(const char *domain,
                                 uint32_t flags,
@@ -511,7 +596,9 @@ wbcErr wbcLookupDomainController(const char *domain,
 
        request.flags = flags;
 
-       dc = talloc(NULL, struct wbcDomainControllerInfo);
+       dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
+                1, sizeof(struct wbcDomainControllerInfo),
+               wbcDomainControllerInfoDestructor);
        BAIL_ON_PTR_ERROR(dc, wbc_status);
 
        /* Send request */
@@ -521,82 +608,87 @@ wbcErr wbcLookupDomainController(const char *domain,
                                        &response);
        BAIL_ON_WBC_ERROR(wbc_status);
 
-       dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
+       dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
        BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
 
        *dc_info = dc;
+       dc = NULL;
 
 done:
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               talloc_free(dc);
-       }
-
+       wbcFreeMemory(dc);
        return wbc_status;
 }
 
-static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx,
-                                                  const struct winbindd_response *resp,
+static void wbcDomainControllerInfoExDestructor(void *ptr)
+{
+       struct wbcDomainControllerInfoEx *i =
+               (struct wbcDomainControllerInfoEx *)ptr;
+       free(discard_const_p(char, i->dc_unc));
+       free(discard_const_p(char, i->dc_address));
+       free(discard_const_p(char, i->domain_guid));
+       free(discard_const_p(char, i->domain_name));
+       free(discard_const_p(char, i->forest_name));
+       free(discard_const_p(char, i->dc_site_name));
+       free(discard_const_p(char, i->client_site_name));
+}
+
+static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
                                                   struct wbcDomainControllerInfoEx **_i)
 {
        wbcErr wbc_status = WBC_ERR_SUCCESS;
        struct wbcDomainControllerInfoEx *i;
        struct wbcGuid guid;
 
-       i = talloc(mem_ctx, struct wbcDomainControllerInfoEx);
+       i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
+               1, sizeof(struct wbcDomainControllerInfoEx),
+               wbcDomainControllerInfoExDestructor);
        BAIL_ON_PTR_ERROR(i, wbc_status);
 
-       i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc);
+       i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
        BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);
 
-       i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address);
+       i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
        BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);
 
        i->dc_address_type = resp->data.dsgetdcname.dc_address_type;
 
        wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
        if (WBC_ERROR_IS_OK(wbc_status)) {
-               i->domain_guid = talloc(i, struct wbcGuid);
+               i->domain_guid = (struct wbcGuid *)malloc(
+                       sizeof(struct wbcGuid));
                BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);
 
                *i->domain_guid = guid;
-       } else {
-               i->domain_guid = NULL;
        }
 
-       i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name);
+       i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
        BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
 
        if (resp->data.dsgetdcname.forest_name[0] != '\0') {
-               i->forest_name = talloc_strdup(i,
-                       resp->data.dsgetdcname.forest_name);
+               i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
                BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
-       } else {
-               i->forest_name = NULL;
        }
 
        i->dc_flags = resp->data.dsgetdcname.dc_flags;
 
        if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
-               i->dc_site_name = talloc_strdup(i,
-                       resp->data.dsgetdcname.dc_site_name);
+               i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
                BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
-       } else {
-               i->dc_site_name = NULL;
        }
 
        if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
-               i->client_site_name = talloc_strdup(i,
+               i->client_site_name = strdup(
                        resp->data.dsgetdcname.client_site_name);
                BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
-       } else {
-               i->client_site_name = NULL;
        }
 
        *_i = i;
        i = NULL;
 
 done:
-       talloc_free(i);
+       if (i != NULL) {
+               wbcFreeMemory(i);
+       }
        return wbc_status;
 }
 
@@ -651,8 +743,7 @@ wbcErr wbcLookupDomainControllerEx(const char *domain,
        BAIL_ON_WBC_ERROR(wbc_status);
 
        if (dc_info) {
-               wbc_status = wbc_create_domain_controller_info_ex(NULL,
-                                                                 &response,
+               wbc_status = wbc_create_domain_controller_info_ex(&response,
                                                                  dc_info);
                BAIL_ON_WBC_ERROR(wbc_status);
        }
@@ -662,35 +753,72 @@ done:
        return wbc_status;
 }
 
+static void wbcNamedBlobDestructor(void *ptr)
+{
+       struct wbcNamedBlob *b = (struct wbcNamedBlob *)ptr;
+
+       while (b->name != NULL) {
+               free(discard_const_p(char, b->name));
+               free(b->blob.data);
+               b += 1;
+       }
+}
+
 /* Initialize a named blob and add to list of blobs */
 wbcErr wbcAddNamedBlob(size_t *num_blobs,
-                      struct wbcNamedBlob **blobs,
+                      struct wbcNamedBlob **pblobs,
                       const char *name,
                       uint32_t flags,
                       uint8_t *data,
                       size_t length)
 {
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
-       struct wbcNamedBlob blob;
+       struct wbcNamedBlob *blobs, *blob;
 
-       *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob,
-                               *(num_blobs)+1);
-       BAIL_ON_PTR_ERROR(*blobs, wbc_status);
+       if (name == NULL) {
+               return WBC_ERR_INVALID_PARAM;
+       }
 
-       blob.name               = talloc_strdup(*blobs, name);
-       BAIL_ON_PTR_ERROR(blob.name, wbc_status);
-       blob.flags              = flags;
-       blob.blob.length        = length;
-       blob.blob.data          = (uint8_t *)talloc_memdup(*blobs, data, length);
-       BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status);
+       /*
+        * Overallocate the b->name==NULL terminator for
+        * wbcNamedBlobDestructor
+        */
+       blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
+               *num_blobs + 2, sizeof(struct wbcNamedBlob),
+               wbcNamedBlobDestructor);
 
-       (*(blobs))[*num_blobs] = blob;
-       *(num_blobs) += 1;
+       if (blobs == NULL) {
+               return WBC_ERR_NO_MEMORY;
+       }
+
+       if (*pblobs != NULL) {
+               struct wbcNamedBlob *old = *pblobs;
+               memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
+               if (*num_blobs != 0) {
+                       /* end indicator for wbcNamedBlobDestructor */
+                       old[0].name = NULL;
+               }
+               wbcFreeMemory(old);
+       }
+       *pblobs = blobs;
+
+       blob = &blobs[*num_blobs];
+
+       blob->name = strdup(name);
+       BAIL_ON_PTR_ERROR(blob->name, wbc_status);
+       blob->flags = flags;
+
+       blob->blob.length = length;
+       blob->blob.data = (uint8_t *)malloc(length);
+       BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
+       memcpy(blob->blob.data, data, length);
+
+       *num_blobs += 1;
+       *pblobs = blobs;
+       blobs = NULL;
 
        wbc_status = WBC_ERR_SUCCESS;
 done:
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               wbcFreeMemory(*blobs);
-       }
+       wbcFreeMemory(blobs);
        return wbc_status;
 }