blob: 205cd07603f277f2a09d339cacbe86567590e93c [file]
//******************************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
//******************************************************************************
#include "tokenkey.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "openssl/evp.h"
#include "seabed/int/types.h"
#include "seabed/pctl.h"
#include "seabed/ms.h"
#include "seabed/fserr.h"
//-----------------------------------------------------------------------------
// Structure used to describe layout of user token
//
class TokenKeyContents
{
public:
char ID[2]; //Key identifier, binary values 3,4
union
{
struct {
char processName[MS_MON_MAX_PROCESS_NAME];
int nodeId; //Node Number
int processId; //pin
char rand[12]; //random byte
} token;
struct {
char b64[71]; //base64 encoded
char zero;
} encoded;
} u;
void populate();
void reset();
};
static int base64(
const char *in,
size_t inLen,
char *out,
bool enc);
extern "C" long random(void);
extern "C" void srandom(unsigned int);
#pragma page "TokenKey::IsA"
// *****************************************************************************
// * *
// * Function: TokenKey::IsA *
// * *
// * Determines if a string matches the format of a token key. The string *
// * may be a token key, but no longer valid. *
// * *
// *****************************************************************************
bool TokenKey::IsA(const char * tokenKeyString)
{
// Verify caller has same size token as current implementation.
if (tokenKeyString == NULL)
return false;
if (tokenKeyString[0] != USERTOKEN_ID_1 ||
tokenKeyString[1] != USERTOKEN_ID_2)
return false;
return true;
}
//************************** End of TokenKey::IsA ******************************
#pragma page "void TokenKey::TokenKey"
// *****************************************************************************
// * *
// * Function: TokenKey::TokenKey *
// * This function constructs a TokenKey object and its contents. *
// * *
// *****************************************************************************
TokenKey::TokenKey()
: self(*new TokenKeyContents())
{
memset((char *)&self,'A',sizeof(TokenKeyContents));
self.populate();
}
//************************ End of TokenKey::TokenKey ***************************
#pragma page "void TokenKey::TokenKey"
// *****************************************************************************
// * *
// * Function: TokenKey::TokenKey *
// * This function constructs a TokenKey object and its contents. *
// * *
// *****************************************************************************
TokenKey::TokenKey(const char * tokenKeyString)
: self(*new TokenKeyContents())
{
strncpy((char *)&self,tokenKeyString,sizeof(TokenKeyContents));
}
//************************ End of TokenKey::TokenKey ***************************
#pragma page "void Token::~Token"
// *****************************************************************************
// * *
// * Function: Token::~Token *
// * This function destroys a Token object and its contents. *
// * *
// *****************************************************************************
TokenKey::~TokenKey()
{
delete &self;
}
//*************************** End of Token::~Token *****************************
#pragma page "void TokenKey::operator="
// *****************************************************************************
// * *
// * Function: TokenKey::operator= *
// * This function assigns TokenKey contents. *
// * *
// *****************************************************************************
TokenKey & TokenKey::operator=(const TokenKey &rhs)
{
if (this == &rhs)
return *this;
memcpy((char *)&self,(char *)&rhs.self,sizeof(TokenKeyContents));
return *this;
}
//*********************** End of TokenKey::operator= ***************************
#pragma page "void Token::operator=="
// *****************************************************************************
// * *
// * Function: Token::operator== *
// * This function compares the contents of two TokenKey objects. *
// * *
// *****************************************************************************
bool TokenKey::operator==(const TokenKey &rhs) const
{
if (this == &rhs)
return true;
return memcmp((char *)&self,(char *)&rhs.self,sizeof(TokenKeyContents)) == 0;
}
//*********************** End of TokenKey::operator== **************************
#pragma page "TokenKey::getTokenKey"
// *****************************************************************************
// * *
// * Function: TokenKey::getTokenKey *
// * Returns the Token Key as an array of bytes. *
// * *
// *****************************************************************************
const char * TokenKey::getTokenKey() const
{
return (const char *)(&self);
}
//******************* End of TokenContents::getTokenKey ************************
#pragma page "TokenKey::getTokenKeyAsString"
// *****************************************************************************
// * *
// * Function: TokenKey::getTokenKeyAsString *
// * Returns the Token Key as a formatted ASCII string. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <tokenKeyString> char * Out *
// * returns the Token Key as a formatted ASCII string. *
// * *
// *****************************************************************************
void TokenKey::getTokenKeyAsString(char *tokenKeyString) const
{
TokenKeyContents decoded;
base64((const char *) self.u.encoded.b64,sizeof(self.u.encoded.b64),
(char *) decoded.u.encoded.b64,false);
int count = sprintf(tokenKeyString,
"ID = '0x%X,0x%X'\nNode ID = %d\nProcess ID = %d\n",
self.ID[0],self.ID[1],decoded.u.token.nodeId,
decoded.u.token.processId);
char *ptr = &tokenKeyString[count];
strcpy(ptr,"Random value = 0x");
ptr += strlen(ptr);
for (size_t i = 0; i < sizeof(self.u.token.rand) / sizeof(self.u.token.rand[0]); i ++)
{
count = sprintf(ptr,"%X",decoded.u.token.rand[i]);
ptr += count;
}
strcpy(ptr,"\nEncoded value = ");
strcat(ptr,self.u.encoded.b64);
}
//*************** End of TokenContents::getTokenKeyAsString ********************
#pragma page "TokenKey::getTokenKeySize"
// *****************************************************************************
// * *
// * Function: TokenKey::getTokenKeySize *
// * Returns the number of bytes in a Token Key. *
// * *
// *****************************************************************************
size_t TokenKey::getTokenKeySize() const
{
return sizeof(TokenKeyContents);
}
//****************** End of TokenContents::getTokenKeySize *********************
#pragma page "TokenKey::reset"
// *****************************************************************************
// * *
// * Function: TokenKey::reset *
// * Resets all the member values to their default. *
// * *
// *****************************************************************************
void TokenKey::reset()
{
// Set/free data members as appropriate
// Use case is the parent MXOSRVR authenticating as different user.
// self.reset();
self.populate();
// Token will get generated once the user is authenticated.
}
//*********************** End of TokenContents::reset **************************
#pragma page "TokenKey::verify"
// *****************************************************************************
// * *
// * Function: TokenKey::verify *
// * *
// * Determines if a token key is valid. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <tokenKey> TokenKey & In *
// * is the token key to be validated against. *
// * *
// *****************************************************************************
bool TokenKey::verify(TokenKey &tokenKey) const
{
// Check to see that the process name matches with the node ID and process IDd
int retval = XZFIL_ERR_OK;
int nid, pid, decoded_nid, decoded_pid;
if (!(*this == tokenKey))
return false;
// decode the token to get the process info
TokenKeyContents decoded_token;
base64((const char *) self.u.encoded.b64,sizeof(self.u.encoded.b64),
(char *) decoded_token.u.encoded.b64,false);
retval = msg_mon_get_process_info(decoded_token.u.token.processName,&nid,&pid);
decoded_nid = decoded_token.u.token.nodeId;
decoded_pid = decoded_token.u.token.processId;
if ((retval == XZFIL_ERR_OK) &&
(nid == decoded_nid) &&
(pid == decoded_pid))
return true;
return false;
}
//************************** End of TokenKey::verify ***************************
#pragma page "TokenKey::verifyParent"
// *****************************************************************************
// * *
// * Function: TokenKey::verifyParent *
// * *
// * Determines if a token key refers to our parent MXOSRVR, and if so, *
// * fetches corresponding authentication black box. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <blackBox> char * Out *
// * is the authentication data (black box) associated with this token. *
// * *
// * <blackBoxLength> size_t & Out *
// * is the number of bytes in <blackBox>. *
// * *
// * <authFn> AuthFunction In *
// * is the function passed by MXOSRVR for verifying and getting *
// * the black box *
// * *
// * *
// *****************************************************************************
bool TokenKey::verifyParent(
char * blackBox,
size_t & blackBoxLength,
AuthFunction authFn) const
{
blackBoxLength = 0;
TokenKeyContents decoded_token;
// First decode the token to get the process name
base64((const char *) self.u.encoded.b64,sizeof(self.u.encoded.b64),
(char *) decoded_token.u.encoded.b64,false);
// Send message to MXOSRVR indicated in the token key. Called MXOSRVR presumably
// verifies we are a child MXOSRVR running as instance ID and either returns
// yes or no, and if yes, includes black box data.
// First get the verification function set by MXOSRVR
// This is set to the address of MXOSRVR_ValidateToken_pst_
// (odbc/nsksrvr/Interface/odbcmxo_drvr.cpp)
int error;
if (authFn == NULL)
return false;
error = (*authFn)( decoded_token.u.token.processName,
sizeof(TokenKeyContents),
(unsigned char *)&self,
4096, // Max size of the BlackBox - need a define
(int *) &blackBoxLength,
(unsigned char *)blackBox );
if (error || blackBoxLength == 0)
return false;
return true;
}
//*********************** End of TokenKey::verifyParent ************************
#pragma page "TokenKeyContents::populate"
// *****************************************************************************
// * *
// * Function: TokenKeyContents::populate *
// * *
// * Populates fields of a token key using information from current *
// * process (node, PID, etc.) and encoding (base64). *
// * *
// *****************************************************************************
void TokenKeyContents::populate()
{
msg_mon_get_my_process_name(u.token.processName, MS_MON_MAX_PROCESS_NAME);
msg_mon_get_process_info( NULL, &u.token.nodeId, &u.token.processId );
ID[0] = USERTOKEN_ID_1;
ID[1] = USERTOKEN_ID_2;
// Generate Random bytes
srandom ((unsigned)time(NULL));
for (int i=0; i < sizeof(u.token.rand); i++)
u.token.rand[i] = (char)(random() & 0xFF);
// Base 64 encoding
char buf[sizeof(u)]= {0};
base64((const char *)&u.token, sizeof(u.token), buf, true);
memcpy(u.encoded.b64, buf, sizeof(u.encoded.b64));
u.encoded.zero='\0';
}
//********************* End of TokenKeyContents::populate **********************
#pragma page "TokenKeyContents::reset"
// *****************************************************************************
// * *
// * Function: TokenKeyContents::reset *
// * *
// * process (node, PID, etc.) and encoding (base64). *
// * *
// *****************************************************************************
void TokenKeyContents::reset()
{
}
//********************** End of TokenKeyContents::reset ************************
#pragma page "base64"
// *****************************************************************************
// * *
// * Function: base64 *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <in> const char * In *
// * is the buffer to be encoded or decoded. *
// * *
// * <inLen> size_t In *
// * is the length (in bytes) of the buffer to be encoded or decoded. *
// * *
// * <out> char * Out *
// * returns the result of the encoding or decoding. *
// * *
// * <env> bool In *
// * is true if encoding and false if decoding. *
// * *
// *****************************************************************************
static int base64(
const char *in,
size_t inLen,
char *out,
bool enc)
{
int len=0;
BIO *bio, *b64;
char *ptr, *buf;
if (enc)
{
// encode to base64 characters
b64 = BIO_new(BIO_f_base64());
bio = BIO_new(BIO_s_mem());
bio = BIO_push(b64, bio);
BIO_write(bio, in, inLen);
BIO_flush(bio);
BIO_get_mem_data(bio, &ptr);
while (*ptr != '\n')
{
*out++ = *ptr++;
len++;
}
*out = '\0';
BIO_free_all(bio);
return len;
}
// decode from base64 characters
buf = (char *)malloc(inLen + 1);
memcpy(buf, in, inLen);
buf[inLen] = '\n';
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_mem_buf(buf, inLen+1);
bio = BIO_push(b64, bio);
len = BIO_read(bio, out, inLen);
BIO_free_all(bio);
free(buf);
return len;
}
//******************************* End of base64 ********************************