383 lines
12 KiB
C
383 lines
12 KiB
C
/***********************************************************************
|
|
* File: util.c
|
|
* Author: Juan Carlos Luciani (jluciani@novell.com)
|
|
*
|
|
* Abstract: Implements common utility functions for the library.
|
|
*
|
|
* Copyright (C) 2005 Novell, Inc.
|
|
*
|
|
* 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 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, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* To contact Novell about this file by physical or electronic mail,
|
|
* you may find current contact information at www.novell.com.
|
|
***********************************************************************/
|
|
|
|
//===[ Include files ]=====================================================
|
|
|
|
#include "internal.h"
|
|
#include <stdlib.h>
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
// Debug Level
|
|
int DebugLevel = 1;
|
|
|
|
// Mechanism OID
|
|
gss_OID g_mechOid = GSS_C_NULL_OID;
|
|
|
|
// Tables for Base64 encoding and decoding
|
|
static const int8_t g_Base64[] =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
static const uint8_t g_Expand64[256] =
|
|
{
|
|
/* ASCII table */
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
|
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
|
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
|
};
|
|
|
|
|
|
/* ************************************************************************
|
|
* LogError()
|
|
*
|
|
* Log error to system log.
|
|
*
|
|
* ************************************************************************/
|
|
//static void
|
|
//LogError(char *pFormatStr, ... )
|
|
//{
|
|
// va_list args;
|
|
//
|
|
// openlog("CASA", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER);
|
|
// va_start(args, pFormatStr);
|
|
// vsyslog(LOG_USER | LOG_INFO, pFormatStr, args);
|
|
// va_end(args);
|
|
// closelog();
|
|
//}
|
|
|
|
|
|
//++=======================================================================
|
|
void
|
|
LogGssStatuses(
|
|
IN char *operation,
|
|
IN OM_uint32 majorGssStatus,
|
|
IN OM_uint32 minorGssStatus)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Description:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
OM_uint32 gssMajStat;
|
|
OM_uint32 gssMinStat;
|
|
gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
|
|
OM_uint32 gssMsgCtx;
|
|
|
|
// Trace the messages associated with the major status
|
|
gssMsgCtx = 0;
|
|
while (1)
|
|
{
|
|
gssMajStat = gss_display_status(&gssMinStat,
|
|
majorGssStatus,
|
|
GSS_C_GSS_CODE,
|
|
g_mechOid,
|
|
&gssMsgCtx,
|
|
&msg);
|
|
if (gssMajStat != GSS_S_COMPLETE)
|
|
{
|
|
DbgTrace(0, "krb5_token -LogGssStatuses- Error obtaining display status\n", 0);
|
|
break;
|
|
}
|
|
|
|
// Trace this message
|
|
DbgTrace(0, "krb5_token -LogGssStatuses- GSS-API error %s: ", operation);
|
|
DbgTrace(0, "%s\n", (char *)msg.value);
|
|
|
|
if (msg.length != 0)
|
|
gss_release_buffer(&gssMinStat, &msg);
|
|
|
|
if (!gssMsgCtx)
|
|
break;
|
|
}
|
|
|
|
// Trace the messages associated with the minor status
|
|
gssMsgCtx = 0;
|
|
while (1)
|
|
{
|
|
gssMajStat = gss_display_status(&gssMinStat,
|
|
minorGssStatus,
|
|
GSS_C_MECH_CODE,
|
|
g_mechOid,
|
|
&gssMsgCtx,
|
|
&msg);
|
|
if (gssMajStat != GSS_S_COMPLETE)
|
|
{
|
|
DbgTrace(0, "krb5_token -LogGssStatuses- Error obtaining display status\n", 0);
|
|
break;
|
|
}
|
|
|
|
// Trace this message
|
|
DbgTrace(0, "krb5_token -LogGssStatuses- GSS-API error %s: ", operation);
|
|
DbgTrace(0, "%s\n", (char *)msg.value);
|
|
|
|
if (msg.length != 0)
|
|
gss_release_buffer(&gssMinStat, &msg);
|
|
|
|
if (!gssMsgCtx)
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus
|
|
EncodeData(
|
|
IN const void *pData,
|
|
IN const int32_t dataLen,
|
|
INOUT char **ppEncodedData,
|
|
INOUT int32_t *pEncodedDataLen)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Description:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
int encodedSize;
|
|
|
|
|
|
DbgTrace(3, "krb5_token -EncodeData- Start\n", 0);
|
|
|
|
// Determine the encoded size and allocate a buffer to hold the encoded data
|
|
encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4;
|
|
*ppEncodedData = malloc(encodedSize);
|
|
if (*ppEncodedData)
|
|
{
|
|
uint8_t *pOut, *pIn;
|
|
int i;
|
|
|
|
// Setup pointers to move through the buffers
|
|
pIn = (uint8_t*) pData;
|
|
pOut = (uint8_t*) *ppEncodedData;
|
|
|
|
// Perform the encoding
|
|
for (i = 0; i < dataLen - 2; i += 3)
|
|
{
|
|
*pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F];
|
|
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4) |
|
|
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
|
*pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) |
|
|
((int32_t)(pIn[i + 2] & 0xC0) >> 6)];
|
|
*pOut++ = g_Base64[pIn[i + 2] & 0x3F];
|
|
}
|
|
if (i < dataLen)
|
|
{
|
|
*pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F];
|
|
if (i == (dataLen - 1))
|
|
{
|
|
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4)];
|
|
*pOut++ = '=';
|
|
}
|
|
else
|
|
{
|
|
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4) |
|
|
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
|
*pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)];
|
|
}
|
|
*pOut++ = '=';
|
|
}
|
|
*pOut++ = '\0';
|
|
|
|
// Return the encoded data length
|
|
*pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData);
|
|
|
|
// Success
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "krb5_token -EncodeData- Buffer allocation failure\n", 0);
|
|
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_KRB5TOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
DbgTrace(3, "krb5_token -EncodeData- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus
|
|
DecodeData(
|
|
IN const char *pEncodedData,
|
|
IN const int32_t encodedDataLen, // Does not include NULL terminator
|
|
INOUT void **ppData,
|
|
INOUT int32_t *pDataLen)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Description:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
int i, j;
|
|
int decodedSize;
|
|
|
|
DbgTrace(3, "krb5_token -DecodeData- Start\n", 0);
|
|
|
|
// Determine the decoded size
|
|
for (i = 0, j = 0; i < encodedDataLen; i++)
|
|
if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64)
|
|
j++;
|
|
decodedSize = (j * 3 + 3) / 4;
|
|
|
|
// Allocate buffer to hold the decoded data
|
|
*ppData = malloc(decodedSize);
|
|
if (*ppData)
|
|
{
|
|
bool endReached = false;
|
|
uint8_t c0, c1, c2, c3;
|
|
uint8_t *p, *q;
|
|
|
|
// Initialize parameters that will be used during the decode operation
|
|
c0 = c1 = c2 = c3 = 0;
|
|
p = (uint8_t*) pEncodedData;
|
|
q = (uint8_t*) *ppData;
|
|
|
|
// Decode the data
|
|
//
|
|
// Loop through the data, piecing back information. Any newlines, and/or
|
|
// carriage returns need to be skipped.
|
|
while (j > 4)
|
|
{
|
|
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
|
p++;
|
|
if (64 == g_Expand64[*p])
|
|
{
|
|
endReached = true;
|
|
break;
|
|
}
|
|
c0 = *(p++);
|
|
|
|
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
|
p++;
|
|
if (64 == g_Expand64[*p])
|
|
{
|
|
*(q++) = (uint8_t)(g_Expand64[c0] << 2);
|
|
j--;
|
|
endReached = true;
|
|
break;
|
|
}
|
|
c1 = *(p++);
|
|
|
|
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
|
p++;
|
|
if (64 == g_Expand64[*p])
|
|
{
|
|
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
|
*(q++) = (uint8_t)(g_Expand64[c1] << 4);
|
|
j -= 2;
|
|
endReached = true;
|
|
break;
|
|
}
|
|
c2 = *(p++);
|
|
|
|
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
|
p++;
|
|
if (64 == g_Expand64[*p])
|
|
{
|
|
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
|
*(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2);
|
|
*(q++) = (uint8_t)(g_Expand64[c2] << 6);
|
|
j -= 3;
|
|
endReached = true;
|
|
break;
|
|
}
|
|
c3 = *(p++);
|
|
|
|
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
|
*(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2);
|
|
*(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]);
|
|
j -= 4;
|
|
}
|
|
if (!endReached)
|
|
{
|
|
if (j > 1)
|
|
*(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4);
|
|
if (j > 2)
|
|
*(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2);
|
|
if (j > 3)
|
|
*(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]);
|
|
}
|
|
|
|
// Return the length of the decoded data
|
|
*pDataLen = (int32_t)(q - (uint8_t*)*ppData);
|
|
|
|
// Success
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "krb5_token -DecodeData- Buffer allocation failure\n", 0);
|
|
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_KRB5TOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
DbgTrace(3, "krb5_token -DecodeData- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|