c99e319a3a
Also made a fix to allow credential store scoping all the way into the authentication mechanisms.
348 lines
12 KiB
C
348 lines
12 KiB
C
/***********************************************************************
|
|
*
|
|
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; version 2.1
|
|
* of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, Novell, Inc.
|
|
*
|
|
* To contact Novell about this file by physical or electronic mail,
|
|
* you may find current contact information at www.novell.com.
|
|
*
|
|
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
|
*
|
|
***********************************************************************/
|
|
|
|
|
|
//===[ Include files ]=====================================================
|
|
|
|
#include "internal.h"
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
GetUserCredentials(
|
|
IN const char *pRealm,
|
|
IN void *pCredStoreScope,
|
|
INOUT char **ppUsername,
|
|
INOUT char **ppPassword)
|
|
//
|
|
// Arguments:
|
|
// pRealm -
|
|
// The realm to which the credentials apply.
|
|
//
|
|
// pCredStoreScope -
|
|
// Pointer to CASA structure for scoping credential store access
|
|
// to specific users. This can only be leveraged when running in
|
|
// the context of System under Windows.
|
|
//
|
|
// ppUsername -
|
|
// Pointer to variable that will receive buffer with the username.
|
|
//
|
|
// ppPassword -
|
|
// Pointer to variable that will receive buffer with the password.
|
|
//
|
|
// Returns:
|
|
// Casa Status
|
|
//
|
|
// Description:
|
|
// Get authentication credentials for the specified realm.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_UNSUCCESSFUL);
|
|
char *pUsername;
|
|
char *pPassword;
|
|
int rcode = NSSCS_E_OBJECT_NOT_FOUND;
|
|
uint32_t credtype = SSCS_CRED_TYPE_BASIC_F;
|
|
SSCS_BASIC_CREDENTIAL credential = {0};
|
|
SSCS_SECRET_ID_T secretId = {0};
|
|
|
|
DbgTrace(1, "-GetUserCredentials- Start\n", 0);
|
|
|
|
// Initialize output parameters
|
|
*ppUsername = NULL;
|
|
*ppPassword = NULL;
|
|
|
|
// Get the length of the realm string into the secret id structure
|
|
// and verify thatr it is not too long.
|
|
secretId.len = sscs_Utf8Strlen(pRealm) + 1;
|
|
if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN)
|
|
{
|
|
// Set the secret id in the structure
|
|
sscs_Utf8Strcpy((char*) secretId.id, pRealm);
|
|
|
|
// Specify that we want the common name
|
|
credential.unFlags = USERNAME_TYPE_CN_F;
|
|
|
|
// Now try to get the credentials
|
|
rcode = miCASAGetCredential(0,
|
|
&secretId,
|
|
NULL,
|
|
&credtype,
|
|
&credential,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
if (rcode != NSSCS_SUCCESS)
|
|
{
|
|
// There were no credentials for the realm, now try to obtain the
|
|
// desktop credentials.
|
|
secretId.len = sscs_Utf8Strlen("Desktop") + 1;
|
|
sscs_Utf8Strcpy((char*) secretId.id, "Desktop");
|
|
rcode = miCASAGetCredential(0,
|
|
&secretId,
|
|
NULL,
|
|
&credtype,
|
|
&credential,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetUserCredentials- Realm name too long\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
// Proceed based on the result of the operatiosn above
|
|
if (rcode == NSSCS_SUCCESS
|
|
&& credential.username != NULL
|
|
&& credential.password != NULL)
|
|
{
|
|
// Allocate a buffer to return the username
|
|
pUsername = (char*) malloc(strlen((char*) credential.username) + 1);
|
|
if (pUsername)
|
|
{
|
|
// Copy the username into the buffer that we will be returning
|
|
strcpy(pUsername, (char*) credential.username);
|
|
|
|
// Allocate a buffer to return the password
|
|
pPassword = (char*) malloc(strlen((char*) credential.password) + 1);
|
|
if (pPassword)
|
|
{
|
|
// Copy the password into the buffer that we will be returning
|
|
strcpy(pPassword, (char*) credential.password);
|
|
|
|
DbgTrace(1, "-GetUserCredentials- Username = %s\n", pUsername);
|
|
|
|
// Success
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
// Free the buffer allocated for the username
|
|
free(pUsername);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetUserCredentials- Failed to obtain credentials for pw authentication\n", 0);
|
|
}
|
|
|
|
// Return the buffers to the caller if successful
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
*ppUsername = pUsername;
|
|
*ppPassword = pPassword;
|
|
}
|
|
|
|
DbgTrace(1, "-GetUserCredentials- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus SSCS_CALL
|
|
AuthTokenIf_GetAuthToken(
|
|
IN const void *pIfInstance,
|
|
IN const char *pContext,
|
|
IN const char *pMechInfo,
|
|
IN void *pCredStoreScope,
|
|
INOUT char *pTokenBuf,
|
|
INOUT int *pTokenBufLen)
|
|
//
|
|
// Arguments:
|
|
// pIfInstance -
|
|
// Pointer to interface object.
|
|
//
|
|
// pContext -
|
|
// Pointer to null terminated string containing mechanism specific
|
|
// context information. Another name for context is Authentication
|
|
// Realm.
|
|
//
|
|
// pMechInfo -
|
|
// Pointer to null terminated string containing mechanism specific
|
|
// information. This is information is provided by the server to
|
|
// aid the mechanism to generate an authentication token. For
|
|
// example, the mechanism information for a Kerberos mechanism
|
|
// may be the service principal name to which the user will be
|
|
// authenticating.
|
|
//
|
|
// pCredStoreScope -
|
|
// Pointer to CASA structure for scoping credential store access
|
|
// to specific users. This can only be leveraged when running in
|
|
// the context of System under Windows.
|
|
//
|
|
// pTokenBuf -
|
|
// Pointer to buffer that will receive the authentication
|
|
// token. The length of this buffer is specified by the
|
|
// pTokenBufLen parameter. Note that the the authentication
|
|
// token will be in the form of a NULL terminated string.
|
|
//
|
|
// pTokenBufLen -
|
|
// Pointer to integer that contains the length of the
|
|
// buffer pointed at by pTokenBuf. Upon return of the
|
|
// function, the integer will contain the actual length
|
|
// of the authentication token if the function successfully
|
|
// completes or the buffer length required if the function
|
|
// fails because the buffer pointed at by pUserNameBuf is
|
|
// not large enough.
|
|
//
|
|
// Returns:
|
|
// Casa Status
|
|
//
|
|
// Description:
|
|
// Get authentication token to authenticate user to specified service.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
char *pUsername = NULL;
|
|
char *pPassword = NULL;
|
|
char *pToken;
|
|
|
|
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0);
|
|
|
|
// Validate input parameters
|
|
if (pIfInstance == NULL
|
|
|| pContext == NULL
|
|
|| pMechInfo == NULL
|
|
|| pTokenBufLen == NULL
|
|
|| (pTokenBuf == NULL && *pTokenBufLen != 0))
|
|
{
|
|
DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0);
|
|
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_INVALID_PARAMETER);
|
|
goto exit;
|
|
}
|
|
|
|
// Get the user credentials
|
|
retStatus = GetUserCredentials(pContext,
|
|
pCredStoreScope,
|
|
&pUsername,
|
|
&pPassword);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Now construct the PW token with the following format:
|
|
// "username\r\n" + "password\r\n"
|
|
//
|
|
// First allocate a buffer large enough to hold the token
|
|
pToken = (char*) malloc(strlen(pUsername) + 2 + strlen(pPassword) + 2 + 1);
|
|
if (pToken)
|
|
{
|
|
char *pEncodedToken;
|
|
int encodedTokenLen;
|
|
|
|
// Now assemble the token
|
|
sprintf(pToken, "%s\r\n%s\r\n", pUsername, pPassword);
|
|
|
|
// The token has been assembled, now encode it.
|
|
retStatus = EncodeData(pToken,
|
|
(const int) strlen(pToken),
|
|
&pEncodedToken,
|
|
&encodedTokenLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Verify that the caller provided a buffer that is big enough
|
|
if (encodedTokenLen > *pTokenBufLen)
|
|
{
|
|
// The buffer is not big enough
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_BUFFER_OVERFLOW);
|
|
}
|
|
else
|
|
{
|
|
// The buffer provided is large enough, copy the data.
|
|
memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen);
|
|
|
|
// Success
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
|
|
// Return the actual size or the size required
|
|
*pTokenBufLen = encodedTokenLen;
|
|
|
|
// Free the buffer containing the encoded token
|
|
free(pEncodedToken);
|
|
}
|
|
|
|
// Free the buffer allocated for the token
|
|
free(pToken);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-AuthTokenIf_GetAuthToken- Buffer allocation error\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_PWTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
// Free allocated buffers
|
|
free(pUsername);
|
|
free(pPassword);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the user credentials\n", 0);
|
|
}
|
|
|
|
exit:
|
|
|
|
DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|