514 lines
17 KiB
C++
514 lines
17 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 <windows.h>
|
|
#include "casa_c_authtoken.h"
|
|
|
|
// Globals
|
|
char usageString[] = "usage: test -a serverAddress -p serverPort [-h]\n";
|
|
|
|
char *pServerAddress = NULL;
|
|
int serverPort = 0;
|
|
BOOLEAN execHttpTest = FALSE;
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* dtoul()
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
dtoul(
|
|
IN char *cp,
|
|
IN int len)
|
|
{
|
|
int n = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++, cp++)
|
|
{
|
|
// Verify that we are dealing with a valid digit
|
|
if (*cp >= '0' && *cp <= '9')
|
|
{
|
|
n = 10 * n + (*cp - '0');
|
|
}
|
|
else
|
|
{
|
|
printf("-dtoul- Found invalid digit\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* EncodeData()
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
EncodeData(
|
|
IN const void *pData,
|
|
IN const int32_t dataLen,
|
|
INOUT char **ppEncodedData,
|
|
INOUT int32_t *pEncodedDataLen)
|
|
{
|
|
int8_t base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
int retStatus;
|
|
int encodedSize;
|
|
|
|
char *pTmp;
|
|
|
|
// Determine the encoded size and allocate a buffer to hold the encoded data
|
|
encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4;
|
|
pTmp = (char*) malloc(encodedSize);
|
|
*ppEncodedData = pTmp;
|
|
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++ = base64[(pIn[i] >> 2) & 0x3F];
|
|
*pOut++ = base64[((pIn[i] & 0x3) << 4) |
|
|
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
|
*pOut++ = base64[((pIn[i + 1] & 0xF) << 2) |
|
|
((int32_t)(pIn[i + 2] & 0xC0) >> 6)];
|
|
*pOut++ = base64[pIn[i + 2] & 0x3F];
|
|
}
|
|
if (i < dataLen)
|
|
{
|
|
*pOut++ = base64[(pIn[i] >> 2) & 0x3F];
|
|
if (i == (dataLen - 1))
|
|
{
|
|
*pOut++ = base64[((pIn[i] & 0x3) << 4)];
|
|
*pOut++ = '=';
|
|
}
|
|
else
|
|
{
|
|
*pOut++ = base64[((pIn[i] & 0x3) << 4) |
|
|
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
|
*pOut++ = base64[((pIn[i + 1] & 0xF) << 2)];
|
|
}
|
|
*pOut++ = '=';
|
|
}
|
|
*pOut++ = '\0';
|
|
|
|
// Return the encoded data length
|
|
*pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData);
|
|
|
|
// Success
|
|
retStatus = 0;
|
|
}
|
|
else
|
|
{
|
|
printf("-EncodeData- Buffer allocation failure\n");
|
|
retStatus = -1;
|
|
}
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* NonHttpTest()
|
|
*
|
|
***********************************************************************/
|
|
void NonHttpTest(void)
|
|
{
|
|
CasaStatus retStatus;
|
|
char authToken[4096];
|
|
int authTokenLen = sizeof(authToken);
|
|
|
|
// Obtain an authentication token for the testService
|
|
retStatus = ObtainAuthToken("testService", pServerAddress, authToken, &authTokenLen);
|
|
if (!CASA_SUCCESS(retStatus))
|
|
{
|
|
printf("-NonHttpTest- ObtainAuthToken failed with status %d\n", retStatus);
|
|
}
|
|
else
|
|
{
|
|
SOCKET sock;
|
|
struct sockaddr_in localAddr = {0};
|
|
struct sockaddr_in remoteAddr = {0};
|
|
struct linger linger_opt = {1, 15};
|
|
struct hostent *pLookupResult;
|
|
int winsockStartupResult;
|
|
WSADATA winsockData;
|
|
|
|
printf("-NonHttpTest- ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen);
|
|
|
|
// Send the token to the server
|
|
//
|
|
// First initialize winsock
|
|
if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0)
|
|
{
|
|
// Open socket
|
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (sock != INVALID_SOCKET)
|
|
{
|
|
// Setup the local address structure
|
|
localAddr.sin_family = AF_INET;
|
|
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
// Bind socket
|
|
if (!bind(sock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in)))
|
|
{
|
|
// Resolve the server address
|
|
pLookupResult = gethostbyname(pServerAddress);
|
|
if (pLookupResult)
|
|
{
|
|
// Validate the address type returned
|
|
if (pLookupResult->h_addrtype == AF_INET)
|
|
{
|
|
int numAddressesFound = 0;
|
|
|
|
// Determine how many addresses where returned
|
|
while (pLookupResult->h_addr_list[numAddressesFound] != NULL)
|
|
{
|
|
//printf("ServerAddress = %08X\n", *((int*) pLookupResult->h_addr_list[numAddressesFound]));
|
|
numAddressesFound ++;
|
|
}
|
|
//printf("Found %d addresses\n", numAddressesFound);
|
|
|
|
// Setup the remote address structure with the lookup results
|
|
remoteAddr.sin_family = AF_INET;
|
|
remoteAddr.sin_port = serverPort;
|
|
remoteAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]); // Short-cut
|
|
//printf("ServerAddress = %08X\n", remoteAddr.sin_addr.s_addr);
|
|
|
|
// Perform connect operation
|
|
if (connect(sock,
|
|
(struct sockaddr*) &remoteAddr,
|
|
sizeof(struct sockaddr_in)) == SOCKET_ERROR)
|
|
{
|
|
printf("-NonHttpTest- Connection creation failed, error = %d\n", WSAGetLastError());
|
|
}
|
|
else
|
|
{
|
|
// Now the connection is setup, send the credentials to the server as one line.
|
|
// using our cheesy protocol followed by a hello string.
|
|
//
|
|
// Send the token to the server (including NULL terminator)
|
|
send(sock, authToken, (int) strlen(authToken) + 1, 0);
|
|
|
|
// Send new line
|
|
send(sock, "\n", 1, 0);
|
|
|
|
// Send "hello"
|
|
//send(sock, helloString, strlen(helloString) + 1, MSG_NOSIGNAL);
|
|
|
|
// Send new line
|
|
//send(sock, "\n", 1, 0);
|
|
|
|
// Shutdown the connection
|
|
shutdown(sock, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("-NonHttpTest- Unsupported address type returned %08X\n", pLookupResult->h_addrtype);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("-NonHttpTest- Lookup for %s failed\n", pServerAddress);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("-NonHttpTest- Unable to bind socket, error = %d", errno);
|
|
}
|
|
|
|
// Close the socket
|
|
setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*) &linger_opt, sizeof(linger_opt));
|
|
closesocket(sock);
|
|
}
|
|
else
|
|
{
|
|
printf("-NonHttpTest- Unable to open socket, error = %d\n", errno);
|
|
}
|
|
|
|
// Close winsock
|
|
WSACleanup();
|
|
}
|
|
else
|
|
{
|
|
printf("-NonHttpTest- WSAStartup failed, error = %d\n", winsockStartupResult);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* HttpTest()
|
|
*
|
|
***********************************************************************/
|
|
void HttpTest(void)
|
|
{
|
|
CasaStatus retStatus;
|
|
char authToken[4096];
|
|
int authTokenLen = sizeof(authToken);
|
|
|
|
// Obtain an authentication token for the testService
|
|
retStatus = ObtainAuthToken("testService", pServerAddress, authToken, &authTokenLen);
|
|
if (!CASA_SUCCESS(retStatus))
|
|
{
|
|
printf("-HttpTest- ObtainAuthToken failed with status %d\n", retStatus);
|
|
}
|
|
else
|
|
{
|
|
SOCKET sock;
|
|
struct sockaddr_in localAddr = {0};
|
|
struct sockaddr_in remoteAddr = {0};
|
|
struct linger linger_opt = {1, 15};
|
|
struct hostent *pLookupResult;
|
|
int winsockStartupResult;
|
|
WSADATA winsockData;
|
|
|
|
//printf("ObtainAuthToken succedded, token = %s\n", authToken);
|
|
printf("-HttpTest- ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen);
|
|
|
|
// Send the token to the server
|
|
//
|
|
// First initialize winsock
|
|
if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0)
|
|
{
|
|
// Open socket
|
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (sock != INVALID_SOCKET)
|
|
{
|
|
// Setup the local address structure
|
|
localAddr.sin_family = AF_INET;
|
|
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
// Bind socket
|
|
if (!bind(sock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in)))
|
|
{
|
|
// Resolve the server address
|
|
pLookupResult = gethostbyname(pServerAddress);
|
|
if (pLookupResult)
|
|
{
|
|
// Validate the address type returned
|
|
if (pLookupResult->h_addrtype == AF_INET)
|
|
{
|
|
int numAddressesFound = 0;
|
|
|
|
// Determine how many addresses where returned
|
|
while (pLookupResult->h_addr_list[numAddressesFound] != NULL)
|
|
{
|
|
//printf("ServerAddress = %08X\n", *((int*) pLookupResult->h_addr_list[numAddressesFound]));
|
|
numAddressesFound ++;
|
|
}
|
|
//printf("Found %d addresses\n", numAddressesFound);
|
|
|
|
|
|
// Setup the remote address structure with the lookup results
|
|
remoteAddr.sin_family = AF_INET;
|
|
remoteAddr.sin_port = serverPort;
|
|
remoteAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]); // Short-cut
|
|
//printf("ServerAddress = %08X\n", remoteAddr.sin_addr.s_addr);
|
|
|
|
// Perform connect operation
|
|
if (connect(sock,
|
|
(struct sockaddr*) &remoteAddr,
|
|
sizeof(struct sockaddr_in)) == SOCKET_ERROR)
|
|
{
|
|
printf("-HttpTest- Connection creation failed, error = %d\n", WSAGetLastError());
|
|
}
|
|
else
|
|
{
|
|
char *pBasicCredentials;
|
|
char *pEncodedBasicCredentials;
|
|
int encodedLength;
|
|
char CasaPrincipal[] = "CasaPrincipal:";
|
|
char HTTPReqPart1[] = "GET /example-info HTTP/1.1\r\\nUser-Agent: CasaTestClient\r\nHost: jcstation.dnsdhcp.provo.novell.com:4096\r\nConnection: Keep-Alive\r\nAuthorization: Basic ";
|
|
|
|
// Now the connection is setup, send 1st part of HTTP request to the server.
|
|
send(sock, HTTPReqPart1, (int) strlen(HTTPReqPart1), 0);
|
|
|
|
// Now setup the HTTP Basic Credentials
|
|
pBasicCredentials = (char*) malloc(strlen(CasaPrincipal) + strlen(authToken) + 1);
|
|
if (pBasicCredentials)
|
|
{
|
|
char *pEncodedCredentials;
|
|
|
|
memcpy(pBasicCredentials, CasaPrincipal, sizeof(CasaPrincipal));
|
|
strcat(pBasicCredentials, authToken);
|
|
|
|
// Now Base64 encode the credentials
|
|
if (EncodeData(pBasicCredentials, strlen(pBasicCredentials), &pEncodedBasicCredentials, &encodedLength) == 0)
|
|
{
|
|
// Send the encoded credentials
|
|
send(sock, pEncodedBasicCredentials, encodedLength - 1, 0);
|
|
|
|
// Send the rest of the header
|
|
send(sock, "\r\n\r\n", 4, 0);
|
|
|
|
// Free the buffer holding the encoded credentials
|
|
free(pEncodedBasicCredentials);
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- Error encoding credentials\n");
|
|
}
|
|
|
|
// Free the buffer containing the basic credentials
|
|
free(pBasicCredentials);
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- Buffer allocation failure\n");
|
|
}
|
|
|
|
// Shutdown the connection
|
|
shutdown(sock, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- Unsupported address type returned %08X\n", pLookupResult->h_addrtype);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- Lookup for %s failed\n", pServerAddress);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- Unable to bind socket, error = %d", errno);
|
|
}
|
|
|
|
// Close the socket
|
|
setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*) &linger_opt, sizeof(linger_opt));
|
|
closesocket(sock);
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- Unable to open socket, error = %d\n", errno);
|
|
}
|
|
|
|
// Close winsock
|
|
WSACleanup();
|
|
}
|
|
else
|
|
{
|
|
printf("-HttpTest- WSAStartup failed, error = %d\n", winsockStartupResult);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* main()
|
|
*
|
|
***********************************************************************/
|
|
int main(int argc, char* argv[])
|
|
{
|
|
// Process input parameters
|
|
int i = 1;
|
|
while(argv[i] != NULL)
|
|
{
|
|
if (stricmp(argv[i], "-a") == 0)
|
|
{
|
|
// Server Address option, the next argument should
|
|
// contain the address.
|
|
i++;
|
|
if (argv[i] != NULL)
|
|
{
|
|
pServerAddress = argv[i];
|
|
}
|
|
else
|
|
{
|
|
printf(usageString);
|
|
return -1;
|
|
}
|
|
}
|
|
else if (stricmp(argv[i], "-p") == 0)
|
|
{
|
|
// Server port option, the next argument should
|
|
// contain the port.
|
|
i++;
|
|
if (argv[i] != NULL)
|
|
{
|
|
serverPort = htons(dtoul(argv[i], strlen(argv[i])));
|
|
}
|
|
else
|
|
{
|
|
printf(usageString);
|
|
return -1;
|
|
}
|
|
}
|
|
else if (stricmp(argv[i], "-h") == 0)
|
|
{
|
|
// Perform http test option
|
|
execHttpTest = TRUE;
|
|
}
|
|
|
|
// Advance to the next argument
|
|
i++;
|
|
}
|
|
|
|
// Verify that the server address and port were specified
|
|
if (pServerAddress && serverPort != 0)
|
|
{
|
|
// Repeat the test when indicated
|
|
printf("Press 'Enter' to run test or 'n + Enter' to stop.\n");
|
|
while(getchar() != 'n')
|
|
{
|
|
// Execute the appropriate test
|
|
if (execHttpTest)
|
|
{
|
|
HttpTest();
|
|
}
|
|
else
|
|
{
|
|
NonHttpTest();
|
|
}
|
|
printf("Press 'Enter' to run test or 'n + Enter' to stop.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf(usageString);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|