/*********************************************************************** * * 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 * ***********************************************************************/ //===[ 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; } //++======================================================================= //++======================================================================= //++=======================================================================