/*#---------------------------------------------------------------------------- ** ** File: sspcalls.c ** ** Synopsis: This module contains SSPI function calls for SSPI SPM DLL. ** ** Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. ** ** Authors: LucyC Created 25 Sept. 1995 ** **---------------------------------------------------------------------------*/ #include "msnspmh.h" /***** #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile *****/ BOOL g_fUUEncodeData = TRUE; /*----------------------------------------------------------------------------- ** ** Function: GetSecAuthMsg ** ** Synopsis: This function generates a SSPI NEGOTIATE or RESPONSE ** authorization string for the specified SSPI package. ** The authorization string generated by this function ** follows the format: ** " " ** If global uuencoding is turned on, this functions will ** uuencode the message before building it into an ** authorization string; by default, the uuencoding flag is ** always on. ** This functions calls InitializeSecurityContext() to ** generate the NEGOTIATE/RESPONSE message for the authori- ** zation string. If the SSPI function returns NO_CREDENTIAL, ** and if the PROMPT_CREDS flag is not turned on when blocking ** is permitted, this function will call the SSPI function ** again with the PROMPT_CREDS flag set; if SSPI returns ** NO_CREDENTIAL again, this SSPI will return ERROR to the ** caller. ** ** ** Arguments: ** ** pData - pointer to SspData containing the SSPI function table ** and the SSPI package list. ** pkgID - the package index of the SSPI package to use. ** pMyContext - pointer to a context handle. If NULL is specified, ** this function will use a temporary space for the context ** handle and delete the handle before returning to the ** caller. If non-NULL address is specified, the context ** handle created by the SSPI is returned to the caller. ** And the caller will have to delete the handle when it's ** done with it. ** fContextReq - the SSPI request flag to pass to InitializeSecurityContext ** pBuffIn - pointer to the uudecoded CHALLENGE message if any. ** For generating NEGOTIATE message, this pointer should be NULL. ** cbBuffIn - length of the CHALLENGE message. This should be zero when ** when pBuffIn is NULL. ** pFinalBuff - pointer to a buffer for the final authorization string. ** pszTarget - Server Host Name ** bNonBlock - a flag which is set if blocking is not permitted. ** ** Return Value: ** ** HTSPM_STATUS_OK - if an authorization string is generated successfully ** HTSPM_STATUS_WOULD_BLOCK - if generating an authorization string would ** cause blocking when blocking is not permitted. ** HTSPM_ERROR - if any problem/error is encountered in generating an ** authorization string, including user hitting cancel on ** the SSPI dialog prompt for name/password. ** **---------------------------------------------------------------------------*/ HTSPMStatusCode GetSecAuthMsg ( F_UserInterface fpUI, void * pvOpaqueOS, PSspData pData, UCHAR pkgID, // the package index into package list PCtxtHandle pMyContext, ULONG fContextReq, // Request Flags VOID *pBuffIn, DWORD cbBuffIn, char *pFinalBuff, SEC_CHAR *pszTarget, // Server Host Name UINT bNonBlock ) { BOOLEAN bOk; SECURITY_STATUS SecStat; CtxtHandle hContext; CtxtHandle *phContext; TimeStamp Lifetime; SecBufferDesc OutBuffDesc; SecBuffer OutSecBuff; SecBufferDesc InBuffDesc; SecBuffer InSecBuff; ULONG ContextAttributes; char OutBufPlain[MAX_AUTH_MSG_SIZE]; char *pOutMsg = NULL; HTSPMStatusCode RetStatus; UI_StatusCode uisc; ULONG bGet; UI_WindowHandle *pwh = NULL; //TraceFunctEnter("GetSecAuthMsg"); // // Initialize the final buffer to hold the package name followed by // a space. And setup the pOutMsg pointer to points to the character // following the space so that the final NEGOTIATE/RESPONSE can be // copied into the pFinalBuff starting at the character pointed to // by pOutMsg. // if (pFinalBuff) { strcpy (pFinalBuff, pData->PkgList[pkgID]->pName); pOutMsg = pFinalBuff + strlen(pFinalBuff); *pOutMsg++ = ' '; } // // If caller does not want the context handle back // if (pMyContext == NULL) phContext = &hContext; // use a temporary one else phContext = pMyContext; // // Prepare our output buffer. We use a temporary buffer because // the real output buffer will most likely need to be uuencoded // OutBuffDesc.ulVersion = 0; OutBuffDesc.cBuffers = 1; OutBuffDesc.pBuffers = &OutSecBuff; OutSecBuff.cbBuffer = MAX_AUTH_MSG_SIZE; OutSecBuff.BufferType = SECBUFFER_TOKEN; OutSecBuff.pvBuffer = OutBufPlain; // // Prepare our Input buffer if a CHALLENGE message is passed in. // if ( pBuffIn ) { InBuffDesc.ulVersion = 0; InBuffDesc.cBuffers = 1; InBuffDesc.pBuffers = &InSecBuff; InSecBuff.cbBuffer = cbBuffIn; InSecBuff.BufferType = SECBUFFER_TOKEN; InSecBuff.pvBuffer = pBuffIn; } // // Call SSPI function generate the NEGOTIATE/RESPONSE message // SspiRetry: SecStat = (*(pData->pFuncTbl->InitializeSecurityContext))( &pData->PkgList[pkgID]->Credential, (pBuffIn ? phContext : NULL), pszTarget, fContextReq, 0, SECURITY_NATIVE_DREP, (pBuffIn) ? &InBuffDesc : NULL, 0, phContext, &OutBuffDesc, &ContextAttributes, &Lifetime ); // // If SSPI function fails // if ( !NT_SUCCESS( SecStat ) ) { RetStatus = HTSPM_ERROR; //ErrorTrace(SSPCALLSID,"InitializeSecurityContext failed [0x%x]\n", // SecStat); // // If SSPI do not have user name/password for the secified package, // if (SecStat == SEC_E_NO_CREDENTIALS) { // // If we have prompted the user and still get back "No Credential" // error, it means the user does not have valid credential; the // user hit on the UI box. If we have supplied a valid // credential, but get back a "No Credential" error, then something // has gone wrong; we definitely should return to caller with ERROR // if ((fContextReq & ISC_REQ_PROMPT_FOR_CREDS) || (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS)) { RetStatus = HTSPM_ERROR; // return ERROR to caller } else if (bNonBlock) { // // Blocking is not permitted, return WOULD_BLOCK to caller // RetStatus = HTSPM_STATUS_WOULD_BLOCK; } else { // Blocking is permitted and we have not asked the SSPI to // prompt the user for proper credential, we should call // the SSPI again with PROMPT_CREDS flag set. // fContextReq = fContextReq | ISC_REQ_PROMPT_FOR_CREDS; goto SspiRetry; } } SetLastError( SecStat ); // // If we failed to generate a RESPONSE, and // if the context handle is not to be returned to the caller, we // should delete the context handle before we exit this function. // However, if we failed to generate a NEGOTIATE, // we don't need to worry about deleting the context handle because // the context handle has not being created in this case. // if (pBuffIn != NULL && pMyContext == NULL) (*(pData->pFuncTbl->DeleteSecurityContext))(phContext); //TraceFunctLeave(); return (RetStatus); } RetStatus = HTSPM_STATUS_OK; // // Only uuencode message if a output buffer is specified // if (pOutMsg) { if ( g_fUUEncodeData && pOutMsg) { if ( !uuencode( (BYTE *) OutSecBuff.pvBuffer, OutSecBuff.cbBuffer, (CHAR *) pOutMsg, MAX_AUTH_MSG_SIZE )) { //ErrorTrace(SSPCALLSID, // "Failed to uuencode NEGOTIATE/RESPONSE\n"); RetStatus = HTSPM_ERROR; } } else { memcpy( (CHAR *) pOutMsg, OutSecBuff.pvBuffer, OutSecBuff.cbBuffer ); } } // // We have successfully generated a NEGOTIATE or RESPONSE, so a context // handle has been created by the SSPI. // If the context handle is not to be returned to the caller, we should // delete the context handle before we exit this function. // if (pMyContext == NULL) (*(pData->pFuncTbl->DeleteSecurityContext))(phContext); //TraceFunctLeave(); return (RetStatus); } /*----------------------------------------------------------------------------- ** ** Function: GetSecCredential ** ** Synopsis: ** ** This function go through the list of SSPI pacakges supported and ** call AcquireCredentialsHandle for each package. If the call fails, ** the SSPI package is deleted from the package list. ** ** Arguments: ** ** fpUI - pointer from the Explorer for making UI_SERVICE call ** pvOpaqueOS - pointer from the Explorer for making UI_SERVICE call ** pData - pointer to the data structure containing the package list. ** ** Return Value: ** ** void. ** **---------------------------------------------------------------------------*/ VOID GetSecCredential ( F_UserInterface fpUI, void *pvOpaqueOS, PSspData pData ) { int ii; SECURITY_STATUS ss; TimeStamp Lifetime; ii = 0; // // For every package in the out package list // while (ii < pData->PkgCnt) { // // Call SSPI function acquire security credential for this package // ss = (*(pData->pFuncTbl->AcquireCredentialsHandle))( NULL, // New principal pData->PkgList[ii]->pName, // Package name SECPKG_CRED_OUTBOUND,// Credential Use NULL, // Logon ID NULL, // Auth Data NULL, // Get key func NULL, // Get key arg &pData->PkgList[ii]->Credential, // Credential Handle &Lifetime ); // // If SSPI can not create a credential handle for the package // if ( ss != STATUS_SUCCESS ) { SetLastError( ss ); // // Failed to acquire credential for this package, // Deallocate memory for this package // spm_free (fpUI, pvOpaqueOS, pData->PkgList[ii]->pName); spm_free (fpUI, pvOpaqueOS, pData->PkgList[ii]); // // remove this SSPI package from the package list. // if (ii < pData->PkgCnt - 1) { memcpy (&pData->PkgList[ii], &pData->PkgList[ii+1], (pData->PkgCnt - ii -1) * sizeof(PSSPAuthPkg)); } pData->PkgList[--pData->PkgCnt] = NULL; } else ii++; // proceed to the next package } }