Skip to content
This repository has been archived by the owner on Nov 9, 2021. It is now read-only.

Commit

Permalink
Merged PR 7583: #154933-Support PasswordSafe password change upon req…
Browse files Browse the repository at this point in the history
…uestId checkin

Currently domain join using PasswordSafe credentials involve requesting, then checkin the password. The password is subsequently used for the domain join. However, this may not work if PasswordSafe is configured to change the password upon checkin. The fix is to request the password from PS, do the domain join then checkin the password.

Related work items: #154933
  • Loading branch information
rali-bt committed Aug 24, 2018
1 parent 754958c commit e1780e6
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 45 deletions.
18 changes: 13 additions & 5 deletions domainjoin/domainjoin-cli/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ ShowUsage(const BOOLEAN isEnterprise)
fprintf(stdout, " setname <computer name>\n");
fprintf(stdout, (isEnterprise)
? " join [join options] [--ou <organizationalUnit>] <domain name> <user name> [<password>]\n"
" join [join options] [--ou <organizationalUnit>] <domain name> --configFile <configuration file]\n"
" join [join options] [--ou <organizationalUnit>] --configFile <configuration file> <domain name>\n"
: " join [join options] [--ou <organizationalUnit>] <domain name> <user name> [<password>]\n");
fprintf(stdout, " join [--advanced] --preview [--ou <organizationalUnit>] <domain name>\n");
fprintf(stdout, " join [--ou <organizationalUnit>] --details <module> <domain name>\n");
Expand Down Expand Up @@ -463,6 +463,7 @@ void DoJoin(int argc, char **argv, int columns, BOOLEAN isEnterprise, LWExceptio
PSTR moduleDetails = NULL;
PSTR wrapped = NULL;
PSTR joinLeaveHistoryFile = NULL;
PPbpsApiHandle_t pPbpsApiHandle = NULL;

DJZeroJoinProcessOptions(&options);
options.isEnterprise = isEnterprise;
Expand Down Expand Up @@ -763,10 +764,11 @@ void DoJoin(int argc, char **argv, int columns, BOOLEAN isEnterprise, LWExceptio
{
CT_SAFE_FREE_STRING(options.username);
CT_SAFE_FREE_STRING(options.password);
LW_CLEANUP_CTERR(exc, PbpsApiGetCredentials(
LW_CLEANUP_CTERR(exc, PbpsApiCredentialGet(
options.pszConfigFile,
&options.username,
&options.password));
&options.password,
&pPbpsApiHandle));
}

options.joiningDomain = TRUE;
Expand Down Expand Up @@ -888,6 +890,8 @@ void DoJoin(int argc, char **argv, int columns, BOOLEAN isEnterprise, LWExceptio
linenoiseHistorySave(joinLeaveHistoryFile);
}

PbpsApiCredentialRelease(&pPbpsApiHandle);

DJFreeJoinProcessOptions(&options);
CTArrayFree(&enableModules);
CTArrayFree(&disableModules);
Expand All @@ -913,6 +917,7 @@ void DoLeaveNew(int argc, char **argv, int columns, BOOLEAN isEnterprise, LWExce
PSTR wrapped = NULL;
int passwordIndex = -1;
PSTR joinLeaveHistoryFile = NULL;
PPbpsApiHandle_t pPbpsApiHandle = NULL;

DJZeroJoinProcessOptions(&options);
options.isEnterprise = isEnterprise;
Expand Down Expand Up @@ -1064,10 +1069,11 @@ void DoLeaveNew(int argc, char **argv, int columns, BOOLEAN isEnterprise, LWExce
{
CT_SAFE_FREE_STRING(options.username);
CT_SAFE_FREE_STRING(options.password);
LW_CLEANUP_CTERR(exc, PbpsApiGetCredentials(
LW_CLEANUP_CTERR(exc, PbpsApiCredentialGet(
options.pszConfigFile,
&options.username,
&options.password));
&options.password,
&pPbpsApiHandle));
}


Expand Down Expand Up @@ -1192,6 +1198,8 @@ void DoLeaveNew(int argc, char **argv, int columns, BOOLEAN isEnterprise, LWExce
linenoiseHistorySave(joinLeaveHistoryFile);
}

PbpsApiCredentialRelease(&pPbpsApiHandle);

DJFreeJoinProcessOptions(&options);
CTArrayFree(&enableModules);
CTArrayFree(&disableModules);
Expand Down
17 changes: 13 additions & 4 deletions domainjoin/libdomainjoin/include/djpbps.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,18 @@
#include <lwdef.h>
#include <lwstr.h>

extern DWORD PbpsApiGetCredentials(
PSTR pszPbpsConfigFile,
PSTR *ppszUsername,
PSTR *ppszPassword);
typedef PVOID PPbpsApiHandle_t; // An opaque type for internal use.

extern
DWORD
PbpsApiCredentialGet(
PSTR pszConfigFile,
PSTR *ppszUsername,
PSTR *ppszPassword,
PPbpsApiHandle_t *ppPbpsApiHandle);

extern
VOID
PbpsApiCredentialRelease(PPbpsApiHandle_t *ppPbpsApiHandle);

#endif
4 changes: 2 additions & 2 deletions domainjoin/libdomainjoin/src/djpbps/djpbps.config.template
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ ApiKey = '<API Key>' #eg. 4b2c430dbe2b6aff66b016cc8e11b0f78b4d7cc426d3fd4c53c92a

# Minutes PBPS credential is valid until it expires.
# Optional. Valid range is between 1 and 10079 inclusive.
# Default is 1 minute. Uncomment if required.
#DurationMinutes = 1
# Default is 2 minutes. Uncomment if required.
#DurationMinutes = 2

# Client Certificate.
# Optional. Needed if Password Safe web console shows "Client Certificate
Expand Down
14 changes: 9 additions & 5 deletions domainjoin/libdomainjoin/src/djpbps/pbps-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include <ctbase.h>
#include <ctfileutils.h>
#include <djlogger.h>
#include <djpbps.h>
#include <djhostinfo.h>


Expand Down Expand Up @@ -86,7 +87,7 @@
*/
#define PBPSAPI_MINIMUM_DURATION_MINUTES 1
#define PBPSAPI_MAXIMUM_DURATION_MINUTES 10079
#define PBPSAPI_DEFAULT_DURATION_MINUTES PBPSAPI_MINIMUM_DURATION_MINUTES
#define PBPSAPI_DEFAULT_DURATION_MINUTES 2

#define CURL_HEADER_AUTH_FORMAT "Authorization: PS-Auth key=%s;runas=%s;"
#define CURL_HEADER_AUTH_PWD_NEEDLE "pwd=["
Expand Down Expand Up @@ -123,6 +124,9 @@ typedef struct PbpsApiConfig_s

typedef struct PbpsApiSession_s
{
BOOLEAN bDoSignout;
BOOLEAN bDoCheckin;
DWORD dwRequestId;
CURL *pCurlHandle;
struct curl_slist *pHeaderList;
PLW_DLINKED_LIST pManagedAccountList; // Fill-in by GET ManagedAccounts
Expand Down Expand Up @@ -185,17 +189,17 @@ extern DWORD PbpsApiSignIn(PbpsApi_t *pApi);
extern DWORD PbpsApiRequestId(PbpsApi_t *pApi, DWORD *pdwRequestId);
extern DWORD PbpsApiCredentialsGet(PbpsApi_t *pApi, DWORD dwRequestId,
PSTR *ppszCredentials);
extern DWORD PbpsApiRequestIdCheckin(PbpsApi_t *pApi, DWORD dwRequestId);
extern DWORD PbpsApiRequestIdCheckin(PbpsApi_t *pApi);
extern DWORD PbpsApiSignOut(PbpsApi_t *pApi);


extern DWORD PbpsApiManagedAccountsGet(PbpsApi_t *pApi);
extern VOID PbpsApiManagedAccountFree(PbpsApiManagedAccount_t *pAccount);
extern VOID PbpsManagedAccountListFree(PLW_DLINKED_LIST pManagedAccountList);
extern DWORD PbpsApiGetJoinAccount(
PbpsApi_t *pApi,
PSTR pszJoinAccount,
PbpsApiManagedAccount_t **ppAccount);
PbpsApi_t *pApi,
PSTR pszJoinAccount,
PbpsApiManagedAccount_t **ppAccount);

#endif // _PBPS_INT_H_

Expand Down
72 changes: 45 additions & 27 deletions domainjoin/libdomainjoin/src/djpbps/pbps.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,22 @@

/*
* Using the config file, get credentials from the PasswordSafe server
* for the user in the config file.
* Updates pointer to username and password
* for the domain join user in the config file.
* Updates pointer to username, password and a API handle subsequently used
* to release the credentials with PasswordSafe.
*/

DWORD
PbpsApiGetCredentials(PSTR pszConfigFile,
PSTR *ppszUsername,
PSTR *ppszPassword)
PbpsApiCredentialGet(PSTR pszConfigFile,
PSTR *ppszUsername,
PSTR *ppszPassword,
PPbpsApiHandle_t *ppPbpsApiHandle)
{

DWORD dwError = LW_ERROR_SUCCESS;
PbpsApi_t *pApi = NULL;
DWORD dwRequestId = 0;
PSTR pszCredentials = NULL;
BOOLEAN bDoCheckIn = FALSE;
BOOLEAN bDoSignOut = FALSE;

dwError = PbpsApiInitialize(&pApi);
BAIL_ON_LW_ERROR(dwError);
Expand All @@ -64,50 +66,66 @@ PbpsApiGetCredentials(PSTR pszConfigFile,
dwError = PbpsApiSignIn(pApi);
BAIL_ON_LW_ERROR(dwError);

bDoSignOut = TRUE;

dwError = PbpsApiManagedAccountsGet(pApi);
BAIL_ON_LW_ERROR(dwError);

dwError = PbpsApiRequestId(pApi, &dwRequestId);
BAIL_ON_LW_ERROR(dwError);

bDoCheckIn = TRUE;

dwError = PbpsApiCredentialsGet(pApi, dwRequestId, &pszCredentials);
BAIL_ON_LW_ERROR(dwError);

dwError = LwStrDupOrNull(pApi->config.pszJoinAccount, ppszUsername);
BAIL_ON_LW_ERROR(dwError);

*ppszPassword = pszCredentials;
*ppPbpsApiHandle = pApi;

fprintf(stdout,
"Successfully retrieved credentials for %s\n",
pApi->config.pszJoinAccount);

*ppszPassword = pszCredentials;

cleanup:
if (bDoCheckIn)
{
// Ignore the return code since we've already successfully retrieved
// pasword safe credentials. Error msgs would already have been
// logged.
PbpsApiRequestIdCheckin(pApi, dwRequestId);
}

if (bDoSignOut)
PbpsApiSignOut(pApi);
return dwError;

error:

fprintf(stderr, "Failed to retrieve credentials\n");

LW_SAFE_FREE_STRING(pszCredentials);
PbpsApiRelease(pApi);

goto cleanup;
}



VOID
PbpsApiCredentialRelease(PPbpsApiHandle_t *ppPbpsApiHandle)
{
PbpsApi_t *pApi = NULL;

if (*ppPbpsApiHandle == NULL)
goto cleanup;

pApi = *ppPbpsApiHandle;

// Ignore the return code since we've already successfully retrieved
// pasword safe credentials. Error msgs would already have been
// logged.
PbpsApiRequestIdCheckin(pApi);

PbpsApiSignOut(pApi);

PbpsApiCurlDebugStop(pApi);

PbpsApiRelease(pApi);

return dwError;
*ppPbpsApiHandle = NULL;

error:
fprintf(stdout, "Failed to retrieved credentials\n");
cleanup:

goto cleanup;
return;
}


12 changes: 10 additions & 2 deletions domainjoin/libdomainjoin/src/djpbps/pbpsRequestId.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ DWORD PbpsApiRequestId(PbpsApi_t *pApi, DWORD *pdwRequestId)

DJ_LOG_INFO("%s requestId:%d", pszFunction, dwRequestId);

pApi->session.bDoCheckin = TRUE;
pApi->session.dwRequestId = dwRequestId;

*pdwRequestId = dwRequestId;


Expand All @@ -166,7 +169,7 @@ DWORD PbpsApiRequestId(PbpsApi_t *pApi, DWORD *pdwRequestId)
* PUT Request Checkin
*
*/
DWORD PbpsApiRequestIdCheckin(PbpsApi_t *pApi, DWORD dwRequestId)
DWORD PbpsApiRequestIdCheckin(PbpsApi_t *pApi)
{
DWORD dwError = LW_ERROR_SUCCESS;
CURLcode curlResult = CURLE_OK;
Expand All @@ -178,11 +181,16 @@ DWORD PbpsApiRequestIdCheckin(PbpsApi_t *pApi, DWORD dwRequestId)
responseBuffer.buffer = NULL;
responseBuffer.size = 0;

if (!pApi->session.bDoCheckin)
return dwError;

readBuffer.buffer = pszDomainJoinCheckInReason;
readBuffer.size = strlen(pszDomainJoinCheckInReason);

dwError = LwAllocateStringPrintf(
&pszUrl, "%s/Requests/%d/Checkin", pApi->config.pszUrlBase, dwRequestId);
&pszUrl, "%s/Requests/%d/Checkin",
pApi->config.pszUrlBase,
pApi->session.dwRequestId);
BAIL_ON_LW_ERROR(dwError);

curlResult = curl_easy_setopt(pApi->session.pCurlHandle, CURLOPT_URL, pszUrl);
Expand Down
5 changes: 5 additions & 0 deletions domainjoin/libdomainjoin/src/djpbps/pbpsSignInOut.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ DWORD PbpsApiSignIn(PbpsApi_t *pApi)
responseBuffer.buffer,
responseBuffer.size);

pApi->session.bDoSignout = TRUE;

cleanup:
LW_SAFE_FREE_STRING(pszUrl);

Expand Down Expand Up @@ -141,6 +143,9 @@ DWORD PbpsApiSignOut(PbpsApi_t *pApi)

responseBuffer_t responseBuffer;

if (!pApi->session.bDoSignout)
return dwError;

responseBuffer.buffer = NULL;
responseBuffer.size = 0;

Expand Down
3 changes: 3 additions & 0 deletions domainjoin/libdomainjoin/src/djpbps/pbpsUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ PbpsApiInitialize(PbpsApi_t **ppApi)
pApiTmp->config.pszCertFileClient = NULL;
pApiTmp->config.pszCertFileCA = NULL;

pApiTmp->session.bDoSignout = FALSE;
pApiTmp->session.bDoCheckin = FALSE;
pApiTmp->session.dwRequestId = 0;
pApiTmp->session.pCurlHandle = NULL;
pApiTmp->session.pHeaderList = NULL;
pApiTmp->session.pManagedAccountList = NULL;
Expand Down

0 comments on commit e1780e6

Please sign in to comment.