| 1 | /*
|
|---|
| 2 | Unix SMB/CIFS implementation.
|
|---|
| 3 |
|
|---|
| 4 | Winbind client API
|
|---|
| 5 |
|
|---|
| 6 | Copyright (C) Gerald (Jerry) Carter 2007
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 | This library is free software; you can redistribute it and/or
|
|---|
| 10 | modify it under the terms of the GNU Lesser General Public
|
|---|
| 11 | License as published by the Free Software Foundation; either
|
|---|
| 12 | version 3 of the License, or (at your option) any later version.
|
|---|
| 13 |
|
|---|
| 14 | This library is distributed in the hope that it will be useful,
|
|---|
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 17 | Library General Public License for more details.
|
|---|
| 18 |
|
|---|
| 19 | You should have received a copy of the GNU Lesser General Public License
|
|---|
| 20 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|---|
| 21 | */
|
|---|
| 22 |
|
|---|
| 23 | /* Required Headers */
|
|---|
| 24 |
|
|---|
| 25 | #include "replace.h"
|
|---|
| 26 | #include "libwbclient.h"
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 | /* Convert a binary SID to a character string */
|
|---|
| 30 | wbcErr wbcSidToString(const struct wbcDomainSid *sid,
|
|---|
| 31 | char **sid_string)
|
|---|
| 32 | {
|
|---|
| 33 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 34 | uint32_t id_auth;
|
|---|
| 35 | int i;
|
|---|
| 36 | char *tmp = NULL;
|
|---|
| 37 |
|
|---|
| 38 | if (!sid) {
|
|---|
| 39 | wbc_status = WBC_ERR_INVALID_SID;
|
|---|
| 40 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 41 | }
|
|---|
| 42 |
|
|---|
| 43 | id_auth = sid->id_auth[5] +
|
|---|
| 44 | (sid->id_auth[4] << 8) +
|
|---|
| 45 | (sid->id_auth[3] << 16) +
|
|---|
| 46 | (sid->id_auth[2] << 24);
|
|---|
| 47 |
|
|---|
| 48 | tmp = talloc_asprintf(NULL, "S-%d-%d", sid->sid_rev_num, id_auth);
|
|---|
| 49 | BAIL_ON_PTR_ERROR(tmp, wbc_status);
|
|---|
| 50 |
|
|---|
| 51 | for (i=0; i<sid->num_auths; i++) {
|
|---|
| 52 | char *tmp2;
|
|---|
| 53 | tmp2 = talloc_asprintf_append(tmp, "-%u", sid->sub_auths[i]);
|
|---|
| 54 | BAIL_ON_PTR_ERROR(tmp2, wbc_status);
|
|---|
| 55 |
|
|---|
| 56 | tmp = tmp2;
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | *sid_string = tmp;
|
|---|
| 60 | tmp = NULL;
|
|---|
| 61 |
|
|---|
| 62 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 63 |
|
|---|
| 64 | done:
|
|---|
| 65 | talloc_free(tmp);
|
|---|
| 66 |
|
|---|
| 67 | return wbc_status;
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | /* Convert a character string to a binary SID */
|
|---|
| 71 | wbcErr wbcStringToSid(const char *str,
|
|---|
| 72 | struct wbcDomainSid *sid)
|
|---|
| 73 | {
|
|---|
| 74 | const char *p;
|
|---|
| 75 | char *q;
|
|---|
| 76 | uint32_t x;
|
|---|
| 77 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 78 |
|
|---|
| 79 | if (!sid) {
|
|---|
| 80 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 81 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 82 | }
|
|---|
| 83 |
|
|---|
| 84 | /* Sanity check for either "S-" or "s-" */
|
|---|
| 85 |
|
|---|
| 86 | if (!str
|
|---|
| 87 | || (str[0]!='S' && str[0]!='s')
|
|---|
| 88 | || (str[1]!='-'))
|
|---|
| 89 | {
|
|---|
| 90 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 91 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | /* Get the SID revision number */
|
|---|
| 95 |
|
|---|
| 96 | p = str+2;
|
|---|
| 97 | x = (uint32_t)strtol(p, &q, 10);
|
|---|
| 98 | if (x==0 || !q || *q!='-') {
|
|---|
| 99 | wbc_status = WBC_ERR_INVALID_SID;
|
|---|
| 100 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 101 | }
|
|---|
| 102 | sid->sid_rev_num = (uint8_t)x;
|
|---|
| 103 |
|
|---|
| 104 | /* Next the Identifier Authority. This is stored in big-endian
|
|---|
| 105 | in a 6 byte array. */
|
|---|
| 106 |
|
|---|
| 107 | p = q+1;
|
|---|
| 108 | x = (uint32_t)strtol(p, &q, 10);
|
|---|
| 109 | if (!q || *q!='-') {
|
|---|
| 110 | wbc_status = WBC_ERR_INVALID_SID;
|
|---|
| 111 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 112 | }
|
|---|
| 113 | sid->id_auth[5] = (x & 0x000000ff);
|
|---|
| 114 | sid->id_auth[4] = (x & 0x0000ff00) >> 8;
|
|---|
| 115 | sid->id_auth[3] = (x & 0x00ff0000) >> 16;
|
|---|
| 116 | sid->id_auth[2] = (x & 0xff000000) >> 24;
|
|---|
| 117 | sid->id_auth[1] = 0;
|
|---|
| 118 | sid->id_auth[0] = 0;
|
|---|
| 119 |
|
|---|
| 120 | /* now read the the subauthorities */
|
|---|
| 121 |
|
|---|
| 122 | p = q +1;
|
|---|
| 123 | sid->num_auths = 0;
|
|---|
| 124 | while (sid->num_auths < WBC_MAXSUBAUTHS) {
|
|---|
| 125 | x=(uint32_t)strtoul(p, &q, 10);
|
|---|
| 126 | if (p == q)
|
|---|
| 127 | break;
|
|---|
| 128 | if (q == NULL) {
|
|---|
| 129 | wbc_status = WBC_ERR_INVALID_SID;
|
|---|
| 130 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 131 | }
|
|---|
| 132 | sid->sub_auths[sid->num_auths++] = x;
|
|---|
| 133 |
|
|---|
| 134 | if ((*q!='-') || (*q=='\0'))
|
|---|
| 135 | break;
|
|---|
| 136 | p = q + 1;
|
|---|
| 137 | }
|
|---|
| 138 |
|
|---|
| 139 | /* IF we ended early, then the SID could not be converted */
|
|---|
| 140 |
|
|---|
| 141 | if (q && *q!='\0') {
|
|---|
| 142 | wbc_status = WBC_ERR_INVALID_SID;
|
|---|
| 143 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 147 |
|
|---|
| 148 | done:
|
|---|
| 149 | return wbc_status;
|
|---|
| 150 |
|
|---|
| 151 | }
|
|---|
| 152 |
|
|---|
| 153 | /* Convert a domain and name to SID */
|
|---|
| 154 | wbcErr wbcLookupName(const char *domain,
|
|---|
| 155 | const char *name,
|
|---|
| 156 | struct wbcDomainSid *sid,
|
|---|
| 157 | enum wbcSidType *name_type)
|
|---|
| 158 | {
|
|---|
| 159 | struct winbindd_request request;
|
|---|
| 160 | struct winbindd_response response;
|
|---|
| 161 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 162 |
|
|---|
| 163 | if (!sid || !name_type) {
|
|---|
| 164 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 165 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 166 | }
|
|---|
| 167 |
|
|---|
| 168 | /* Initialize request */
|
|---|
| 169 |
|
|---|
| 170 | ZERO_STRUCT(request);
|
|---|
| 171 | ZERO_STRUCT(response);
|
|---|
| 172 |
|
|---|
| 173 | /* dst is already null terminated from the memset above */
|
|---|
| 174 |
|
|---|
| 175 | strncpy(request.data.name.dom_name, domain,
|
|---|
| 176 | sizeof(request.data.name.dom_name)-1);
|
|---|
| 177 | strncpy(request.data.name.name, name,
|
|---|
| 178 | sizeof(request.data.name.name)-1);
|
|---|
| 179 |
|
|---|
| 180 | wbc_status = wbcRequestResponse(WINBINDD_LOOKUPNAME,
|
|---|
| 181 | &request,
|
|---|
| 182 | &response);
|
|---|
| 183 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 184 |
|
|---|
| 185 | wbc_status = wbcStringToSid(response.data.sid.sid, sid);
|
|---|
| 186 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 187 |
|
|---|
| 188 | *name_type = (enum wbcSidType)response.data.sid.type;
|
|---|
| 189 |
|
|---|
| 190 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 191 |
|
|---|
| 192 | done:
|
|---|
| 193 | return wbc_status;
|
|---|
| 194 | }
|
|---|
| 195 |
|
|---|
| 196 | /* Convert a SID to a domain and name */
|
|---|
| 197 | wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
|
|---|
| 198 | char **pdomain,
|
|---|
| 199 | char **pname,
|
|---|
| 200 | enum wbcSidType *pname_type)
|
|---|
| 201 | {
|
|---|
| 202 | struct winbindd_request request;
|
|---|
| 203 | struct winbindd_response response;
|
|---|
| 204 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 205 | char *sid_string = NULL;
|
|---|
| 206 | char *domain = NULL;
|
|---|
| 207 | char *name = NULL;
|
|---|
| 208 | enum wbcSidType name_type = WBC_SID_NAME_USE_NONE;
|
|---|
| 209 |
|
|---|
| 210 | if (!sid) {
|
|---|
| 211 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 212 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 213 | }
|
|---|
| 214 |
|
|---|
| 215 | /* Initialize request */
|
|---|
| 216 |
|
|---|
| 217 | ZERO_STRUCT(request);
|
|---|
| 218 | ZERO_STRUCT(response);
|
|---|
| 219 |
|
|---|
| 220 | /* dst is already null terminated from the memset above */
|
|---|
| 221 |
|
|---|
| 222 | wbc_status = wbcSidToString(sid, &sid_string);
|
|---|
| 223 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 224 |
|
|---|
| 225 | strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
|
|---|
| 226 | wbcFreeMemory(sid_string);
|
|---|
| 227 |
|
|---|
| 228 | /* Make request */
|
|---|
| 229 |
|
|---|
| 230 | wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID,
|
|---|
| 231 | &request,
|
|---|
| 232 | &response);
|
|---|
| 233 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 234 |
|
|---|
| 235 | /* Copy out result */
|
|---|
| 236 |
|
|---|
| 237 | domain = talloc_strdup(NULL, response.data.name.dom_name);
|
|---|
| 238 | BAIL_ON_PTR_ERROR(domain, wbc_status);
|
|---|
| 239 |
|
|---|
| 240 | name = talloc_strdup(NULL, response.data.name.name);
|
|---|
| 241 | BAIL_ON_PTR_ERROR(name, wbc_status);
|
|---|
| 242 |
|
|---|
| 243 | name_type = (enum wbcSidType)response.data.name.type;
|
|---|
| 244 |
|
|---|
| 245 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 246 |
|
|---|
| 247 | done:
|
|---|
| 248 | if (WBC_ERROR_IS_OK(wbc_status)) {
|
|---|
| 249 | if (pdomain != NULL) {
|
|---|
| 250 | *pdomain = domain;
|
|---|
| 251 | } else {
|
|---|
| 252 | TALLOC_FREE(domain);
|
|---|
| 253 | }
|
|---|
| 254 | if (pname != NULL) {
|
|---|
| 255 | *pname = name;
|
|---|
| 256 | } else {
|
|---|
| 257 | TALLOC_FREE(name);
|
|---|
| 258 | }
|
|---|
| 259 | if (pname_type != NULL) {
|
|---|
| 260 | *pname_type = name_type;
|
|---|
| 261 | }
|
|---|
| 262 | }
|
|---|
| 263 | else {
|
|---|
| 264 | #if 0
|
|---|
| 265 | /*
|
|---|
| 266 | * Found by Coverity: In this particular routine we can't end
|
|---|
| 267 | * up here with a non-NULL name. Further up there are just two
|
|---|
| 268 | * exit paths that lead here, neither of which leave an
|
|---|
| 269 | * allocated name. If you add more paths up there, re-activate
|
|---|
| 270 | * this.
|
|---|
| 271 | */
|
|---|
| 272 | if (name != NULL) {
|
|---|
| 273 | talloc_free(name);
|
|---|
| 274 | }
|
|---|
| 275 | #endif
|
|---|
| 276 | if (domain != NULL) {
|
|---|
| 277 | talloc_free(domain);
|
|---|
| 278 | }
|
|---|
| 279 | }
|
|---|
| 280 |
|
|---|
| 281 | return wbc_status;
|
|---|
| 282 | }
|
|---|
| 283 |
|
|---|
| 284 | /* Translate a collection of RIDs within a domain to names */
|
|---|
| 285 |
|
|---|
| 286 | wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
|
|---|
| 287 | int num_rids,
|
|---|
| 288 | uint32_t *rids,
|
|---|
| 289 | const char **pp_domain_name,
|
|---|
| 290 | const char ***pnames,
|
|---|
| 291 | enum wbcSidType **ptypes)
|
|---|
| 292 | {
|
|---|
| 293 | size_t i, len, ridbuf_size;
|
|---|
| 294 | char *ridlist;
|
|---|
| 295 | char *p;
|
|---|
| 296 | struct winbindd_request request;
|
|---|
| 297 | struct winbindd_response response;
|
|---|
| 298 | char *sid_string = NULL;
|
|---|
| 299 | char *domain_name = NULL;
|
|---|
| 300 | const char **names = NULL;
|
|---|
| 301 | enum wbcSidType *types = NULL;
|
|---|
| 302 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 303 |
|
|---|
| 304 | /* Initialise request */
|
|---|
| 305 |
|
|---|
| 306 | ZERO_STRUCT(request);
|
|---|
| 307 | ZERO_STRUCT(response);
|
|---|
| 308 |
|
|---|
| 309 | if (!dom_sid || (num_rids == 0)) {
|
|---|
| 310 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 311 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 312 | }
|
|---|
| 313 |
|
|---|
| 314 | wbc_status = wbcSidToString(dom_sid, &sid_string);
|
|---|
| 315 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 316 |
|
|---|
| 317 | strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
|
|---|
| 318 | wbcFreeMemory(sid_string);
|
|---|
| 319 |
|
|---|
| 320 | /* Even if all the Rids were of maximum 32bit values,
|
|---|
| 321 | we would only have 11 bytes per rid in the final array
|
|---|
| 322 | ("4294967296" + \n). Add one more byte for the
|
|---|
| 323 | terminating '\0' */
|
|---|
| 324 |
|
|---|
| 325 | ridbuf_size = (sizeof(char)*11) * num_rids + 1;
|
|---|
| 326 |
|
|---|
| 327 | ridlist = talloc_zero_array(NULL, char, ridbuf_size);
|
|---|
| 328 | BAIL_ON_PTR_ERROR(ridlist, wbc_status);
|
|---|
| 329 |
|
|---|
| 330 | len = 0;
|
|---|
| 331 | for (i=0; i<num_rids && (len-1)>0; i++) {
|
|---|
| 332 | char ridstr[12];
|
|---|
| 333 |
|
|---|
| 334 | len = strlen(ridlist);
|
|---|
| 335 | p = ridlist + len;
|
|---|
| 336 |
|
|---|
| 337 | snprintf( ridstr, sizeof(ridstr)-1, "%u\n", rids[i]);
|
|---|
| 338 | strncat(p, ridstr, ridbuf_size-len-1);
|
|---|
| 339 | }
|
|---|
| 340 |
|
|---|
| 341 | request.extra_data.data = ridlist;
|
|---|
| 342 | request.extra_len = strlen(ridlist)+1;
|
|---|
| 343 |
|
|---|
| 344 | wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS,
|
|---|
| 345 | &request,
|
|---|
| 346 | &response);
|
|---|
| 347 | talloc_free(ridlist);
|
|---|
| 348 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 349 |
|
|---|
| 350 | domain_name = talloc_strdup(NULL, response.data.domain_name);
|
|---|
| 351 | BAIL_ON_PTR_ERROR(domain_name, wbc_status);
|
|---|
| 352 |
|
|---|
| 353 | names = talloc_array(NULL, const char*, num_rids);
|
|---|
| 354 | BAIL_ON_PTR_ERROR(names, wbc_status);
|
|---|
| 355 |
|
|---|
| 356 | types = talloc_array(NULL, enum wbcSidType, num_rids);
|
|---|
| 357 | BAIL_ON_PTR_ERROR(types, wbc_status);
|
|---|
| 358 |
|
|---|
| 359 | p = (char *)response.extra_data.data;
|
|---|
| 360 |
|
|---|
| 361 | for (i=0; i<num_rids; i++) {
|
|---|
| 362 | char *q;
|
|---|
| 363 |
|
|---|
| 364 | if (*p == '\0') {
|
|---|
| 365 | wbc_status = WBC_ERR_INVALID_RESPONSE;
|
|---|
| 366 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 367 | }
|
|---|
| 368 |
|
|---|
| 369 | types[i] = (enum wbcSidType)strtoul(p, &q, 10);
|
|---|
| 370 |
|
|---|
| 371 | if (*q != ' ') {
|
|---|
| 372 | wbc_status = WBC_ERR_INVALID_RESPONSE;
|
|---|
| 373 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 374 | }
|
|---|
| 375 |
|
|---|
| 376 | p = q+1;
|
|---|
| 377 |
|
|---|
| 378 | if ((q = strchr(p, '\n')) == NULL) {
|
|---|
| 379 | wbc_status = WBC_ERR_INVALID_RESPONSE;
|
|---|
| 380 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 381 | }
|
|---|
| 382 |
|
|---|
| 383 | *q = '\0';
|
|---|
| 384 |
|
|---|
| 385 | names[i] = talloc_strdup(names, p);
|
|---|
| 386 | BAIL_ON_PTR_ERROR(names[i], wbc_status);
|
|---|
| 387 |
|
|---|
| 388 | p = q+1;
|
|---|
| 389 | }
|
|---|
| 390 |
|
|---|
| 391 | if (*p != '\0') {
|
|---|
| 392 | wbc_status = WBC_ERR_INVALID_RESPONSE;
|
|---|
| 393 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 394 | }
|
|---|
| 395 |
|
|---|
| 396 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 397 |
|
|---|
| 398 | done:
|
|---|
| 399 | if (response.extra_data.data) {
|
|---|
| 400 | free(response.extra_data.data);
|
|---|
| 401 | }
|
|---|
| 402 |
|
|---|
| 403 | if (WBC_ERROR_IS_OK(wbc_status)) {
|
|---|
| 404 | *pp_domain_name = domain_name;
|
|---|
| 405 | *pnames = names;
|
|---|
| 406 | *ptypes = types;
|
|---|
| 407 | }
|
|---|
| 408 | else {
|
|---|
| 409 | if (domain_name)
|
|---|
| 410 | talloc_free(domain_name);
|
|---|
| 411 | if (names)
|
|---|
| 412 | talloc_free(names);
|
|---|
| 413 | if (types)
|
|---|
| 414 | talloc_free(types);
|
|---|
| 415 | }
|
|---|
| 416 |
|
|---|
| 417 | return wbc_status;
|
|---|
| 418 | }
|
|---|
| 419 |
|
|---|
| 420 | /* Get the groups a user belongs to */
|
|---|
| 421 | wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
|
|---|
| 422 | bool domain_groups_only,
|
|---|
| 423 | uint32_t *num_sids,
|
|---|
| 424 | struct wbcDomainSid **_sids)
|
|---|
| 425 | {
|
|---|
| 426 | uint32_t i;
|
|---|
| 427 | const char *s;
|
|---|
| 428 | struct winbindd_request request;
|
|---|
| 429 | struct winbindd_response response;
|
|---|
| 430 | char *sid_string = NULL;
|
|---|
| 431 | struct wbcDomainSid *sids = NULL;
|
|---|
| 432 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 433 | int cmd;
|
|---|
| 434 |
|
|---|
| 435 | /* Initialise request */
|
|---|
| 436 |
|
|---|
| 437 | ZERO_STRUCT(request);
|
|---|
| 438 | ZERO_STRUCT(response);
|
|---|
| 439 |
|
|---|
| 440 | if (!user_sid) {
|
|---|
| 441 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 442 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 443 | }
|
|---|
| 444 |
|
|---|
| 445 | wbc_status = wbcSidToString(user_sid, &sid_string);
|
|---|
| 446 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 447 |
|
|---|
| 448 | strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
|
|---|
| 449 | wbcFreeMemory(sid_string);
|
|---|
| 450 |
|
|---|
| 451 | if (domain_groups_only) {
|
|---|
| 452 | cmd = WINBINDD_GETUSERDOMGROUPS;
|
|---|
| 453 | } else {
|
|---|
| 454 | cmd = WINBINDD_GETUSERSIDS;
|
|---|
| 455 | }
|
|---|
| 456 |
|
|---|
| 457 | wbc_status = wbcRequestResponse(cmd,
|
|---|
| 458 | &request,
|
|---|
| 459 | &response);
|
|---|
| 460 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 461 |
|
|---|
| 462 | if (response.data.num_entries &&
|
|---|
| 463 | !response.extra_data.data) {
|
|---|
| 464 | wbc_status = WBC_ERR_INVALID_RESPONSE;
|
|---|
| 465 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 466 | }
|
|---|
| 467 |
|
|---|
| 468 | sids = talloc_array(NULL, struct wbcDomainSid,
|
|---|
| 469 | response.data.num_entries);
|
|---|
| 470 | BAIL_ON_PTR_ERROR(sids, wbc_status);
|
|---|
| 471 |
|
|---|
| 472 | s = (const char *)response.extra_data.data;
|
|---|
| 473 | for (i = 0; i < response.data.num_entries; i++) {
|
|---|
| 474 | char *n = strchr(s, '\n');
|
|---|
| 475 | if (n) {
|
|---|
| 476 | *n = '\0';
|
|---|
| 477 | }
|
|---|
| 478 | wbc_status = wbcStringToSid(s, &sids[i]);
|
|---|
| 479 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 480 | s += strlen(s) + 1;
|
|---|
| 481 | }
|
|---|
| 482 |
|
|---|
| 483 | *num_sids = response.data.num_entries;
|
|---|
| 484 | *_sids = sids;
|
|---|
| 485 | sids = NULL;
|
|---|
| 486 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 487 |
|
|---|
| 488 | done:
|
|---|
| 489 | if (response.extra_data.data) {
|
|---|
| 490 | free(response.extra_data.data);
|
|---|
| 491 | }
|
|---|
| 492 | if (sids) {
|
|---|
| 493 | talloc_free(sids);
|
|---|
| 494 | }
|
|---|
| 495 |
|
|---|
| 496 | return wbc_status;
|
|---|
| 497 | }
|
|---|
| 498 |
|
|---|
| 499 | static inline
|
|---|
| 500 | wbcErr _sid_to_rid(struct wbcDomainSid *sid, uint32_t *rid)
|
|---|
| 501 | {
|
|---|
| 502 | if (sid->num_auths < 1) {
|
|---|
| 503 | return WBC_ERR_INVALID_RESPONSE;
|
|---|
| 504 | }
|
|---|
| 505 | *rid = sid->sub_auths[sid->num_auths - 1];
|
|---|
| 506 |
|
|---|
| 507 | return WBC_ERR_SUCCESS;
|
|---|
| 508 | }
|
|---|
| 509 |
|
|---|
| 510 | /* Get alias membership for sids */
|
|---|
| 511 | wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
|
|---|
| 512 | struct wbcDomainSid *sids,
|
|---|
| 513 | uint32_t num_sids,
|
|---|
| 514 | uint32_t **alias_rids,
|
|---|
| 515 | uint32_t *num_alias_rids)
|
|---|
| 516 | {
|
|---|
| 517 | uint32_t i;
|
|---|
| 518 | const char *s;
|
|---|
| 519 | struct winbindd_request request;
|
|---|
| 520 | struct winbindd_response response;
|
|---|
| 521 | char *sid_string = NULL;
|
|---|
| 522 | ssize_t sid_len;
|
|---|
| 523 | ssize_t extra_data_len = 0;
|
|---|
| 524 | char * extra_data = NULL;
|
|---|
| 525 | ssize_t buflen = 0;
|
|---|
| 526 | struct wbcDomainSid sid;
|
|---|
| 527 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 528 | uint32_t * rids = NULL;
|
|---|
| 529 |
|
|---|
| 530 | /* Initialise request */
|
|---|
| 531 |
|
|---|
| 532 | ZERO_STRUCT(request);
|
|---|
| 533 | ZERO_STRUCT(response);
|
|---|
| 534 |
|
|---|
| 535 | if (!dom_sid) {
|
|---|
| 536 | wbc_status = WBC_ERR_INVALID_PARAM;
|
|---|
| 537 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 538 | }
|
|---|
| 539 |
|
|---|
| 540 | wbc_status = wbcSidToString(dom_sid, &sid_string);
|
|---|
| 541 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 542 |
|
|---|
| 543 | strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
|
|---|
| 544 | wbcFreeMemory(sid_string);
|
|---|
| 545 | sid_string = NULL;
|
|---|
| 546 |
|
|---|
| 547 | /* Lets assume each sid is around 54 characters
|
|---|
| 548 | * S-1-5-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
|
|---|
| 549 | buflen = 54 * num_sids;
|
|---|
| 550 | extra_data = talloc_array(NULL, char, buflen);
|
|---|
| 551 | if (!extra_data) {
|
|---|
| 552 | wbc_status = WBC_ERR_NO_MEMORY;
|
|---|
| 553 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 554 | }
|
|---|
| 555 |
|
|---|
| 556 | /* Build the sid list */
|
|---|
| 557 | for (i=0; i<num_sids; i++) {
|
|---|
| 558 | if (sid_string) {
|
|---|
| 559 | wbcFreeMemory(sid_string);
|
|---|
| 560 | sid_string = NULL;
|
|---|
| 561 | }
|
|---|
| 562 | wbc_status = wbcSidToString(&sids[i], &sid_string);
|
|---|
| 563 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 564 |
|
|---|
| 565 | sid_len = strlen(sid_string);
|
|---|
| 566 |
|
|---|
| 567 | if (buflen < extra_data_len + sid_len + 2) {
|
|---|
| 568 | buflen *= 2;
|
|---|
| 569 | extra_data = talloc_realloc(NULL, extra_data,
|
|---|
| 570 | char, buflen);
|
|---|
| 571 | if (!extra_data) {
|
|---|
| 572 | wbc_status = WBC_ERR_NO_MEMORY;
|
|---|
| 573 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 574 | }
|
|---|
| 575 | }
|
|---|
| 576 |
|
|---|
| 577 | strncpy(&extra_data[extra_data_len], sid_string,
|
|---|
| 578 | buflen - extra_data_len);
|
|---|
| 579 | extra_data_len += sid_len;
|
|---|
| 580 | extra_data[extra_data_len++] = '\n';
|
|---|
| 581 | extra_data[extra_data_len] = '\0';
|
|---|
| 582 | }
|
|---|
| 583 |
|
|---|
| 584 | request.extra_data.data = extra_data;
|
|---|
| 585 | request.extra_len = extra_data_len;
|
|---|
| 586 |
|
|---|
| 587 | wbc_status = wbcRequestResponse(WINBINDD_GETSIDALIASES,
|
|---|
| 588 | &request,
|
|---|
| 589 | &response);
|
|---|
| 590 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 591 |
|
|---|
| 592 | if (response.data.num_entries &&
|
|---|
| 593 | !response.extra_data.data) {
|
|---|
| 594 | wbc_status = WBC_ERR_INVALID_RESPONSE;
|
|---|
| 595 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 596 | }
|
|---|
| 597 |
|
|---|
| 598 | rids = talloc_array(NULL, uint32_t,
|
|---|
| 599 | response.data.num_entries);
|
|---|
| 600 | BAIL_ON_PTR_ERROR(sids, wbc_status);
|
|---|
| 601 |
|
|---|
| 602 | s = (const char *)response.extra_data.data;
|
|---|
| 603 | for (i = 0; i < response.data.num_entries; i++) {
|
|---|
| 604 | char *n = strchr(s, '\n');
|
|---|
| 605 | if (n) {
|
|---|
| 606 | *n = '\0';
|
|---|
| 607 | }
|
|---|
| 608 | wbc_status = wbcStringToSid(s, &sid);
|
|---|
| 609 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 610 | wbc_status = _sid_to_rid(&sid, &rids[i]);
|
|---|
| 611 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 612 | s += strlen(s) + 1;
|
|---|
| 613 | }
|
|---|
| 614 |
|
|---|
| 615 | *num_alias_rids = response.data.num_entries;
|
|---|
| 616 | *alias_rids = rids;
|
|---|
| 617 | rids = NULL;
|
|---|
| 618 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 619 |
|
|---|
| 620 | done:
|
|---|
| 621 | if (sid_string) {
|
|---|
| 622 | wbcFreeMemory(sid_string);
|
|---|
| 623 | }
|
|---|
| 624 | if (extra_data) {
|
|---|
| 625 | talloc_free(extra_data);
|
|---|
| 626 | }
|
|---|
| 627 | if (response.extra_data.data) {
|
|---|
| 628 | free(response.extra_data.data);
|
|---|
| 629 | }
|
|---|
| 630 | if (rids) {
|
|---|
| 631 | talloc_free(rids);
|
|---|
| 632 | }
|
|---|
| 633 |
|
|---|
| 634 | return wbc_status;
|
|---|
| 635 | }
|
|---|
| 636 |
|
|---|
| 637 |
|
|---|
| 638 | /* Lists Users */
|
|---|
| 639 | wbcErr wbcListUsers(const char *domain_name,
|
|---|
| 640 | uint32_t *_num_users,
|
|---|
| 641 | const char ***_users)
|
|---|
| 642 | {
|
|---|
| 643 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 644 | struct winbindd_request request;
|
|---|
| 645 | struct winbindd_response response;
|
|---|
| 646 | uint32_t num_users = 0;
|
|---|
| 647 | const char **users = NULL;
|
|---|
| 648 | const char *next;
|
|---|
| 649 |
|
|---|
| 650 | /* Initialise request */
|
|---|
| 651 |
|
|---|
| 652 | ZERO_STRUCT(request);
|
|---|
| 653 | ZERO_STRUCT(response);
|
|---|
| 654 |
|
|---|
| 655 | if (domain_name) {
|
|---|
| 656 | strncpy(request.domain_name, domain_name,
|
|---|
| 657 | sizeof(request.domain_name)-1);
|
|---|
| 658 | }
|
|---|
| 659 |
|
|---|
| 660 | wbc_status = wbcRequestResponse(WINBINDD_LIST_USERS,
|
|---|
| 661 | &request,
|
|---|
| 662 | &response);
|
|---|
| 663 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 664 |
|
|---|
| 665 | /* Look through extra data */
|
|---|
| 666 |
|
|---|
| 667 | next = (const char *)response.extra_data.data;
|
|---|
| 668 | while (next) {
|
|---|
| 669 | const char **tmp;
|
|---|
| 670 | const char *current = next;
|
|---|
| 671 | char *k = strchr(next, ',');
|
|---|
| 672 | if (k) {
|
|---|
| 673 | k[0] = '\0';
|
|---|
| 674 | next = k+1;
|
|---|
| 675 | } else {
|
|---|
| 676 | next = NULL;
|
|---|
| 677 | }
|
|---|
| 678 |
|
|---|
| 679 | tmp = talloc_realloc(NULL, users,
|
|---|
| 680 | const char *,
|
|---|
| 681 | num_users+1);
|
|---|
| 682 | BAIL_ON_PTR_ERROR(tmp, wbc_status);
|
|---|
| 683 | users = tmp;
|
|---|
| 684 |
|
|---|
| 685 | users[num_users] = talloc_strdup(users, current);
|
|---|
| 686 | BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
|
|---|
| 687 |
|
|---|
| 688 | num_users++;
|
|---|
| 689 | }
|
|---|
| 690 |
|
|---|
| 691 | *_num_users = num_users;
|
|---|
| 692 | *_users = users;
|
|---|
| 693 | users = NULL;
|
|---|
| 694 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 695 |
|
|---|
| 696 | done:
|
|---|
| 697 | if (response.extra_data.data) {
|
|---|
| 698 | free(response.extra_data.data);
|
|---|
| 699 | }
|
|---|
| 700 | if (users) {
|
|---|
| 701 | talloc_free(users);
|
|---|
| 702 | }
|
|---|
| 703 | return wbc_status;
|
|---|
| 704 | }
|
|---|
| 705 |
|
|---|
| 706 | /* Lists Groups */
|
|---|
| 707 | wbcErr wbcListGroups(const char *domain_name,
|
|---|
| 708 | uint32_t *_num_groups,
|
|---|
| 709 | const char ***_groups)
|
|---|
| 710 | {
|
|---|
| 711 | wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
|
|---|
| 712 | struct winbindd_request request;
|
|---|
| 713 | struct winbindd_response response;
|
|---|
| 714 | uint32_t num_groups = 0;
|
|---|
| 715 | const char **groups = NULL;
|
|---|
| 716 | const char *next;
|
|---|
| 717 |
|
|---|
| 718 | /* Initialise request */
|
|---|
| 719 |
|
|---|
| 720 | ZERO_STRUCT(request);
|
|---|
| 721 | ZERO_STRUCT(response);
|
|---|
| 722 |
|
|---|
| 723 | if (domain_name) {
|
|---|
| 724 | strncpy(request.domain_name, domain_name,
|
|---|
| 725 | sizeof(request.domain_name)-1);
|
|---|
| 726 | }
|
|---|
| 727 |
|
|---|
| 728 | wbc_status = wbcRequestResponse(WINBINDD_LIST_GROUPS,
|
|---|
| 729 | &request,
|
|---|
| 730 | &response);
|
|---|
| 731 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 732 |
|
|---|
| 733 | /* Look through extra data */
|
|---|
| 734 |
|
|---|
| 735 | next = (const char *)response.extra_data.data;
|
|---|
| 736 | while (next) {
|
|---|
| 737 | const char **tmp;
|
|---|
| 738 | const char *current = next;
|
|---|
| 739 | char *k = strchr(next, ',');
|
|---|
| 740 | if (k) {
|
|---|
| 741 | k[0] = '\0';
|
|---|
| 742 | next = k+1;
|
|---|
| 743 | } else {
|
|---|
| 744 | next = NULL;
|
|---|
| 745 | }
|
|---|
| 746 |
|
|---|
| 747 | tmp = talloc_realloc(NULL, groups,
|
|---|
| 748 | const char *,
|
|---|
| 749 | num_groups+1);
|
|---|
| 750 | BAIL_ON_PTR_ERROR(tmp, wbc_status);
|
|---|
| 751 | groups = tmp;
|
|---|
| 752 |
|
|---|
| 753 | groups[num_groups] = talloc_strdup(groups, current);
|
|---|
| 754 | BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
|
|---|
| 755 |
|
|---|
| 756 | num_groups++;
|
|---|
| 757 | }
|
|---|
| 758 |
|
|---|
| 759 | *_num_groups = num_groups;
|
|---|
| 760 | *_groups = groups;
|
|---|
| 761 | groups = NULL;
|
|---|
| 762 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 763 |
|
|---|
| 764 | done:
|
|---|
| 765 | if (response.extra_data.data) {
|
|---|
| 766 | free(response.extra_data.data);
|
|---|
| 767 | }
|
|---|
| 768 | if (groups) {
|
|---|
| 769 | talloc_free(groups);
|
|---|
| 770 | }
|
|---|
| 771 | return wbc_status;
|
|---|
| 772 | }
|
|---|
| 773 |
|
|---|
| 774 | wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
|
|---|
| 775 | char **pdomain,
|
|---|
| 776 | char **pfullname,
|
|---|
| 777 | enum wbcSidType *pname_type)
|
|---|
| 778 | {
|
|---|
| 779 | wbcErr wbc_status;
|
|---|
| 780 | char *domain = NULL;
|
|---|
| 781 | char *name = NULL;
|
|---|
| 782 | enum wbcSidType name_type;
|
|---|
| 783 |
|
|---|
| 784 | wbc_status = wbcLookupSid(sid, &domain, &name, &name_type);
|
|---|
| 785 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 786 |
|
|---|
| 787 | if (name_type == WBC_SID_NAME_USER) {
|
|---|
| 788 | uid_t uid;
|
|---|
| 789 | struct passwd *pwd;
|
|---|
| 790 |
|
|---|
| 791 | wbc_status = wbcSidToUid(sid, &uid);
|
|---|
| 792 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 793 |
|
|---|
| 794 | wbc_status = wbcGetpwuid(uid, &pwd);
|
|---|
| 795 | BAIL_ON_WBC_ERROR(wbc_status);
|
|---|
| 796 |
|
|---|
| 797 | wbcFreeMemory(name);
|
|---|
| 798 |
|
|---|
| 799 | name = talloc_strdup(NULL, pwd->pw_gecos);
|
|---|
| 800 | BAIL_ON_PTR_ERROR(name, wbc_status);
|
|---|
| 801 | }
|
|---|
| 802 |
|
|---|
| 803 | wbc_status = WBC_ERR_SUCCESS;
|
|---|
| 804 |
|
|---|
| 805 | done:
|
|---|
| 806 | if (WBC_ERROR_IS_OK(wbc_status)) {
|
|---|
| 807 | *pdomain = domain;
|
|---|
| 808 | *pfullname = name;
|
|---|
| 809 | *pname_type = name_type;
|
|---|
| 810 | } else {
|
|---|
| 811 | wbcFreeMemory(domain);
|
|---|
| 812 | wbcFreeMemory(name);
|
|---|
| 813 | }
|
|---|
| 814 |
|
|---|
| 815 | return wbc_status;
|
|---|
| 816 | }
|
|---|
| 817 |
|
|---|
| 818 | const char* wbcSidTypeString(enum wbcSidType type)
|
|---|
| 819 | {
|
|---|
| 820 | switch (type) {
|
|---|
| 821 | case WBC_SID_NAME_USE_NONE: return "SID_NONE";
|
|---|
| 822 | case WBC_SID_NAME_USER: return "SID_USER";
|
|---|
| 823 | case WBC_SID_NAME_DOM_GRP: return "SID_DOM_GROUP";
|
|---|
| 824 | case WBC_SID_NAME_DOMAIN: return "SID_DOMAIN";
|
|---|
| 825 | case WBC_SID_NAME_ALIAS: return "SID_ALIAS";
|
|---|
| 826 | case WBC_SID_NAME_WKN_GRP: return "SID_WKN_GROUP";
|
|---|
| 827 | case WBC_SID_NAME_DELETED: return "SID_DELETED";
|
|---|
| 828 | case WBC_SID_NAME_INVALID: return "SID_INVALID";
|
|---|
| 829 | case WBC_SID_NAME_UNKNOWN: return "SID_UNKNOWN";
|
|---|
| 830 | case WBC_SID_NAME_COMPUTER: return "SID_COMPUTER";
|
|---|
| 831 | default: return "Unknown type";
|
|---|
| 832 | }
|
|---|
| 833 | }
|
|---|