/* Unix SMB/CIFS implementation. Winbind client API Copyright (C) Gerald (Jerry) Carter 2007 Copyright (C) Volker Lendecke 2010 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ /* Required Headers */ #include #include "libwbclient.h" #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /* Convert a sid to a string into a buffer. Return the string * length. If buflen is too small, return the string length that would * result if it was long enough. */ int wbcSidToStringBuf(const struct wbcDomainSid *sid, char *buf, int buflen) { uint64_t id_auth; int i, ofs; if (!sid) { strncpy(buf, "(NULL SID)", buflen); buf[buflen < 10 ? buflen :10] = '\0'; return 10; /* strlen("(NULL SID)") */ } id_auth = (uint64_t)sid->id_auth[5] + ((uint64_t)sid->id_auth[4] << 8) + ((uint64_t)sid->id_auth[3] << 16) + ((uint64_t)sid->id_auth[2] << 24) + ((uint64_t)sid->id_auth[1] << 32) + ((uint64_t)sid->id_auth[0] << 40); ofs = snprintf(buf, buflen, "S-%hhu-", (unsigned char)sid->sid_rev_num); if (id_auth >= UINT32_MAX) { ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "0x%llx", (unsigned long long)id_auth); } else { ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "%llu", (unsigned long long)id_auth); } for (i = 0; i < sid->num_auths; i++) { ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "-%u", (unsigned int)sid->sub_auths[i]); } return ofs; } /* Convert a binary SID to a character string */ wbcErr wbcSidToString(const struct wbcDomainSid *sid, char **sid_string) { char buf[WBC_SID_STRING_BUFLEN]; char *result; int len; if (!sid) { return WBC_ERR_INVALID_SID; } len = wbcSidToStringBuf(sid, buf, sizeof(buf)); if (len+1 > sizeof(buf)) { return WBC_ERR_INVALID_SID; } result = (char *)wbcAllocateMemory(len+1, 1, NULL); if (result == NULL) { return WBC_ERR_NO_MEMORY; } memcpy(result, buf, len+1); *sid_string = result; return WBC_ERR_SUCCESS; } #define AUTHORITY_MASK (~(0xffffffffffffULL)) /* Convert a character string to a binary SID */ wbcErr wbcStringToSid(const char *str, struct wbcDomainSid *sid) { const char *p; char *q; uint64_t x; wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; if (!sid) { wbc_status = WBC_ERR_INVALID_PARAM; BAIL_ON_WBC_ERROR(wbc_status); } /* Sanity check for either "S-" or "s-" */ if (!str || (str[0]!='S' && str[0]!='s') || (str[1]!='-')) { wbc_status = WBC_ERR_INVALID_PARAM; BAIL_ON_WBC_ERROR(wbc_status); } /* Get the SID revision number */ p = str+2; x = (uint64_t)strtoul(p, &q, 10); if (x==0 || x > UINT8_MAX || !q || *q!='-') { wbc_status = WBC_ERR_INVALID_SID; BAIL_ON_WBC_ERROR(wbc_status); } sid->sid_rev_num = (uint8_t)x; /* * Next the Identifier Authority. This is stored big-endian in a * 6 byte array. If the authority value is >= UINT_MAX, then it should * be expressed as a hex value, according to MS-DTYP. */ p = q+1; x = strtoull(p, &q, 0); if (!q || *q!='-' || (x & AUTHORITY_MASK)) { wbc_status = WBC_ERR_INVALID_SID; BAIL_ON_WBC_ERROR(wbc_status); } sid->id_auth[5] = (x & 0x0000000000ffULL); sid->id_auth[4] = (x & 0x00000000ff00ULL) >> 8; sid->id_auth[3] = (x & 0x000000ff0000ULL) >> 16; sid->id_auth[2] = (x & 0x0000ff000000ULL) >> 24; sid->id_auth[1] = (x & 0x00ff00000000ULL) >> 32; sid->id_auth[0] = (x & 0xff0000000000ULL) >> 40; /* now read the the subauthorities */ p = q +1; sid->num_auths = 0; while (sid->num_auths < WBC_MAXSUBAUTHS) { x = strtoull(p, &q, 10); if (p == q) break; if (x > UINT32_MAX) { wbc_status = WBC_ERR_INVALID_SID; BAIL_ON_WBC_ERROR(wbc_status); } sid->sub_auths[sid->num_auths++] = x; if (*q != '-') { break; } p = q + 1; } /* IF we ended early, then the SID could not be converted */ if (q && *q!='\0') { wbc_status = WBC_ERR_INVALID_SID; BAIL_ON_WBC_ERROR(wbc_status); } wbc_status = WBC_ERR_SUCCESS; done: return wbc_status; } const char* wbcSidTypeString(enum wbcSidType type) { switch (type) { case WBC_SID_NAME_USE_NONE: return "SID_NONE"; case WBC_SID_NAME_USER: return "SID_USER"; case WBC_SID_NAME_DOM_GRP: return "SID_DOM_GROUP"; case WBC_SID_NAME_DOMAIN: return "SID_DOMAIN"; case WBC_SID_NAME_ALIAS: return "SID_ALIAS"; case WBC_SID_NAME_WKN_GRP: return "SID_WKN_GROUP"; case WBC_SID_NAME_DELETED: return "SID_DELETED"; case WBC_SID_NAME_INVALID: return "SID_INVALID"; case WBC_SID_NAME_UNKNOWN: return "SID_UNKNOWN"; case WBC_SID_NAME_COMPUTER: return "SID_COMPUTER"; default: return "Unknown type"; } }