DWORD LsaPamSetDataString( pam_handle_t* pamh, PCSTR pszKey, PCSTR pszStr ) { DWORD dwError = 0; PSTR pszStrCopy = NULL; int iPamError = 0; dwError = LwAllocateString(pszStr, &pszStrCopy); BAIL_ON_LSA_ERROR(dwError); iPamError = pam_set_data(pamh, pszKey, pszStrCopy, LsaPamCleanupDataString); dwError = LsaPamUnmapErrorCode(iPamError); BAIL_ON_LSA_ERROR(dwError); error: return dwError; }
DWORD LsaPamGetContext( pam_handle_t* pamh, int flags, int argc, const char** argv, PPAMCONTEXT* ppPamContext ) { DWORD dwError = 0; PPAMCONTEXT pPamContext = NULL; BOOLEAN bFreeContext = FALSE; int iPamError = 0; LSA_LOG_PAM_DEBUG("LsaPamGetContext::begin"); iPamError = pam_get_data(pamh, MODULE_NAME, (PAM_GET_DATA_TYPE)&pPamContext); dwError = LsaPamUnmapErrorCode(iPamError); if (dwError) { if (dwError == LsaPamUnmapErrorCode(PAM_NO_MODULE_DATA)) { dwError = LwAllocateMemory( sizeof(PAMCONTEXT), (PVOID*)&pPamContext); BAIL_ON_LSA_ERROR(dwError); bFreeContext = TRUE; iPamError = pam_set_data( pamh, MODULE_NAME, (PVOID)pPamContext, &LsaPamCleanupContext); dwError = LsaPamUnmapErrorCode(iPamError); BAIL_ON_LSA_ERROR(dwError); bFreeContext = FALSE; } else { BAIL_ON_LSA_ERROR(dwError); } } dwError = LsaPamGetLoginId(pamh, pPamContext, NULL, FALSE); BAIL_ON_LSA_ERROR(dwError); dwError = LsaPamGetOptions( pamh, flags, argc, argv, &pPamContext->pamOptions); BAIL_ON_LSA_ERROR(dwError); *ppPamContext = pPamContext; cleanup: LSA_LOG_PAM_DEBUG("LsaPamGetContext::end"); return dwError; error: if (pPamContext && bFreeContext) { LsaPamFreeContext(pPamContext); } *ppPamContext = NULL; LSA_LOG_PAM_ERROR("LsaPamGetContext failed [error code: %u]", dwError); goto cleanup; }
DWORD LsaPamGetLoginId( pam_handle_t* pamh, PPAMCONTEXT pPamContext, PSTR* ppszLoginId, BOOLEAN bAllowPrompt ) { DWORD dwError = 0; PSTR pszLoginId = NULL; PSTR pszPamId = NULL; int iPamError = 0; LSA_LOG_PAM_DEBUG("LsaPamGetLoginId::begin"); iPamError = pam_get_item( pamh, PAM_USER, (PAM_GET_ITEM_TYPE)&pszPamId); dwError = LsaPamUnmapErrorCode(iPamError); #if HAVE_DECL_PAM_BAD_ITEM if (dwError == LsaPamUnmapErrorCode(PAM_BAD_ITEM)) { pszPamId = NULL; dwError = 0; } #endif BAIL_ON_LSA_ERROR(dwError); if (LW_IS_NULL_OR_EMPTY_STR(pszPamId) && bAllowPrompt) { iPamError = pam_get_user( pamh, (PPCHAR_ARG_CAST)&pszPamId, NULL); dwError = LsaPamUnmapErrorCode(iPamError); if (dwError) { dwError = (dwError == LsaPamUnmapErrorCode(PAM_CONV_AGAIN)) ? LsaPamUnmapErrorCode(PAM_INCOMPLETE) : LsaPamUnmapErrorCode(PAM_SERVICE_ERR); BAIL_ON_LSA_ERROR(dwError); } if (LW_IS_NULL_OR_EMPTY_STR(pszPamId)) { dwError = LsaPamUnmapErrorCode(PAM_SERVICE_ERR); BAIL_ON_LSA_ERROR(dwError); } } dwError = LwStrDupOrNull( pszPamId, &pszLoginId); BAIL_ON_LSA_ERROR(dwError); LW_SAFE_FREE_STRING(pPamContext->pszLoginName); dwError = LwStrDupOrNull(pszPamId, &pPamContext->pszLoginName); BAIL_ON_LSA_ERROR(dwError); if (ppszLoginId) { *ppszLoginId = pszLoginId; } else { LW_SAFE_FREE_STRING(pszLoginId); } cleanup: LSA_LOG_PAM_DEBUG("LsaPamGetLoginId::end"); return dwError; error: LW_SAFE_FREE_STRING(pszLoginId); if (ppszLoginId) { *ppszLoginId = NULL; } LSA_LOG_PAM_ERROR("LsaPamGetLoginId failed [error code: %u]", dwError); goto cleanup; }
DWORD LsaPamConverseMulti( pam_handle_t* pamh, int numMessages, PLSA_PAM_CONVERSE_MESSAGE pLsaPamConvMessages ) { DWORD dwError = 0; struct pam_conv* pConv = NULL; struct pam_response* pResponses = NULL; struct pam_message* msgs = NULL; struct pam_message** pMsgs = NULL; int iPamError = 0; int i; iPamError = pam_get_item(pamh, PAM_CONV, (PAM_GET_ITEM_TYPE)&pConv); dwError = LsaPamUnmapErrorCode(iPamError); BAIL_ON_LSA_ERROR(dwError); if (!pConv) { dwError = LsaPamUnmapErrorCode(PAM_CONV_ERR); BAIL_ON_LSA_ERROR(dwError); } else if (pConv->conv) { dwError = LwAllocateMemory(numMessages * sizeof(*msgs), (PVOID*) &msgs); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory(numMessages * sizeof(*pMsgs), (PVOID*) &pMsgs); BAIL_ON_LSA_ERROR(dwError); for (i = 0; i < numMessages; ++i) { msgs[i].msg_style = pLsaPamConvMessages[i].messageStyle; msgs[i].msg = pLsaPamConvMessages[i].pszMessage; switch (msgs[i].msg_style) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: if (pLsaPamConvMessages[i].ppszResponse == NULL) { BAIL_WITH_LSA_ERROR(LW_ERROR_INVALID_PARAMETER); } break; default: if (pLsaPamConvMessages[i].ppszResponse != NULL) { BAIL_WITH_LSA_ERROR(LW_ERROR_INVALID_PARAMETER); } break; } pMsgs[i] = &msgs[i]; } iPamError = pConv->conv(numMessages, (PAM_CONV_2ND_ARG_TYPE)pMsgs, &pResponses, pConv->appdata_ptr); dwError = LsaPamUnmapErrorCode(iPamError); BAIL_ON_LSA_ERROR(dwError); } else { LSA_LOG_PAM_INFO("Unable to send prompt to user from PAM. Most likely the calling program is non-interactive"); // Leave pResponses as NULL. } for (i = 0; i < numMessages; ++i) { switch (pLsaPamConvMessages[i].messageStyle) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: /* * The pResponses == NULL check is here because * it's perfectly OK for it to be NULL if none of the * messages required a response. */ if (pResponses == NULL || pResponses[i].resp == NULL) { BAIL_WITH_LSA_ERROR(PAM_CONV_ERR); } *pLsaPamConvMessages[i].ppszResponse = pResponses[i].resp; break; default: if (pResponses != NULL && pResponses[i].resp != NULL) { /* Got a response we weren't expecting. */ BAIL_WITH_LSA_ERROR(PAM_CONV_ERR); } break; } } cleanup: if (pResponses) { /* * All the .resp pointers have either been copied to * the caller or freed. */ free(pResponses); } LW_SAFE_FREE_MEMORY(msgs); LW_SAFE_FREE_MEMORY(pMsgs); return dwError; error: if (pResponses) { for (i = 0; i < numMessages; ++i) { LW_SECURE_FREE_STRING(pResponses[i].resp); } } goto cleanup; }