/* Convert a SID to a domain and name */ wbcErr wbcLookupSid(const struct wbcDomainSid *sid, char **pdomain, char **pname, enum wbcSidType *pname_type) { struct winbindd_request request; struct winbindd_response response; wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; char *domain, *name; if (!sid) { return WBC_ERR_INVALID_PARAM; } /* Initialize request */ ZERO_STRUCT(request); ZERO_STRUCT(response); wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid)); /* Make request */ wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID, &request, &response); if (!WBC_ERROR_IS_OK(wbc_status)) { return wbc_status; } /* Copy out result */ wbc_status = WBC_ERR_NO_MEMORY; domain = NULL; name = NULL; domain = wbcStrDup(response.data.name.dom_name); if (domain == NULL) { goto done; } name = wbcStrDup(response.data.name.name); if (name == NULL) { goto done; } if (pdomain != NULL) { *pdomain = domain; domain = NULL; } if (pname != NULL) { *pname = name; name = NULL; } if (pname_type != NULL) { *pname_type = (enum wbcSidType)response.data.name.type; } wbc_status = WBC_ERR_SUCCESS; done: wbcFreeMemory(name); wbcFreeMemory(domain); return wbc_status; }
/* Resolve an IP address via WINS into a NetbiosName */ wbcErr wbcResolveWinsByIP(const char *ip, char **name) { struct winbindd_request request; struct winbindd_response response; wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; char *name_str; ZERO_STRUCT(request); ZERO_STRUCT(response); /* Send request */ strncpy(request.data.winsreq, ip, sizeof(request.data.winsreq)-1); wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP, &request, &response); BAIL_ON_WBC_ERROR(wbc_status); /* Display response */ name_str = wbcStrDup(response.data.winsresp); BAIL_ON_PTR_ERROR(name_str, wbc_status); *name = name_str; wbc_status = WBC_ERR_SUCCESS; done: return wbc_status; }
wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid, char **pdomain, char **pfullname, enum wbcSidType *pname_type) { wbcErr wbc_status; char *domain = NULL; char *name = NULL; enum wbcSidType name_type; wbc_status = wbcLookupSid(sid, &domain, &name, &name_type); BAIL_ON_WBC_ERROR(wbc_status); if (name_type == WBC_SID_NAME_USER) { uid_t uid; struct passwd *pwd; wbc_status = wbcSidToUid(sid, &uid); BAIL_ON_WBC_ERROR(wbc_status); wbc_status = wbcGetpwuid(uid, &pwd); BAIL_ON_WBC_ERROR(wbc_status); wbcFreeMemory(name); name = wbcStrDup(pwd->pw_gecos); wbcFreeMemory(pwd); BAIL_ON_PTR_ERROR(name, wbc_status); } wbc_status = WBC_ERR_SUCCESS; done: if (WBC_ERROR_IS_OK(wbc_status)) { *pdomain = domain; *pfullname = name; *pname_type = name_type; } else { wbcFreeMemory(domain); wbcFreeMemory(name); } return wbc_status; }
wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid, int num_rids, uint32_t *rids, const char **pp_domain_name, const char ***pnames, enum wbcSidType **ptypes) { size_t i, len, ridbuf_size; char *ridlist; char *p; struct winbindd_request request; struct winbindd_response response; char *domain_name = NULL; const char **names = NULL; enum wbcSidType *types = NULL; wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; /* Initialise request */ ZERO_STRUCT(request); ZERO_STRUCT(response); if (!dom_sid || (num_rids == 0)) { wbc_status = WBC_ERR_INVALID_PARAM; BAIL_ON_WBC_ERROR(wbc_status); } wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid)); /* Even if all the Rids were of maximum 32bit values, we would only have 11 bytes per rid in the final array ("4294967296" + \n). Add one more byte for the terminating '\0' */ ridbuf_size = (sizeof(char)*11) * num_rids + 1; ridlist = (char *)malloc(ridbuf_size); BAIL_ON_PTR_ERROR(ridlist, wbc_status); len = 0; for (i=0; i<num_rids; i++) { len += snprintf(ridlist + len, ridbuf_size - len, "%u\n", rids[i]); } ridlist[len] = '\0'; len += 1; request.extra_data.data = ridlist; request.extra_len = len; wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS, &request, &response); free(ridlist); BAIL_ON_WBC_ERROR(wbc_status); domain_name = wbcStrDup(response.data.domain_name); BAIL_ON_PTR_ERROR(domain_name, wbc_status); names = wbcAllocateStringArray(num_rids); BAIL_ON_PTR_ERROR(names, wbc_status); types = (enum wbcSidType *)wbcAllocateMemory( num_rids, sizeof(enum wbcSidType), NULL); BAIL_ON_PTR_ERROR(types, wbc_status); p = (char *)response.extra_data.data; for (i=0; i<num_rids; i++) { char *q; if (*p == '\0') { wbc_status = WBC_ERR_INVALID_RESPONSE; goto done; } types[i] = (enum wbcSidType)strtoul(p, &q, 10); if (*q != ' ') { wbc_status = WBC_ERR_INVALID_RESPONSE; goto done; } p = q+1; if ((q = strchr(p, '\n')) == NULL) { wbc_status = WBC_ERR_INVALID_RESPONSE; goto done; } *q = '\0'; names[i] = strdup(p); BAIL_ON_PTR_ERROR(names[i], wbc_status); p = q+1; } if (*p != '\0') { wbc_status = WBC_ERR_INVALID_RESPONSE; goto done; } wbc_status = WBC_ERR_SUCCESS; done: winbindd_free_response(&response); if (WBC_ERROR_IS_OK(wbc_status)) { *pp_domain_name = domain_name; *pnames = names; *ptypes = types; } else { wbcFreeMemory(domain_name); wbcFreeMemory(names); wbcFreeMemory(types); } return wbc_status; }
wbcErr wbcLookupSids(const struct wbcDomainSid *sids, int num_sids, struct wbcDomainInfo **pdomains, int *pnum_domains, struct wbcTranslatedName **pnames) { struct winbindd_request request; struct winbindd_response response; wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; int buflen, i, extra_len, num_domains, num_names; char *sidlist, *p, *q, *extra_data; struct wbcDomainInfo *domains = NULL; struct wbcTranslatedName *names = NULL; buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1; sidlist = (char *)malloc(buflen); if (sidlist == NULL) { return WBC_ERR_NO_MEMORY; } p = sidlist; for (i=0; i<num_sids; i++) { int remaining; int len; remaining = buflen - (p - sidlist); len = wbcSidToStringBuf(&sids[i], p, remaining); if (len > remaining) { free(sidlist); return WBC_ERR_UNKNOWN_FAILURE; } p += len; *p++ = '\n'; } *p++ = '\0'; ZERO_STRUCT(request); ZERO_STRUCT(response); request.extra_data.data = sidlist; request.extra_len = p - sidlist; wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSIDS, &request, &response); free(sidlist); if (!WBC_ERROR_IS_OK(wbc_status)) { return wbc_status; } extra_len = response.length - sizeof(struct winbindd_response); extra_data = (char *)response.extra_data.data; if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) { goto wbc_err_invalid; } p = extra_data; num_domains = strtoul(p, &q, 10); if (*q != '\n') { goto wbc_err_invalid; } p = q+1; domains = (struct wbcDomainInfo *)wbcAllocateMemory( num_domains+1, sizeof(struct wbcDomainInfo), wbcDomainInfosDestructor); if (domains == NULL) { wbc_status = WBC_ERR_NO_MEMORY; goto fail; } for (i=0; i<num_domains; i++) { q = strchr(p, ' '); if (q == NULL) { goto wbc_err_invalid; } *q = '\0'; wbc_status = wbcStringToSid(p, &domains[i].sid); if (!WBC_ERROR_IS_OK(wbc_status)) { goto fail; } p = q+1; q = strchr(p, '\n'); if (q == NULL) { goto wbc_err_invalid; } *q = '\0'; domains[i].short_name = wbcStrDup(p); if (domains[i].short_name == NULL) { wbc_status = WBC_ERR_NO_MEMORY; goto fail; } p = q+1; } num_names = strtoul(p, &q, 10); if (*q != '\n') { goto wbc_err_invalid; } p = q+1; if (num_names != num_sids) { goto wbc_err_invalid; } names = (struct wbcTranslatedName *)wbcAllocateMemory( num_names+1, sizeof(struct wbcTranslatedName), wbcTranslatedNamesDestructor); if (names == NULL) { wbc_status = WBC_ERR_NO_MEMORY; goto fail; } for (i=0; i<num_names; i++) { names[i].domain_index = strtoul(p, &q, 10); if (*q != ' ') { goto wbc_err_invalid; } p = q+1; names[i].type = strtoul(p, &q, 10); if (*q != ' ') { goto wbc_err_invalid; } p = q+1; q = strchr(p, '\n'); if (q == NULL) { goto wbc_err_invalid; } *q = '\0'; names[i].name = wbcStrDup(p); if (names[i].name == NULL) { wbc_status = WBC_ERR_NO_MEMORY; goto fail; } p = q+1; } if (*p != '\0') { goto wbc_err_invalid; } *pdomains = domains; *pnames = names; winbindd_free_response(&response); return WBC_ERR_SUCCESS; wbc_err_invalid: wbc_status = WBC_ERR_INVALID_RESPONSE; fail: winbindd_free_response(&response); wbcFreeMemory(domains); wbcFreeMemory(names); return wbc_status; }
/* Convert a SID to a domain and name */ wbcErr wbcLookupSid(const struct wbcDomainSid *sid, char **pdomain, char **pname, enum wbcSidType *pname_type) { char *str_sid; char *fq_name = NULL; enum sss_id_type type; int ret; char *p; wbcErr wbc_status; wbc_status = wbcSidToString(sid, &str_sid); if (!WBC_ERROR_IS_OK(wbc_status)) { return wbc_status; } ret = sss_nss_getnamebysid(str_sid, &fq_name, &type); wbcFreeMemory(str_sid); if (ret != 0) { return WBC_ERR_UNKNOWN_FAILURE; } if (pname_type != NULL) { ret = sss_id_type_to_wbcSidType(type, pname_type); if (ret != 0) { wbc_status = WBC_ERR_UNKNOWN_FAILURE; goto done; } } /* TODO: it would be nice to have an sss_nss_getnamebysid() call which * returns name and domain separately. */ p = strchr(fq_name, '@'); if (p == NULL) { wbc_status = WBC_ERR_UNKNOWN_FAILURE; goto done; } *p = '\0'; if (pname != NULL) { *pname = wbcStrDup(fq_name); if (*pname == NULL) { wbc_status = WBC_ERR_NO_MEMORY; goto done; } } if (pdomain != NULL) { *pdomain = wbcStrDup(p + 1); if (*pdomain == NULL) { wbcFreeMemory(*pname); wbc_status = WBC_ERR_NO_MEMORY; goto done; } } wbc_status = WBC_ERR_SUCCESS; done: free(fq_name); return wbc_status; }