Changeset 988 for vendor/current/nsswitch/wb_common.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/nsswitch/wb_common.c
r860 r988 7 7 Copyright (C) Andrew Tridgell 2000 8 8 Copyright (C) Andrew Bartlett 2002 9 Copyright (C) Matthew Newton 2015 9 10 10 11 … … 27 28 #include "winbind_client.h" 28 29 29 /* Global variables. These are effectively the client state information */ 30 31 int winbindd_fd = -1; /* fd for winbindd socket */ 32 static int is_privileged = 0; 30 /* Global context */ 31 32 struct winbindd_context { 33 int winbindd_fd; /* winbind file descriptor */ 34 bool is_privileged; /* using the privileged socket? */ 35 pid_t our_pid; /* calling process pid */ 36 }; 37 38 static struct winbindd_context wb_global_ctx = { 39 .winbindd_fd = -1, 40 .is_privileged = 0, 41 .our_pid = 0 42 }; 33 43 34 44 /* Free a response structure */ … … 65 75 /* Close established socket */ 66 76 67 #if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR 77 static void winbind_close_sock(struct winbindd_context *ctx) 78 { 79 if (!ctx) { 80 return; 81 } 82 83 if (ctx->winbindd_fd != -1) { 84 close(ctx->winbindd_fd); 85 ctx->winbindd_fd = -1; 86 } 87 } 88 89 /* Destructor for global context to ensure fd is closed */ 90 91 #if HAVE_DESTRUCTOR_ATTRIBUTE 68 92 __attribute__((destructor)) 69 93 #endif 70 static void winbind_close_sock(void) 71 { 72 if (winbindd_fd != -1) { 73 close(winbindd_fd); 74 winbindd_fd = -1; 75 } 94 static void winbind_destructor(void) 95 { 96 winbind_close_sock(&wb_global_ctx); 76 97 } 77 98 … … 169 190 } 170 191 192 /** 193 * @internal 194 * 195 * @brief Check if we talk to the priviliged pipe which should be owned by root. 196 * 197 * This checks if we have uid_wrapper running and if this is the case it will 198 * allow one to connect to the winbind privileged pipe even it is not owned by root. 199 * 200 * @param[in] uid The uid to check if we can safely talk to the pipe. 201 * 202 * @return If we have access it returns true, else false. 203 */ 204 static bool winbind_privileged_pipe_is_root(uid_t uid) 205 { 206 if (uid == 0) { 207 return true; 208 } 209 210 if (uid_wrapper_enabled()) { 211 return true; 212 } 213 214 return false; 215 } 216 171 217 /* Connect to winbindd socket */ 172 218 … … 175 221 struct sockaddr_un sunaddr; 176 222 struct stat st; 177 char *path = NULL;178 223 int fd; 179 224 int wait_time; 180 225 int slept; 226 int ret; 181 227 182 228 /* Check permissions on unix socket directory */ … … 187 233 } 188 234 235 /* 236 * This tells us that the pipe is owned by a privileged 237 * process, as we will be sending passwords to it. 238 */ 189 239 if (!S_ISDIR(st.st_mode) || 190 (st.st_uid != 0 && st.st_uid != geteuid())) {240 !winbind_privileged_pipe_is_root(st.st_uid)) { 191 241 errno = ENOENT; 192 242 return -1; … … 195 245 /* Connect to socket */ 196 246 197 if (asprintf(&path, "%s/%s", dir, WINBINDD_SOCKET_NAME) < 0) { 198 return -1; 199 } 200 201 ZERO_STRUCT(sunaddr); 202 sunaddr.sun_family = AF_UNIX; 203 strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); 247 sunaddr = (struct sockaddr_un) { .sun_family = AF_UNIX }; 248 249 ret = snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), 250 "%s/%s", dir, WINBINDD_SOCKET_NAME); 251 if ((ret == -1) || (ret >= sizeof(sunaddr.sun_path))) { 252 errno = ENAMETOOLONG; 253 return -1; 254 } 204 255 205 256 /* If socket file doesn't exist, don't bother trying to connect … … 207 258 the winbindd daemon is not running. */ 208 259 209 if (lstat( path, &st) == -1) {260 if (lstat(sunaddr.sun_path, &st) == -1) { 210 261 errno = ENOENT; 211 SAFE_FREE(path); 212 return -1; 213 } 214 215 SAFE_FREE(path); 262 return -1; 263 } 264 216 265 /* Check permissions on unix socket file */ 217 266 267 /* 268 * This tells us that the pipe is owned by a privileged 269 * process, as we will be sending passwords to it. 270 */ 218 271 if (!S_ISSOCK(st.st_mode) || 219 (st.st_uid != 0 && st.st_uid != geteuid())) {272 !winbind_privileged_pipe_is_root(st.st_uid)) { 220 273 errno = ENOENT; 221 274 return -1; … … 237 290 wait_time += slept) { 238 291 struct pollfd pfd; 239 int ret;240 292 int connect_errno = 0; 241 293 socklen_t errnosize; … … 287 339 static const char *winbindd_socket_dir(void) 288 340 { 289 #ifdef SOCKET_WRAPPER 290 const char *env_dir;291 292 env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR);293 if (env_dir) {294 return env_dir;295 }296 #endif 341 if (nss_wrapper_enabled()) { 342 const char *env_dir; 343 344 env_dir = getenv("SELFTEST_WINBINDD_SOCKET_DIR"); 345 if (env_dir != NULL) { 346 return env_dir; 347 } 348 } 297 349 298 350 return WINBINDD_SOCKET_DIR; … … 301 353 /* Connect to winbindd socket */ 302 354 303 static int winbind_open_pipe_sock(int recursing, int need_priv) 355 static int winbind_open_pipe_sock(struct winbindd_context *ctx, 356 int recursing, int need_priv) 304 357 { 305 358 #ifdef HAVE_UNIXSOCKET 306 static pid_t our_pid;307 359 struct winbindd_request request; 308 360 struct winbindd_response response; 361 309 362 ZERO_STRUCT(request); 310 363 ZERO_STRUCT(response); 311 364 312 if (our_pid != getpid()) { 313 winbind_close_sock(); 314 our_pid = getpid(); 315 } 316 317 if ((need_priv != 0) && (is_privileged == 0)) { 318 winbind_close_sock(); 319 } 320 321 if (winbindd_fd != -1) { 322 return winbindd_fd; 365 if (!ctx) { 366 return -1; 367 } 368 369 if (ctx->our_pid != getpid()) { 370 winbind_close_sock(ctx); 371 ctx->our_pid = getpid(); 372 } 373 374 if ((need_priv != 0) && (ctx->is_privileged == 0)) { 375 winbind_close_sock(ctx); 376 } 377 378 if (ctx->winbindd_fd != -1) { 379 return ctx->winbindd_fd; 323 380 } 324 381 … … 327 384 } 328 385 329 if ((winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir())) == -1) { 330 return -1; 331 } 332 333 is_privileged = 0; 386 ctx->winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir()); 387 388 if (ctx->winbindd_fd == -1) { 389 return -1; 390 } 391 392 ctx->is_privileged = 0; 334 393 335 394 /* version-check the socket */ 336 395 337 396 request.wb_flags = WBFLAG_RECURSE; 338 if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { 339 winbind_close_sock(); 397 if ((winbindd_request_response(ctx, WINBINDD_INTERFACE_VERSION, &request, 398 &response) != NSS_STATUS_SUCCESS) || 399 (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { 400 winbind_close_sock(ctx); 340 401 return -1; 341 402 } … … 344 405 345 406 request.wb_flags = WBFLAG_RECURSE; 346 if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { 407 408 /* Note that response needs to be initialized to avoid 409 * crashing on clean up after WINBINDD_PRIV_PIPE_DIR call failed 410 * as interface version (from the first request) returned as a fstring, 411 * thus response.extra_data.data will not be NULL even though 412 * winbindd response did not write over it due to a failure */ 413 ZERO_STRUCT(response); 414 if (winbindd_request_response(ctx, WINBINDD_PRIV_PIPE_DIR, &request, 415 &response) == NSS_STATUS_SUCCESS) { 347 416 int fd; 348 if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) { 349 close(winbindd_fd); 350 winbindd_fd = fd; 351 is_privileged = 1; 352 } 353 } 354 355 if ((need_priv != 0) && (is_privileged == 0)) { 417 fd = winbind_named_pipe_sock((char *)response.extra_data.data); 418 if (fd != -1) { 419 close(ctx->winbindd_fd); 420 ctx->winbindd_fd = fd; 421 ctx->is_privileged = 1; 422 } 423 } 424 425 if ((need_priv != 0) && (ctx->is_privileged == 0)) { 356 426 return -1; 357 427 } … … 359 429 SAFE_FREE(response.extra_data.data); 360 430 361 return winbindd_fd;431 return ctx->winbindd_fd; 362 432 #else 363 433 return -1; … … 367 437 /* Write data to winbindd socket */ 368 438 369 static int winbind_write_sock( void *buffer, int count, int recursing,370 int need_priv)371 { 372 int result, nwritten;439 static int winbind_write_sock(struct winbindd_context *ctx, void *buffer, 440 int count, int recursing, int need_priv) 441 { 442 int fd, result, nwritten; 373 443 374 444 /* Open connection to winbind daemon */ … … 376 446 restart: 377 447 378 if (winbind_open_pipe_sock(recursing, need_priv) == -1) { 448 fd = winbind_open_pipe_sock(ctx, recursing, need_priv); 449 if (fd == -1) { 379 450 errno = ENOENT; 380 451 return -1; … … 392 463 call would not block by calling poll(). */ 393 464 394 pfd.fd = winbindd_fd;465 pfd.fd = fd; 395 466 pfd.events = POLLIN|POLLOUT|POLLHUP; 396 467 397 468 ret = poll(&pfd, 1, -1); 398 469 if (ret == -1) { 399 winbind_close_sock( );470 winbind_close_sock(ctx); 400 471 return -1; /* poll error */ 401 472 } … … 407 478 /* Pipe has closed on remote end */ 408 479 409 winbind_close_sock( );480 winbind_close_sock(ctx); 410 481 goto restart; 411 482 } … … 413 484 /* Do the write */ 414 485 415 result = write(winbindd_fd, 416 (char *)buffer + nwritten, 486 result = write(fd, (char *)buffer + nwritten, 417 487 count - nwritten); 418 488 … … 421 491 /* Write failed */ 422 492 423 winbind_close_sock( );493 winbind_close_sock(ctx); 424 494 return -1; 425 495 } … … 433 503 /* Read data from winbindd socket */ 434 504 435 static int winbind_read_sock(void *buffer, int count) 436 { 505 static int winbind_read_sock(struct winbindd_context *ctx, 506 void *buffer, int count) 507 { 508 int fd; 437 509 int nread = 0; 438 510 int total_time = 0; 439 511 440 if (winbindd_fd == -1) { 512 fd = winbind_open_pipe_sock(ctx, false, false); 513 if (fd == -1) { 441 514 return -1; 442 515 } … … 450 523 call would not block by calling poll(). */ 451 524 452 pfd.fd = winbindd_fd;525 pfd.fd = fd; 453 526 pfd.events = POLLIN|POLLHUP; 454 527 … … 457 530 ret = poll(&pfd, 1, 5000); 458 531 if (ret == -1) { 459 winbind_close_sock( );532 winbind_close_sock(ctx); 460 533 return -1; /* poll error */ 461 534 } … … 463 536 if (ret == 0) { 464 537 /* Not ready for read yet... */ 465 if (total_time >= 30 ) {538 if (total_time >= 300) { 466 539 /* Timeout */ 467 winbind_close_sock( );540 winbind_close_sock(ctx); 468 541 return -1; 469 542 } … … 476 549 /* Do the Read */ 477 550 478 int result = read( winbindd_fd, (char *)buffer + nread,551 int result = read(fd, (char *)buffer + nread, 479 552 count - nread); 480 553 … … 485 558 transaction has failed half way through. */ 486 559 487 winbind_close_sock( );560 winbind_close_sock(ctx); 488 561 return -1; 489 562 } … … 499 572 /* Read reply */ 500 573 501 static int winbindd_read_reply(struct winbindd_response *response) 574 static int winbindd_read_reply(struct winbindd_context *ctx, 575 struct winbindd_response *response) 502 576 { 503 577 int result1, result2 = 0; … … 509 583 /* Read fixed length response */ 510 584 511 result1 = winbind_read_sock( response,585 result1 = winbind_read_sock(ctx, response, 512 586 sizeof(struct winbindd_response)); 513 if (result1 == -1) {514 return -1;515 }516 517 if (response->length < sizeof(struct winbindd_response)) {518 return -1;519 }520 587 521 588 /* We actually send the pointer value of the extra_data field from … … 525 592 response->extra_data.data = NULL; 526 593 594 if (result1 == -1) { 595 return -1; 596 } 597 598 if (response->length < sizeof(struct winbindd_response)) { 599 return -1; 600 } 601 527 602 /* Read variable length response */ 528 603 … … 537 612 } 538 613 539 result2 = winbind_read_sock( response->extra_data.data,614 result2 = winbind_read_sock(ctx, response->extra_data.data, 540 615 extra_data_len); 541 616 if (result2 == -1) { … … 554 629 */ 555 630 556 NSS_STATUS winbindd_send_request(int req_type, int need_priv, 631 NSS_STATUS winbindd_send_request(struct winbindd_context *ctx, 632 int req_type, int need_priv, 557 633 struct winbindd_request *request) 558 634 { … … 574 650 winbindd_init_request(request, req_type); 575 651 576 if (winbind_write_sock( request, sizeof(*request),652 if (winbind_write_sock(ctx, request, sizeof(*request), 577 653 request->wb_flags & WBFLAG_RECURSE, 578 654 need_priv) == -1) … … 585 661 586 662 if ((request->extra_len != 0) && 587 (winbind_write_sock( request->extra_data.data,663 (winbind_write_sock(ctx, request->extra_data.data, 588 664 request->extra_len, 589 665 request->wb_flags & WBFLAG_RECURSE, … … 603 679 */ 604 680 605 NSS_STATUS winbindd_get_response(struct winbindd_response *response) 681 NSS_STATUS winbindd_get_response(struct winbindd_context *ctx, 682 struct winbindd_response *response) 606 683 { 607 684 struct winbindd_response lresponse; … … 615 692 616 693 /* Wait for reply */ 617 if (winbindd_read_reply( response) == -1) {694 if (winbindd_read_reply(ctx, response) == -1) { 618 695 /* Set ENOENT for consistency. Required by some apps */ 619 696 errno = ENOENT; … … 637 714 /* Handle simple types of requests */ 638 715 639 NSS_STATUS winbindd_request_response(int req_type, 640 struct winbindd_request *request, 641 struct winbindd_response *response) 716 NSS_STATUS winbindd_request_response(struct winbindd_context *ctx, 717 int req_type, 718 struct winbindd_request *request, 719 struct winbindd_response *response) 642 720 { 643 721 NSS_STATUS status = NSS_STATUS_UNAVAIL; 644 int count = 0; 645 646 while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { 647 status = winbindd_send_request(req_type, 0, request); 648 if (status != NSS_STATUS_SUCCESS) 649 return(status); 650 status = winbindd_get_response(response); 651 count += 1; 652 } 722 struct winbindd_context *wb_ctx = ctx; 723 724 if (ctx == NULL) { 725 wb_ctx = &wb_global_ctx; 726 } 727 728 status = winbindd_send_request(wb_ctx, req_type, 0, request); 729 if (status != NSS_STATUS_SUCCESS) 730 return (status); 731 status = winbindd_get_response(wb_ctx, response); 653 732 654 733 return status; 655 734 } 656 735 657 NSS_STATUS winbindd_priv_request_response(int req_type, 736 NSS_STATUS winbindd_priv_request_response(struct winbindd_context *ctx, 737 int req_type, 658 738 struct winbindd_request *request, 659 739 struct winbindd_response *response) 660 740 { 661 741 NSS_STATUS status = NSS_STATUS_UNAVAIL; 662 int count = 0; 663 664 while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { 665 status = winbindd_send_request(req_type, 1, request); 666 if (status != NSS_STATUS_SUCCESS) 667 return(status); 668 status = winbindd_get_response(response); 669 count += 1; 670 } 742 struct winbindd_context *wb_ctx = ctx; 743 744 if (ctx == NULL) { 745 wb_ctx = &wb_global_ctx; 746 } 747 748 status = winbindd_send_request(wb_ctx, req_type, 1, request); 749 if (status != NSS_STATUS_SUCCESS) 750 return (status); 751 status = winbindd_get_response(wb_ctx, response); 671 752 672 753 return status; 673 754 } 755 756 /* Create and free winbindd context */ 757 758 struct winbindd_context *winbindd_ctx_create(void) 759 { 760 struct winbindd_context *ctx; 761 762 ctx = calloc(1, sizeof(struct winbindd_context)); 763 764 if (!ctx) { 765 return NULL; 766 } 767 768 ctx->winbindd_fd = -1; 769 770 return ctx; 771 } 772 773 void winbindd_ctx_free(struct winbindd_context *ctx) 774 { 775 winbind_close_sock(ctx); 776 free(ctx); 777 }
Note:
See TracChangeset
for help on using the changeset viewer.