/*********************************************************************** * * 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 #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[8192]; 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; }