1/* 2 Unix SMB/CIFS implementation. 3 4 winbind client code 5 6 Copyright (C) Tim Potter 2000 7 Copyright (C) Andrew Tridgell 2000 8 9 This library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Library General Public 11 License as published by the Free Software Foundation; either 12 version 2 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 Library General Public 20 License along with this library; if not, write to the 21 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 Boston, MA 02111-1307, USA. 23*/ 24 25#include "includes.h" 26#include "nsswitch/winbind_nss.h" 27 28#undef DBGC_CLASS 29#define DBGC_CLASS DBGC_WINBIND 30 31NSS_STATUS winbindd_request_response(int req_type, 32 struct winbindd_request *request, 33 struct winbindd_response *response); 34 35/* Call winbindd to convert a name to a sid */ 36 37BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, 38 enum lsa_SidType *name_type) 39{ 40 struct winbindd_request request; 41 struct winbindd_response response; 42 NSS_STATUS result; 43 44 if (!sid || !name_type) 45 return False; 46 47 /* Send off request */ 48 49 ZERO_STRUCT(request); 50 ZERO_STRUCT(response); 51 52 fstrcpy(request.data.name.dom_name, dom_name); 53 fstrcpy(request.data.name.name, name); 54 55 if ((result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, 56 &response)) == NSS_STATUS_SUCCESS) { 57 if (!string_to_sid(sid, response.data.sid.sid)) 58 return False; 59 *name_type = (enum lsa_SidType)response.data.sid.type; 60 } 61 62 return result == NSS_STATUS_SUCCESS; 63} 64 65/* Call winbindd to convert sid to name */ 66 67BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, 68 const char **domain, const char **name, 69 enum lsa_SidType *name_type) 70{ 71 struct winbindd_request request; 72 struct winbindd_response response; 73 NSS_STATUS result; 74 75 /* Initialise request */ 76 77 ZERO_STRUCT(request); 78 ZERO_STRUCT(response); 79 80 fstrcpy(request.data.sid, sid_string_static(sid)); 81 82 /* Make request */ 83 84 result = winbindd_request_response(WINBINDD_LOOKUPSID, &request, 85 &response); 86 87 if (result != NSS_STATUS_SUCCESS) { 88 return False; 89 } 90 91 /* Copy out result */ 92 93 if (domain != NULL) { 94 *domain = talloc_strdup(mem_ctx, response.data.name.dom_name); 95 if (*domain == NULL) { 96 DEBUG(0, ("talloc failed\n")); 97 return False; 98 } 99 } 100 if (name != NULL) { 101 *name = talloc_strdup(mem_ctx, response.data.name.name); 102 if (*name == NULL) { 103 DEBUG(0, ("talloc failed\n")); 104 return False; 105 } 106 } 107 108 *name_type = (enum lsa_SidType)response.data.name.type; 109 110 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", 111 sid_string_static(sid), response.data.name.dom_name, 112 response.data.name.name)); 113 return True; 114} 115 116BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx, 117 const DOM_SID *domain_sid, 118 int num_rids, uint32 *rids, 119 const char **domain_name, 120 const char ***names, enum lsa_SidType **types) 121{ 122 size_t i, buflen; 123 ssize_t len; 124 char *ridlist; 125 char *p; 126 struct winbindd_request request; 127 struct winbindd_response response; 128 NSS_STATUS result; 129 130 if (num_rids == 0) { 131 return False; 132 } 133 134 /* Initialise request */ 135 136 ZERO_STRUCT(request); 137 ZERO_STRUCT(response); 138 139 fstrcpy(request.data.sid, sid_string_static(domain_sid)); 140 141 len = 0; 142 buflen = 0; 143 ridlist = NULL; 144 145 for (i=0; i<num_rids; i++) { 146 sprintf_append(mem_ctx, &ridlist, &len, &buflen, 147 "%ld\n", rids[i]); 148 } 149 150 if ((num_rids != 0) && (ridlist == NULL)) { 151 return False; 152 } 153 154 request.extra_data.data = ridlist; 155 request.extra_len = strlen(ridlist)+1; 156 157 result = winbindd_request_response(WINBINDD_LOOKUPRIDS, 158 &request, &response); 159 160 TALLOC_FREE(ridlist); 161 162 if (result != NSS_STATUS_SUCCESS) { 163 return False; 164 } 165 166 *domain_name = talloc_strdup(mem_ctx, response.data.domain_name); 167 168 if (num_rids) { 169 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids); 170 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids); 171 172 if ((*names == NULL) || (*types == NULL)) { 173 goto fail; 174 } 175 } else { 176 *names = NULL; 177 *types = NULL; 178 } 179 180 p = (char *)response.extra_data.data; 181 182 for (i=0; i<num_rids; i++) { 183 char *q; 184 185 if (*p == '\0') { 186 DEBUG(10, ("Got invalid reply: %s\n", 187 (char *)response.extra_data.data)); 188 goto fail; 189 } 190 191 (*types)[i] = (enum lsa_SidType)strtoul(p, &q, 10); 192 193 if (*q != ' ') { 194 DEBUG(10, ("Got invalid reply: %s\n", 195 (char *)response.extra_data.data)); 196 goto fail; 197 } 198 199 p = q+1; 200 201 q = strchr(p, '\n'); 202 if (q == NULL) { 203 DEBUG(10, ("Got invalid reply: %s\n", 204 (char *)response.extra_data.data)); 205 goto fail; 206 } 207 208 *q = '\0'; 209 210 (*names)[i] = talloc_strdup(*names, p); 211 212 p = q+1; 213 } 214 215 if (*p != '\0') { 216 DEBUG(10, ("Got invalid reply: %s\n", 217 (char *)response.extra_data.data)); 218 goto fail; 219 } 220 221 SAFE_FREE(response.extra_data.data); 222 223 return True; 224 225 fail: 226 TALLOC_FREE(*names); 227 TALLOC_FREE(*types); 228 return False; 229} 230 231/* Call winbindd to convert SID to uid */ 232 233BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid) 234{ 235 struct winbindd_request request; 236 struct winbindd_response response; 237 int result; 238 fstring sid_str; 239 240 if (!puid) 241 return False; 242 243 /* Initialise request */ 244 245 ZERO_STRUCT(request); 246 ZERO_STRUCT(response); 247 248 sid_to_string(sid_str, sid); 249 fstrcpy(request.data.sid, sid_str); 250 251 /* Make request */ 252 253 result = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response); 254 255 /* Copy out result */ 256 257 if (result == NSS_STATUS_SUCCESS) { 258 *puid = response.data.uid; 259 } 260 261 return (result == NSS_STATUS_SUCCESS); 262} 263 264/* Call winbindd to convert uid to sid */ 265 266BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid) 267{ 268 struct winbindd_request request; 269 struct winbindd_response response; 270 int result; 271 272 if (!sid) 273 return False; 274 275 /* Initialise request */ 276 277 ZERO_STRUCT(request); 278 ZERO_STRUCT(response); 279 280 request.data.uid = uid; 281 282 /* Make request */ 283 284 result = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response); 285 286 /* Copy out result */ 287 288 if (result == NSS_STATUS_SUCCESS) { 289 if (!string_to_sid(sid, response.data.sid.sid)) 290 return False; 291 } else { 292 sid_copy(sid, &global_sid_NULL); 293 } 294 295 return (result == NSS_STATUS_SUCCESS); 296} 297 298/* Call winbindd to convert SID to gid */ 299 300BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid) 301{ 302 struct winbindd_request request; 303 struct winbindd_response response; 304 int result; 305 fstring sid_str; 306 307 if (!pgid) 308 return False; 309 310 /* Initialise request */ 311 312 ZERO_STRUCT(request); 313 ZERO_STRUCT(response); 314 315 sid_to_string(sid_str, sid); 316 fstrcpy(request.data.sid, sid_str); 317 318 /* Make request */ 319 320 result = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response); 321 322 /* Copy out result */ 323 324 if (result == NSS_STATUS_SUCCESS) { 325 *pgid = response.data.gid; 326 } 327 328 return (result == NSS_STATUS_SUCCESS); 329} 330 331/* Call winbindd to convert gid to sid */ 332 333BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid) 334{ 335 struct winbindd_request request; 336 struct winbindd_response response; 337 int result; 338 339 if (!sid) 340 return False; 341 342 /* Initialise request */ 343 344 ZERO_STRUCT(request); 345 ZERO_STRUCT(response); 346 347 request.data.gid = gid; 348 349 /* Make request */ 350 351 result = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response); 352 353 /* Copy out result */ 354 355 if (result == NSS_STATUS_SUCCESS) { 356 if (!string_to_sid(sid, response.data.sid.sid)) 357 return False; 358 } else { 359 sid_copy(sid, &global_sid_NULL); 360 } 361 362 return (result == NSS_STATUS_SUCCESS); 363} 364 365/* Call winbindd to convert SID to uid */ 366 367BOOL winbind_sids_to_unixids(struct id_map *ids, int num_ids) 368{ 369 struct winbindd_request request; 370 struct winbindd_response response; 371 int result; 372 DOM_SID *sids; 373 int i; 374 375 /* Initialise request */ 376 377 ZERO_STRUCT(request); 378 ZERO_STRUCT(response); 379 380 request.extra_len = num_ids * sizeof(DOM_SID); 381 382 sids = (DOM_SID *)SMB_MALLOC(request.extra_len); 383 for (i = 0; i < num_ids; i++) { 384 sid_copy(&sids[i], ids[i].sid); 385 } 386 387 request.extra_data.data = (char *)sids; 388 389 /* Make request */ 390 391 result = winbindd_request_response(WINBINDD_SIDS_TO_XIDS, &request, &response); 392 393 /* Copy out result */ 394 395 if (result == NSS_STATUS_SUCCESS) { 396 struct unixid *wid = (struct unixid *)response.extra_data.data; 397 398 for (i = 0; i < num_ids; i++) { 399 if (wid[i].type == -1) { 400 ids[i].status = ID_UNMAPPED; 401 } else { 402 ids[i].status = ID_MAPPED; 403 ids[i].xid.type = wid[i].type; 404 ids[i].xid.id = wid[i].id; 405 } 406 } 407 } 408 409 SAFE_FREE(request.extra_data.data); 410 SAFE_FREE(response.extra_data.data); 411 412 return (result == NSS_STATUS_SUCCESS); 413} 414 415BOOL winbind_idmap_dump_maps(TALLOC_CTX *memctx, const char *file) 416{ 417 struct winbindd_request request; 418 struct winbindd_response response; 419 int result; 420 421 ZERO_STRUCT(request); 422 ZERO_STRUCT(response); 423 424 request.extra_data.data = SMB_STRDUP(file); 425 request.extra_len = strlen(request.extra_data.data) + 1; 426 427 result = winbindd_request_response(WINBINDD_DUMP_MAPS, &request, &response); 428 429 SAFE_FREE(request.extra_data.data); 430 return (result == NSS_STATUS_SUCCESS); 431} 432 433BOOL winbind_allocate_uid(uid_t *uid) 434{ 435 struct winbindd_request request; 436 struct winbindd_response response; 437 int result; 438 439 /* Initialise request */ 440 441 ZERO_STRUCT(request); 442 ZERO_STRUCT(response); 443 444 /* Make request */ 445 446 result = winbindd_request_response(WINBINDD_ALLOCATE_UID, 447 &request, &response); 448 449 if (result != NSS_STATUS_SUCCESS) 450 return False; 451 452 /* Copy out result */ 453 *uid = response.data.uid; 454 455 return True; 456} 457 458BOOL winbind_allocate_gid(gid_t *gid) 459{ 460 struct winbindd_request request; 461 struct winbindd_response response; 462 int result; 463 464 /* Initialise request */ 465 466 ZERO_STRUCT(request); 467 ZERO_STRUCT(response); 468 469 /* Make request */ 470 471 result = winbindd_request_response(WINBINDD_ALLOCATE_GID, 472 &request, &response); 473 474 if (result != NSS_STATUS_SUCCESS) 475 return False; 476 477 /* Copy out result */ 478 *gid = response.data.gid; 479 480 return True; 481} 482 483BOOL winbind_set_mapping(const struct id_map *map) 484{ 485 struct winbindd_request request; 486 struct winbindd_response response; 487 int result; 488 489 /* Initialise request */ 490 491 ZERO_STRUCT(request); 492 ZERO_STRUCT(response); 493 494 /* Make request */ 495 496 request.data.dual_idmapset.id = map->xid.id; 497 request.data.dual_idmapset.type = map->xid.type; 498 sid_to_string(request.data.dual_idmapset.sid, map->sid); 499 500 result = winbindd_request_response(WINBINDD_SET_MAPPING, &request, &response); 501 502 return (result == NSS_STATUS_SUCCESS); 503} 504 505BOOL winbind_set_uid_hwm(unsigned long id) 506{ 507 struct winbindd_request request; 508 struct winbindd_response response; 509 int result; 510 511 /* Initialise request */ 512 513 ZERO_STRUCT(request); 514 ZERO_STRUCT(response); 515 516 /* Make request */ 517 518 request.data.dual_idmapset.id = id; 519 request.data.dual_idmapset.type = ID_TYPE_UID; 520 521 result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response); 522 523 return (result == NSS_STATUS_SUCCESS); 524} 525 526BOOL winbind_set_gid_hwm(unsigned long id) 527{ 528 struct winbindd_request request; 529 struct winbindd_response response; 530 int result; 531 532 /* Initialise request */ 533 534 ZERO_STRUCT(request); 535 ZERO_STRUCT(response); 536 537 /* Make request */ 538 539 request.data.dual_idmapset.id = id; 540 request.data.dual_idmapset.type = ID_TYPE_GID; 541 542 result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response); 543 544 return (result == NSS_STATUS_SUCCESS); 545} 546 547/********************************************************************** 548 simple wrapper function to see if winbindd is alive 549**********************************************************************/ 550 551BOOL winbind_ping( void ) 552{ 553 NSS_STATUS result; 554 555 result = winbindd_request_response(WINBINDD_PING, NULL, NULL); 556 557 return result == NSS_STATUS_SUCCESS; 558} 559 560/********************************************************************** 561 Is a domain trusted? 562 563 result == NSS_STATUS_UNAVAIL: winbind not around 564 result == NSS_STATUS_NOTFOUND: winbind around, but domain missing 565 566 Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off and 567 when winbind return WINBINDD_ERROR. So the semantics of this routine depends 568 on winbind_on. Grepping for winbind_off I just found 3 places where winbind 569 is turned off, and this does not conflict (as far as I have seen) with the 570 callers of is_trusted_domains. 571 572 I *hate* global variables.... 573 574 Volker 575 576**********************************************************************/ 577 578NSS_STATUS wb_is_trusted_domain(const char *domain) 579{ 580 struct winbindd_request request; 581 struct winbindd_response response; 582 583 /* Call winbindd */ 584 585 ZERO_STRUCT(request); 586 ZERO_STRUCT(response); 587 588 fstrcpy(request.domain_name, domain); 589 590 return winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response); 591} 592