/*
---------------------------------------------------------------------------
$Id: tsp_cap.c,v 1.25 2007/04/25 19:31:50 cnepveu Exp $
---------------------------------------------------------------------------
Copyright (c) 2001-2007 Hexago Inc. All rights reserved.
LICENSE NOTICE: You may use and modify this source code only if you
have executed a valid license agreement with Hexago Inc. granting
you the right to do so, the said license agreement governing such
use and modifications. Copyright or other intellectual property
notices are not to be removed from the source code.
---------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define _USES_SYS_SOCKET_H_
#include "platform.h"
#include "tsp_cap.h"
#include "tsp_client.h" // tspGetStatusCode()
#include "net.h"
#include "log.h"
#include "hex_strings.h"
#include "version.h"
#include "tsp_redirect.h"
/* static functions */
/* Convert a CAPABILITY string in corresponding bit in capability flag */
static
tCapability
tspExtractCapability(char *String) {
tCapability flags;
char *s, *e, Token[strlen(String)+1], Value[strlen(String)+1];
int len;
flags = 0;
*Token = *Value = 0;
for(s=e=String+11; *e; e++) {
if(*e== ' ' || *e == '\r' || *e == '\n' || *e == 0) {
if(s!=e) {
if(*Token && (*Value == 0)) {
len = (int)((char *)e-(char *)s);
memcpy(Value, s, len);
Value[len] = 0;
}
if(*Token && *Value) {
flags |= tspSetCapability(Token,Value);
*Value = *Token = 0;
}
}
s = ++e;
}
if((*e=='=' || *e== ' ' || *e == '\r' || *e == '\n' || *e == 0) && (e != s)) {
len = (int)((char *)e-(char *)s);
memcpy(Token, s, len);
Token[len] = 0;
s = ++e;
}
}
return flags;
}
/* exports */
/* Return the capability flag corrsponding to the token */
tCapability
tspSetCapability(char *Token, char *Value) {
if(strcmp("TUNNEL", Token)==0) {
if(strcmp("V6V4", Value)==0)
return TUNNEL_V6V4;
if(strcmp("V6UDPV4", Value)==0)
return TUNNEL_V6UDPV4;
#ifdef V4V6_SUPPORT
if(strcmp("V4V6", Value)==0)
return TUNNEL_V4V6;
#endif /* V4V6_SUPPORT */
}
if(strcmp("AUTH", Token)==0) {
#ifndef NO_OPENSSL
if(strcasecmp("PASSDSS-3DES-1", Value)==0)
return AUTH_PASSDSS_3DES_1;
#endif
if(strcasecmp("DIGEST-MD5", Value)==0)
return AUTH_DIGEST_MD5;
if(strcasecmp("ANONYMOUS", Value)==0)
return AUTH_ANONYMOUS;
if(strcasecmp("PLAIN", Value)==0)
return AUTH_PLAIN;
}
return 0;
}
tErrors
tspGetCapabilities(SOCKET socket, net_tools_t *nt, tCapability *capability, int version_index, tConf *conf, tBrokerList **broker_list) {
char dataout[256];
char datain[REDIRECT_RECEIVE_BUFFER_SIZE];
snprintf(dataout, sizeof(dataout), "VERSION=%s\r\n", TspProtocolVersionStrings[version_index]);
memset(datain, -0, sizeof(datain));
if (nt->netsendrecv(socket, dataout, strlen(dataout), datain, sizeof(datain)) == -1)
return SOCKET_ERROR;
if(memcmp("CAPABILITY ", datain, 11) == 0)
*capability = tspExtractCapability(datain);
else {
if ( tspGetStatusCode(datain) == 302 )
return TSP_VERSION_ERROR;
if (tspIsRedirectStatus(tspGetStatusCode(datain))) {
if (tspHandleRedirect(datain, conf, broker_list) == TSP_REDIRECT_OK) {
return BROKER_REDIRECTION;
}
else {
return BROKER_REDIRECTION_ERROR;
}
}
Display(LOG_LEVEL_3, ELInfo, "Capability", HEX_STR_ERR_FROM_SERVER, datain);
return TSP_ERROR;
}
return NO_ERROR;
}
// Formats a comma-separated string containing the capability(ies) in the buffer provided.
// Returns the buffer.
char* tspFormatCapabilities( char* szBuffer, const size_t bufLen, const tCapability cap )
{
static const char* authTab[] = { "Any, ",
#ifndef NO_OPENSSL
"Passdss-3des-1, ",
#endif
"Digest MD5, ",
"Anonymous, ",
"Plain, " };
size_t nWritten = 0;
/*
AUTH_ANY is explicitly expanded in the following capabilities.
*/
#ifndef NO_OPENSSL
if( (cap & AUTH_PASSDSS_3DES_1) == AUTH_PASSDSS_3DES_1 )
{
strncpy( szBuffer + nWritten, authTab[1], bufLen - nWritten );
nWritten += strlen( authTab[1] );
}
#endif
if( (cap & AUTH_DIGEST_MD5) == AUTH_DIGEST_MD5 )
{
strncpy( szBuffer + nWritten, authTab[2], bufLen - nWritten );
nWritten += strlen( authTab[2] );
}
if( (cap & AUTH_ANONYMOUS) == AUTH_ANONYMOUS && (cap & AUTH_ANY) != AUTH_ANY )
{
// ANY does not include ANONYMOUS
strncpy( szBuffer + nWritten, authTab[3], bufLen - nWritten );
nWritten += strlen( authTab[3] );
}
if( (cap & AUTH_PLAIN) == AUTH_PLAIN )
{
strncpy( szBuffer + nWritten, authTab[4], bufLen - nWritten );
nWritten += strlen( authTab[4] );
}
if( nWritten > 2 )
szBuffer[nWritten-2] = '\0'; // Remove the end comma.
return szBuffer;
}
syntax highlighted by Code2HTML, v. 0.9.1