Changeset 38545 in vbox for trunk/src/VBox/Additions/common/pam
- Timestamp:
- Aug 26, 2011 12:32:27 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/pam/pam_vbox.cpp
r38486 r38545 47 47 #include <iprt/stream.h> 48 48 #include <iprt/string.h> 49 #include <iprt/thread.h> 50 #include <iprt/time.h> 49 51 50 52 #include <VBox/VBoxGuestLib.h> … … 65 67 static int g_verbosity = 0; 66 68 #endif 69 70 /** 71 * User-provided thread data for the credentials waiting thread. 72 */ 73 typedef struct PAMVBOXTHREAD 74 { 75 /** The PAM handle. */ 76 pam_handle_t *hPAM; 77 /** The timeout (in ms) to wait for credentials. */ 78 uint32_t uTimeoutMS; 79 /** The overall result of the thread operation. */ 80 int rc; 81 } PAMVBOXTHREAD, *PPAMVBOXTHREAD; 67 82 68 83 /** … … 261 276 if (RT_FAILURE(rc)) 262 277 { 263 if (rc == VERR_NOT_FOUND) 278 if (rc != VERR_NOT_FOUND) 279 pam_vbox_error(hPAM, "pam_vbox_check_creds: could not query for credentials! rc=%Rrc. Aborting\n", rc); 280 #ifdef DEBUG 281 else 264 282 pam_vbox_log(hPAM, "pam_vbox_check_creds: no credentials available\n"); 265 else 266 pam_vbox_error(hPAM, "pam_vbox_check_creds: could not query for credentials! rc=%Rrc. Aborting\n", rc); 283 #endif 267 284 } 268 285 else … … 300 317 pam_vbox_error(hPAM, "pam_vbox_check_creds: could not set password! pamrc=%d, msg=%s. Aborting\n", 301 318 pamrc, pam_strerror(hPAM, pamrc)); 319 302 320 } 303 321 /** @todo Add handling domains as well. */ 304 305 322 VbglR3CredentialsDestroy(pszUsername, pszPassword, pszDomain, 306 323 3 /* Three wipe passes */); 307 pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with pamrc=%d, msg=%s\n", 308 pamrc, pam_strerror(hPAM, pamrc)); 309 } 310 } 311 324 pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with pamrc=%d, msg=%s\n", 325 pamrc, pam_strerror(hPAM, pamrc)); 326 } 327 } 328 329 #ifdef DEBUG 312 330 pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with rc=%Rrc\n", rc); 331 #endif 313 332 return rc; 314 333 } 315 334 335 316 336 #ifdef VBOX_WITH_GUEST_PROPS 317 static int pam_vbox_wait_for_creds(pam_handle_t *hPAM, uint32_t uClientID, uint32_t uTimeoutMS)318 {319 int rc;320 321 /* The buffer for storing the data and its initial size. We leave a bit322 * of space here in case the maximum values are raised. */323 void *pvBuf = NULL;324 uint32_t cbBuf = MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN + _1K;325 326 pam_vbox_log(hPAM, "Waiting for credentials (%dms) ...\n", uTimeoutMS);327 328 int i;329 for (i = 0; i < 10; i++)330 {331 void *pvTmpBuf = RTMemRealloc(pvBuf, cbBuf);332 if (pvTmpBuf)333 {334 char *pszName = NULL;335 char *pszValue = NULL;336 uint64_t u64TimestampOut = 0;337 char *pszFlags = NULL;338 339 pvBuf = pvTmpBuf;340 rc = VbglR3GuestPropWait(uClientID, "/VirtualBox/GuestAdd/PAM/CredsChanged", pvBuf, cbBuf,341 0 /* Last timestamp; just wait for next event */, uTimeoutMS,342 &pszName, &pszValue, &u64TimestampOut,343 &pszFlags, &cbBuf);344 }345 else346 rc = VERR_NO_MEMORY;347 348 switch (rc)349 {350 case VINF_SUCCESS:351 pam_vbox_error(hPAM, "Got notification for supplied credentials\n");352 break;353 354 case VERR_BUFFER_OVERFLOW:355 {356 /* Buffer too small, try it with a bigger one next time. */357 cbBuf += _1K;358 continue; /* Try next round. */359 }360 361 case VERR_INTERRUPTED:362 pam_vbox_error(hPAM, "The credentials notification request timed out or was interrupted\n");363 break;364 365 case VERR_TIMEOUT:366 pam_vbox_error(hPAM, "Credentials did not arrive within time (%dms)\n", uTimeoutMS);367 break;368 369 case VERR_TOO_MUCH_DATA:370 pam_vbox_error(hPAM, "Temporarily unable to get credentials notification\n");371 break;372 373 default:374 pam_vbox_error(hPAM, "The credentials notification request failed with rc=%Rrc\n", rc);375 break;376 }377 378 /* Everything except VERR_BUFFER_OVERLOW makes us bail out ... */379 break;380 }381 382 pam_vbox_log(hPAM, "Waiting for credentials returned with rc=%Rrc\n", rc);383 return rc;384 }385 386 337 static int pam_vbox_read_prop(pam_handle_t *hPAM, uint32_t uClientID, 387 338 const char *pszKey, bool fReadOnly, 388 339 char *pszValue, size_t cbValue) 389 340 { 341 AssertPtrReturn(hPAM, VERR_INVALID_POINTER); 390 342 AssertReturn(uClientID, VERR_INVALID_PARAMETER); 391 343 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); … … 474 426 return rc; 475 427 } 476 #endif 428 429 430 static int pam_vbox_wait_prop(pam_handle_t *hPAM, uint32_t uClientID, 431 const char *pszKey, uint32_t uTimeoutMS) 432 { 433 AssertPtrReturn(hPAM, VERR_INVALID_POINTER); 434 AssertReturn(uClientID, VERR_INVALID_PARAMETER); 435 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 436 437 int rc; 438 439 /* The buffer for storing the data and its initial size. We leave a bit 440 * of space here in case the maximum values are raised. */ 441 void *pvBuf = NULL; 442 uint32_t cbBuf = MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN + _1K; 443 444 for (int i = 0; i < 10; i++) 445 { 446 void *pvTmpBuf = RTMemRealloc(pvBuf, cbBuf); 447 if (pvTmpBuf) 448 { 449 char *pszName = NULL; 450 char *pszValue = NULL; 451 uint64_t u64TimestampOut = 0; 452 char *pszFlags = NULL; 453 454 pvBuf = pvTmpBuf; 455 rc = VbglR3GuestPropWait(uClientID, pszKey, pvBuf, cbBuf, 456 0 /* Last timestamp; just wait for next event */, uTimeoutMS, 457 &pszName, &pszValue, &u64TimestampOut, 458 &pszFlags, &cbBuf); 459 } 460 else 461 rc = VERR_NO_MEMORY; 462 463 if (rc == VERR_BUFFER_OVERFLOW) 464 { 465 /* Buffer too small, try it with a bigger one next time. */ 466 cbBuf += _1K; 467 continue; /* Try next round. */ 468 } 469 470 /* Everything except VERR_BUFFER_OVERLOW makes us bail out ... */ 471 break; 472 } 473 474 return rc; 475 } 476 #endif 477 478 479 static DECLCALLBACK(int) pam_vbox_wait_thread(RTTHREAD ThreadSelf, void *pvUser) 480 { 481 PPAMVBOXTHREAD pUserData = (PPAMVBOXTHREAD)pvUser; 482 AssertPtr(pUserData); 483 484 int rc = VINF_SUCCESS; 485 /* Get current time stamp to later calculate rest of timeout left. */ 486 uint64_t u64StartMS = RTTimeMilliTS(); 487 488 #ifdef VBOX_WITH_GUEST_PROPS 489 uint32_t uClientID = 0; 490 rc = VbglR3GuestPropConnect(&uClientID); 491 if (RT_FAILURE(rc)) 492 { 493 pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: Unable to connect to guest property service, rc=%Rrc\n", rc); 494 } 495 else 496 { 497 pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: clientID=%u\n", uClientID); 498 #endif 499 for (;;) 500 { 501 #ifdef VBOX_WITH_GUEST_PROPS 502 if (uClientID) 503 { 504 rc = pam_vbox_wait_prop(pUserData->hPAM, uClientID, 505 "/VirtualBox/GuestAdd/PAM/CredsWaitAbort", 506 500 /* Wait 500ms, same as VBoxGINA/VBoxCredProv. */); 507 switch (rc) 508 { 509 case VINF_SUCCESS: 510 /* Somebody (guest/host) wants to abort waiting for credentials. */ 511 break; 512 513 case VERR_INTERRUPTED: 514 pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: The abort notification request timed out or was interrupted\n"); 515 break; 516 517 case VERR_TIMEOUT: 518 /* We did not receive an abort message within time. */ 519 break; 520 521 case VERR_TOO_MUCH_DATA: 522 pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: Temporarily unable to get abort notification\n"); 523 break; 524 525 default: 526 pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: The abort notification request failed with rc=%Rrc\n", rc); 527 break; 528 } 529 530 if (RT_SUCCESS(rc)) /* Abort waiting. */ 531 { 532 pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: Got notification to abort waiting\n"); 533 rc = VERR_CANCELLED; 534 break; 535 } 536 } 537 #endif 538 if ( RT_SUCCESS(rc) 539 || rc == VERR_TIMEOUT) 540 { 541 rc = pam_vbox_check_creds(pUserData->hPAM); 542 if (RT_SUCCESS(rc)) 543 { 544 /* Credentials retrieved. */ 545 break; /* Thread no longer is required, bail out. */ 546 } 547 else if (rc == VERR_NOT_FOUND) 548 { 549 /* No credentials found, but try next round (if there's 550 * time left for) ... */ 551 #ifndef VBOX_WITH_GUEST_PROPS 552 RTThreadSleep(500); /* Wait 500 ms. */ 553 #endif 554 } 555 else 556 break; /* Something bad happend ... */ 557 } 558 else 559 break; 560 561 /* Calculate timeout value left after process has been started. */ 562 uint64_t u64Elapsed = RTTimeMilliTS() - u64StartMS; 563 /* Is it time to bail out? */ 564 if (pUserData->uTimeoutMS < u64Elapsed) 565 { 566 pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: Waiting thread has reached timeout (%dms), exiting ...\n", 567 pUserData->uTimeoutMS); 568 rc = VERR_TIMEOUT; 569 break; 570 } 571 } 572 #ifdef VBOX_WITH_GUEST_PROPS 573 } 574 VbglR3GuestPropDisconnect(uClientID); 575 #endif 576 577 /* Save result. */ 578 pUserData->rc = rc; /** @todo Use ASMAtomicXXX? */ 579 580 int rc2 = RTThreadUserSignal(RTThreadSelf()); 581 AssertRC(rc2); 582 583 pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: Waiting thread returned with rc=%Rrc\n", rc); 584 return rc; 585 } 586 587 588 static int pam_vbox_wait_for_creds(pam_handle_t *hPAM, uint32_t uClientID, uint32_t uTimeoutMS) 589 { 590 PAMVBOXTHREAD threadData; 591 threadData.hPAM = hPAM; 592 threadData.uTimeoutMS = uTimeoutMS; 593 594 RTTHREAD threadWait; 595 int rc = RTThreadCreate(&threadWait, pam_vbox_wait_thread, 596 (void *)&threadData, 0, 597 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "pam_vbox"); 598 if (RT_SUCCESS(rc)) 599 { 600 pam_vbox_log(hPAM, "pam_vbox_wait_for_creds: Waiting for credentials (%dms) ...\n", uTimeoutMS); 601 /* Wait for thread to initialize. */ 602 rc = RTThreadUserWait(threadWait, RT_INDEFINITE_WAIT); 603 if (RT_SUCCESS(rc)) 604 rc = threadData.rc; /* Get back thread result to take further actions. */ 605 } 606 else 607 pam_vbox_error(hPAM, "pam_vbox_wait_for_creds: Creating thread failed with rc=%Rrc\n", rc); 608 609 pam_vbox_log(hPAM, "pam_vbox_wait_for_creds: Waiting for credentials returned with rc=%Rrc\n", rc); 610 return rc; 611 } 477 612 478 613 … … 563 698 else if (rc == VERR_TIMEOUT) 564 699 { 565 pam_vbox_log(hPAM, "pam_sm_authenticate: no credentials given within time\n" , rc);700 pam_vbox_log(hPAM, "pam_sm_authenticate: no credentials given within time\n"); 566 701 567 702 rc2 = pam_vbox_read_prop(hPAM, uClientId, … … 570 705 szVal, sizeof(szVal)); 571 706 if (RT_SUCCESS(rc2)) 707 { 572 708 rc2 = vbox_set_msg(hPAM, 0 /* Info message */, szVal); 709 AssertRC(rc2); 710 } 711 } 712 else if (rc == VERR_CANCELLED) 713 { 714 pam_vbox_log(hPAM, "pam_sm_authenticate: waiting aborted\n"); 715 716 rc2 = pam_vbox_read_prop(hPAM, uClientId, 717 "/VirtualBox/GuestAdd/PAM/CredsMsgWaitAbort", 718 true /* Read-only on guest */, 719 szVal, sizeof(szVal)); 720 if (RT_SUCCESS(rc2)) 721 { 722 rc2 = vbox_set_msg(hPAM, 0 /* Info message */, szVal); 723 AssertRC(rc2); 724 } 573 725 } 574 726 }
Note:
See TracChangeset
for help on using the changeset viewer.