894 lines
27 KiB
C
894 lines
27 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Copyright (C) 2007 Wind River Systems
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01a,17jul07,ps initial checkin of dhcpv6 authentication key database module
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysvar.h>
|
|
|
|
#include <ipnet.h>
|
|
#include <ipnet_routesock.h>
|
|
|
|
#include "ipdhcps6.h"
|
|
#include "ipdhcps6_h.h"
|
|
#include "ipdhcps6_host.h"
|
|
#include "ipdhcps6_prefix.h"
|
|
#include "ipdhcps6_subnet.h"
|
|
#include "ipdhcps6_duid.h"
|
|
#include "ipdhcps6_cvthex.h"
|
|
#include "ipdhcps6_authhash.h"
|
|
|
|
#define IPDHCPS6_DUID_LL_ACTUALSIZE 10
|
|
#define IPDHCPS6_DUID_LLT_ACTUALSIZE 14
|
|
#define IPDHCPS6_DUID_EN_ACTUALSIZE 14
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps6_authdata_obj_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value based on an authkey value.
|
|
* Parameters: dbentry - The option to return a hash value for.
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipdhcps6_authdb_obj_hash (Ipdhcps6_authkey_dbentry *dbentry)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
|
|
printf ("ipdhcps6_authdb_obj_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(dbentry->duid.data.ll.link_addr);
|
|
for (i = 0 ; i < 6 ; i++)
|
|
{ printf ("%2x ", cptr [i]);
|
|
}
|
|
printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(dbentry->duid.data), dbentry->duid.len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps6_authdb_key_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value for a DUID key.
|
|
* Parameters: key - Pointer to the Ipdhcps6_authkey_duid structure
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipdhcps6_authdb_key_hash(Ipdhcps6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
printf ("ipdhcps6_authdb_key_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(key->data.ll.link_addr);
|
|
for (i = 0 ; i < 6 ; i++)
|
|
{ printf ("%2x ", cptr [i]);
|
|
}
|
|
printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(key->data), key->len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps6_authdb_hash_cmp
|
|
*===========================================================================
|
|
* Description: Compares a hash object and a hash key for equality.
|
|
* Parameters: dbentry - An authkey_dbentry structure.
|
|
* key - A pointer to the search key.
|
|
* Returns: IP_TRUE if the search key matches the prefix entry.
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipdhcps6_authdb_hash_cmp(Ipdhcps6_authkey_dbentry *dbentry, Ipdhcps6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
printf ("ipdhcps6_authdb_hash_cmp called\n");
|
|
#endif
|
|
|
|
if (dbentry->duid.len != key->len)
|
|
return IP_FALSE;
|
|
|
|
return ipcom_memcmp(&(dbentry->duid.data), &(key->data),
|
|
key->len) == 0;
|
|
}
|
|
|
|
/*************/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps6_authtrans_obj_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value based on an authkey value.
|
|
* Parameters: dbentry - The option to return a hash value for.
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipdhcps6_authtrans_obj_hash (Ipdhcps6_authtrans_dbentry *dbentry)
|
|
{
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
|
|
printf ("ipdhcps6_authtrans_obj_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(dbentry->duid.data);
|
|
|
|
switch (dbentry->duid.data.generic.content)
|
|
{ case IPDHCPS6_DUID_LL:
|
|
printf ("LL content\n");
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_LLT:
|
|
printf ("LLT content\n");
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN:
|
|
printf ("EN content\n");
|
|
break;
|
|
|
|
default:
|
|
printf ("default case content\n");
|
|
|
|
}
|
|
|
|
for (i = 0 ; i < dbentry->duid.len ; i++)
|
|
{ printf ("%2x ", cptr [i]);
|
|
}
|
|
printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(dbentry->duid.data), dbentry->duid.len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps6_authtrans_key_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value for a DUID key.
|
|
* Parameters: key - Pointer to the Ipdhcps6_authkey_duid structure
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipdhcps6_authtrans_key_hash(Ipdhcps6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
printf ("ipdhcps6_authtrans_key_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(key->data);
|
|
|
|
switch (key->data.generic.content)
|
|
{ case IPDHCPS6_DUID_LL:
|
|
printf ("LL content\n");
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_LLT:
|
|
printf ("LLT content\n");
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN:
|
|
printf ("EN content\n");
|
|
break;
|
|
|
|
default:
|
|
printf ("default case content\n");
|
|
}
|
|
|
|
for (i = 0 ; i < key->len ; i++)
|
|
{ printf ("%2x ", cptr [i]);
|
|
}
|
|
printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(key->data), key->len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps6_authtrans_hash_cmp
|
|
*===========================================================================
|
|
* Description: Compares a hash object and a hash key for equality.
|
|
* Parameters: prefix - A prefix structure.
|
|
* key - A pointer to the search key.
|
|
* Returns: IP_TRUE if the search key matches the prefix entry.
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipdhcps6_authtrans_hash_cmp(Ipdhcps6_authtrans_dbentry *dbentry, Ipdhcps6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
printf ("ipdhcps6_authtrans_hash_cmp called\n");
|
|
#endif
|
|
|
|
if (dbentry->duid.len != key->len)
|
|
return IP_FALSE;
|
|
|
|
return ipcom_memcmp(&(dbentry->duid.data), &(key->data),
|
|
key->len) == 0;
|
|
}
|
|
|
|
|
|
/*****************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_STATIC Ipcom_hash *client_authkey_db;
|
|
IP_STATIC Ipcom_hash *client_transaction_db;
|
|
|
|
IP_GLOBAL Ipcom_hash *
|
|
ipdhcps6_authdb_hash_create(void)
|
|
{
|
|
return ipcom_hash_new ((Ipcom_hash_obj_func) ipdhcps6_authdb_obj_hash,
|
|
(Ipcom_hash_key_func) ipdhcps6_authdb_key_hash,
|
|
(Ipcom_hash_cmp_func) ipdhcps6_authdb_hash_cmp);
|
|
}
|
|
|
|
IP_GLOBAL Ipcom_hash *
|
|
ipdhcps6_authtrans_hash_create(void)
|
|
{
|
|
return ipcom_hash_new ((Ipcom_hash_obj_func) ipdhcps6_authtrans_obj_hash,
|
|
(Ipcom_hash_key_func) ipdhcps6_authtrans_key_hash,
|
|
(Ipcom_hash_cmp_func) ipdhcps6_authtrans_hash_cmp);
|
|
}
|
|
|
|
IP_GLOBAL Ipdhcps6_duid *ipdhcps6_authdb_create_ll_duid (int len, Ip_u16 hwtype, Ip_u8 *link_addr)
|
|
{
|
|
Ipdhcps6_duid *retval = (Ipdhcps6_duid *)
|
|
ipcom_malloc (sizeof (struct Ipdhcps6_duid_struct));
|
|
|
|
(void)len;
|
|
|
|
if (IP_NULL == retval)
|
|
return IP_NULL;
|
|
|
|
retval->len = IPDHCPS6_DUID_LL_ACTUALSIZE;
|
|
retval->data.ll.content = IPDHCPS6_DUID_LL;
|
|
retval->data.ll.hardware_type = hwtype;
|
|
|
|
ipcom_memcpy (retval->data.ll.link_addr, link_addr, 6);
|
|
|
|
return retval;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_add_client_authkey (Ipdhcps6_duid *client_duid,
|
|
Ip_u8 *key, int keylen)
|
|
{
|
|
|
|
Ip_u16 duid_content;
|
|
|
|
Ipdhcps6_authkey_dbentry *new_authdb_entry = (Ipdhcps6_authkey_dbentry *)
|
|
ipcom_malloc (sizeof (struct Ipdhcps6_authkey_dbentry));
|
|
|
|
if (IP_NULL == new_authdb_entry)
|
|
return IPCOM_ERR_FAILED;
|
|
|
|
new_authdb_entry->secret.key = (Ip_u8 *) ipcom_malloc ((Ip_size_t)keylen);
|
|
if (IP_NULL == new_authdb_entry->secret.key)
|
|
{ ipcom_free (new_authdb_entry);
|
|
IPCOM_LOG0 (DEBUG, "ipdhcps6_add_client_authkey: no memory!\n");
|
|
return IPCOM_ERR_NO_MEMORY;
|
|
}
|
|
|
|
/*
|
|
* copy in key
|
|
*/
|
|
ipcom_memcpy (new_authdb_entry->secret.key, key, (Ip_size_t)keylen);
|
|
new_authdb_entry->secret.len = keylen;
|
|
|
|
/*
|
|
* copy in duid data
|
|
*/
|
|
|
|
new_authdb_entry->duid.len = client_duid->len;
|
|
duid_content = client_duid->data.ll.content;
|
|
|
|
switch (duid_content)
|
|
{
|
|
case IPDHCPS6_DUID_LL:
|
|
new_authdb_entry->duid.data.ll.hardware_type = client_duid->data.ll.hardware_type;
|
|
new_authdb_entry->duid.data.ll.content = IPDHCPS6_DUID_LL;
|
|
|
|
ipcom_memcpy (new_authdb_entry->duid.data.ll.link_addr,
|
|
client_duid->data.ll.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN: /* not yet implemented */
|
|
case IPDHCPS6_DUID_LLT: /* not yet implemented */
|
|
default:
|
|
/* Coverity defect fix for RESOURCE_LEAK */
|
|
ipcom_free( new_authdb_entry->secret.key);
|
|
ipcom_free (new_authdb_entry);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
if (IPCOM_SUCCESS != ipcom_hash_add (client_authkey_db, new_authdb_entry))
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_client_wants_auth (union Ipdhcps6_duid_data *client, int len)
|
|
{
|
|
Ip_u16 client_duid_content;
|
|
Ipdhcps6_authtrans_dbentry *client_dbentry = IP_NULL;
|
|
|
|
client_dbentry = (Ipdhcps6_authtrans_dbentry *)
|
|
ipcom_malloc (sizeof (struct Ipdhcps6_authtrans_dbentry));
|
|
if (IP_NULL == client_dbentry)
|
|
return IPCOM_ERR_NO_MEMORY;
|
|
|
|
client_duid_content = ip_ntohs (client->generic.content);
|
|
|
|
switch (client_duid_content)
|
|
{ case IPDHCPS6_DUID_LLT:
|
|
client_dbentry->duid.len = IPDHCPS6_DUID_LLT_ACTUALSIZE;
|
|
client_dbentry->duid.data.llt.content = IPDHCPS6_DUID_LLT;
|
|
client_dbentry->duid.data.llt.hardware_type = client->llt.hardware_type;
|
|
client_dbentry->duid.data.llt.time = client->llt.time;
|
|
ipcom_memcpy (client_dbentry->duid.data.llt.link_addr,
|
|
client->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN:
|
|
|
|
/*
|
|
* FIXME
|
|
* using the duid union structure we have, we know we will have
|
|
* enough space to copy in the first 8 bytes of the enterprise
|
|
* ID. This may or may not be enough to be unique; we'll need
|
|
* to revisit this later. Look at "len" to see if we were given
|
|
* less than 8 bytes for the ID; if so, only copy the bytes
|
|
* given.
|
|
*/
|
|
|
|
client_dbentry->duid.len =
|
|
(Ip_u16)(len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
|
|
len : IPDHCPS6_DUID_EN_ACTUALSIZE);
|
|
|
|
client_dbentry->duid.data.en.content = IPDHCPS6_DUID_EN;
|
|
client_dbentry->duid.data.en.enterprise_number_1 =
|
|
client->en.enterprise_number_1;
|
|
client_dbentry->duid.data.en.enterprise_number_2 =
|
|
client->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (client_dbentry->duid.data.en.id,
|
|
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - len)));
|
|
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_LL:
|
|
client_dbentry->duid.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
|
|
client_dbentry->duid.data.ll.content = IPDHCPS6_DUID_LL;
|
|
client_dbentry->duid.data.ll.hardware_type = client->ll.hardware_type;
|
|
ipcom_memcpy (client_dbentry->duid.data.ll.link_addr,
|
|
client->ll.link_addr, 6);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* set replay counters
|
|
*/
|
|
|
|
client_dbentry->server_replay1 = 0xdeadbeef;
|
|
client_dbentry->server_replay2 = 0x0;
|
|
client_dbentry->client_replay1 = 0x0;
|
|
client_dbentry->client_replay2 = 0x0;
|
|
|
|
if (IPCOM_SUCCESS != ipcom_hash_add (client_transaction_db, client_dbentry))
|
|
return IPCOM_ERR_FAILED;
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_client_no_auth (union Ipdhcps6_duid_data *client, int len)
|
|
{
|
|
|
|
Ip_u16 client_duid_content;
|
|
Ipdhcps6_duid client_dbkey;
|
|
Ipdhcps6_authkey_dbentry *client_dbobj = IP_NULL;
|
|
|
|
client_duid_content = ip_ntohs (client->generic.content);
|
|
|
|
switch (client_duid_content)
|
|
{ case IPDHCPS6_DUID_LLT:
|
|
client_dbkey.len = IPDHCPS6_DUID_LLT_ACTUALSIZE;
|
|
client_dbkey.data.llt.content = IPDHCPS6_DUID_LLT;
|
|
client_dbkey.data.llt.hardware_type = client->llt.hardware_type;
|
|
client_dbkey.data.llt.time = client->llt.time;
|
|
ipcom_memcpy (client_dbkey.data.llt.link_addr,
|
|
client->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN:
|
|
/*
|
|
* FIXME
|
|
* using the duid union structure we have, we know we will have
|
|
* enough space to copy in the first 8 bytes of the enterprise
|
|
* ID. This may or may not be enough to be unique; we'll need
|
|
* to revisit this later. Look at "len" to see if we were given
|
|
* less than 8 bytes for the ID; if so, only copy the bytes
|
|
* given.
|
|
*/
|
|
|
|
client_dbkey.len =
|
|
(Ip_u16)(len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
|
|
len : IPDHCPS6_DUID_EN_ACTUALSIZE);
|
|
|
|
client_dbkey.data.en.content = IPDHCPS6_DUID_EN;
|
|
client_dbkey.data.en.enterprise_number_1 =
|
|
client->en.enterprise_number_1;
|
|
client_dbkey.data.en.enterprise_number_2 =
|
|
client->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (client_dbkey.data.en.id,
|
|
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - len)));
|
|
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_LL:
|
|
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
|
|
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
|
|
client_dbkey.data.ll.hardware_type = client->ll.hardware_type;
|
|
ipcom_memcpy (client_dbkey.data.ll.link_addr,
|
|
client->ll.link_addr, 6);
|
|
break;
|
|
|
|
default:
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
client_dbobj = ipcom_hash_get (client_transaction_db, &client_dbkey);
|
|
if (IP_NULL == client_dbobj)
|
|
{
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
ipcom_hash_remove (client_transaction_db, client_dbobj);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
}
|
|
|
|
IP_GLOBAL Ipdhcps6_authtrans_dbentry *
|
|
ipdhcps6_client_requested_auth (union Ipdhcps6_duid_data *client, int len)
|
|
{
|
|
Ip_u16 client_duid_content;
|
|
Ipdhcps6_duid client_dbkey;
|
|
Ipdhcps6_authtrans_dbentry *client_dbobj = IP_NULL;
|
|
|
|
client_duid_content = ip_ntohs (client->generic.content);
|
|
|
|
switch (client_duid_content)
|
|
{ case IPDHCPS6_DUID_LLT:
|
|
client_dbkey.len = IPDHCPS6_DUID_LLT_ACTUALSIZE;
|
|
client_dbkey.data.llt.content = IPDHCPS6_DUID_LLT;
|
|
client_dbkey.data.llt.hardware_type = client->llt.hardware_type;
|
|
client_dbkey.data.llt.time = client->llt.time;
|
|
ipcom_memcpy (client_dbkey.data.llt.link_addr,
|
|
client->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN:
|
|
/*
|
|
* FIXME
|
|
* using the duid union structure we have, we know we will have
|
|
* enough space to copy in the first 8 bytes of the enterprise
|
|
* ID. This may or may not be enough to be unique; we'll need
|
|
* to revisit this later. Look at "len" to see if we were given
|
|
* less than 8 bytes for the ID; if so, only copy the bytes
|
|
* given.
|
|
*/
|
|
|
|
client_dbkey.len =
|
|
(Ip_u16)(len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
|
|
len : IPDHCPS6_DUID_EN_ACTUALSIZE);
|
|
|
|
client_dbkey.data.en.content = IPDHCPS6_DUID_EN;
|
|
client_dbkey.data.en.enterprise_number_1 =
|
|
client->en.enterprise_number_1;
|
|
client_dbkey.data.en.enterprise_number_2 =
|
|
client->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (client_dbkey.data.en.id,
|
|
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - len)));
|
|
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_LL:
|
|
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
|
|
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
|
|
client_dbkey.data.ll.hardware_type = client->ll.hardware_type;
|
|
ipcom_memcpy (client_dbkey.data.ll.link_addr,
|
|
client->ll.link_addr, 6);
|
|
break;
|
|
|
|
default:
|
|
/* invalid DUID type; ignore it and return failure */
|
|
return IP_NULL;
|
|
}
|
|
|
|
client_dbobj = ipcom_hash_get (client_transaction_db, &client_dbkey);
|
|
if (IP_NULL == client_dbobj)
|
|
return IP_NULL;
|
|
|
|
return client_dbobj;
|
|
|
|
}
|
|
|
|
#define MAX_IPDHCPV6_AUTH_KEY_SIZE 128
|
|
|
|
IP_STATIC int authKeyInitialized = 0;
|
|
IP_STATIC int authRealmInitialized = 0;
|
|
|
|
IP_STATIC Ip_u8 authKeyFromSysVars [256];
|
|
IP_STATIC Ip_size_t authKeyLenFromSysVars = 0;
|
|
|
|
IP_STATIC Ip_u8 authKey [128];
|
|
IP_STATIC Ip_size_t authKeyLen = 0;
|
|
|
|
IP_STATIC Ip_u8 authRealmFromSysVars [128];
|
|
IP_STATIC Ip_size_t authRealmLenFromSysVars = 0;
|
|
|
|
|
|
IP_STATIC Ip_err ipdhcps6_set_default_auth_key_from_sysvars (void)
|
|
{
|
|
|
|
authKeyLenFromSysVars = sizeof (authKeyFromSysVars);
|
|
|
|
(void)ipcom_sysvar_get("ipdhcps6.authkey", (char *) authKeyFromSysVars,
|
|
&authKeyLenFromSysVars);
|
|
|
|
/*
|
|
* check if the value we read is a valid hex key; convert to
|
|
* a key buffer.
|
|
*/
|
|
|
|
if (ipdhcps6_check_is_hex_string ((char *) authKeyFromSysVars))
|
|
{
|
|
/* we need at least 4 characters to proceed here; "0x--" or more */
|
|
if (authKeyLenFromSysVars >= 4)
|
|
{ char *kptr = (char *) authKeyFromSysVars;
|
|
kptr += 2; /* get past leading "0x" */
|
|
|
|
authKeyLen = (authKeyLenFromSysVars - 2) / 2;
|
|
if (! ipdhcps6_cvt_hex_to_membuf (kptr, authKey, (int)authKeyLen) )
|
|
{ authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
authKeyInitialized = 1;
|
|
return IPCOM_SUCCESS;
|
|
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_set_default_auth_key (char *authkey)
|
|
{
|
|
Ip_size_t auth_key_len;
|
|
|
|
auth_key_len = strlen (authkey);
|
|
|
|
if (auth_key_len > ((MAX_IPDHCPV6_AUTH_KEY_SIZE + 1) * 2))
|
|
{ return IPCOM_ERR_FAILED; /* given key is too large */
|
|
}
|
|
|
|
/*
|
|
* check if the value we read is a valid hex key; convert to
|
|
* a key buffer.
|
|
*/
|
|
|
|
if (ipdhcps6_check_is_hex_string (authkey))
|
|
{
|
|
/* we need at least 4 characters to proceed here; "0x--" or more */
|
|
if (auth_key_len >= 4)
|
|
{ char *kptr = authkey;
|
|
kptr += 2; /* get past leading "0x" */
|
|
|
|
authKeyLen = (auth_key_len - 2) / 2;
|
|
if (! ipdhcps6_cvt_hex_to_membuf (kptr, authKey, (int)authKeyLen) )
|
|
{ authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
authKeyInitialized = 1;
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_get_default_auth_key (Ip_size_t *len, Ip_u8 **key)
|
|
{
|
|
if (authKeyInitialized)
|
|
{
|
|
*len = authKeyLen;
|
|
*key = authKey;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
if (IPCOM_SUCCESS == ipdhcps6_set_default_auth_key_from_sysvars ())
|
|
{
|
|
*len = authKeyLen;
|
|
*key = authKey;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
}
|
|
*key = IP_NULL;
|
|
*len = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
|
|
}
|
|
|
|
IP_STATIC Ip_err ipdhcps6_set_auth_realm_from_sysvars ()
|
|
{
|
|
|
|
authRealmLenFromSysVars = sizeof (authRealmFromSysVars);
|
|
|
|
if (ipcom_sysvar_get("ipdhcps6.authrealm", (char *) authRealmFromSysVars,
|
|
&authRealmLenFromSysVars) == IP_NULL)
|
|
{
|
|
/* Don't set it if we dont got it */
|
|
authRealmLenFromSysVars = 0;
|
|
}
|
|
|
|
|
|
if (authRealmLenFromSysVars > 0)
|
|
{
|
|
authRealmInitialized = 1;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_set_auth_realm (char *auth_realm)
|
|
{
|
|
Ip_size_t realm_len;
|
|
|
|
authRealmInitialized = 0;
|
|
|
|
realm_len = strlen (auth_realm);
|
|
|
|
if ((unsigned)realm_len > (sizeof (authRealmFromSysVars) - 1))
|
|
{ /* passed in realm is too large. */
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
strncpy ((char *) authRealmFromSysVars, auth_realm, realm_len);
|
|
authRealmFromSysVars [realm_len] = '\0';
|
|
authRealmLenFromSysVars = realm_len;
|
|
|
|
authRealmInitialized = 1;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_get_auth_realm (Ip_size_t *len, Ip_u8 **realm)
|
|
{
|
|
|
|
if (authRealmInitialized)
|
|
{ *len = authRealmLenFromSysVars;
|
|
*realm = authRealmFromSysVars;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
else
|
|
{ if (IPCOM_SUCCESS == ipdhcps6_set_auth_realm_from_sysvars ())
|
|
{
|
|
*len = authRealmLenFromSysVars;
|
|
*realm = authRealmFromSysVars;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
}
|
|
|
|
*len = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
IP_GLOBAL void ipdhcps6_authdb_init (void)
|
|
{
|
|
client_authkey_db = ipdhcps6_authdb_hash_create ();
|
|
client_transaction_db = ipdhcps6_authtrans_hash_create ();
|
|
}
|
|
|
|
|
|
IP_GLOBAL Ip_err ipdhcps6_find_key_for_client (union Ipdhcps6_duid_data *client,
|
|
int duid_len,
|
|
Ip_u8 **key, Ip_size_t *key_len)
|
|
{
|
|
|
|
Ip_u16 client_duid_content;
|
|
Ipdhcps6_duid client_dbkey;
|
|
Ipdhcps6_authkey_dbentry *client_dbobj = IP_NULL;
|
|
|
|
client_duid_content = ip_ntohs (client->generic.content);
|
|
|
|
switch (client_duid_content)
|
|
{ case IPDHCPS6_DUID_LLT:
|
|
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
|
|
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
|
|
client_dbkey.data.ll.hardware_type = client->llt.hardware_type;
|
|
ipcom_memcpy (client_dbkey.data.ll.link_addr,
|
|
client->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_EN:
|
|
/*
|
|
* FIXME
|
|
* using the duid union structure we have, we know we will have
|
|
* enough space to copy in the first 8 bytes of the enterprise
|
|
* ID. This may or may not be enough to be unique; we'll need
|
|
* to revisit this later. Look at "len" to see if we were given
|
|
* less than 8 bytes for the ID; if so, only copy the bytes
|
|
* given.
|
|
*/
|
|
|
|
client_dbkey.len =
|
|
(Ip_u16)(duid_len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
|
|
duid_len : IPDHCPS6_DUID_EN_ACTUALSIZE);
|
|
|
|
client_dbkey.data.en.content = IPDHCPS6_DUID_EN;
|
|
client_dbkey.data.en.enterprise_number_1 =
|
|
client->en.enterprise_number_1;
|
|
client_dbkey.data.en.enterprise_number_2 =
|
|
client->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (client_dbkey.data.en.id,
|
|
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - duid_len)));
|
|
break;
|
|
|
|
case IPDHCPS6_DUID_LL:
|
|
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
|
|
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
|
|
client_dbkey.data.ll.hardware_type = client->ll.hardware_type;
|
|
ipcom_memcpy (client_dbkey.data.ll.link_addr,
|
|
client->ll.link_addr, 6);
|
|
break;
|
|
|
|
default:
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
client_dbobj = ipcom_hash_get (client_authkey_db, &client_dbkey);
|
|
if (IP_NULL == client_dbobj)
|
|
{
|
|
/* use default system auth key */
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
else
|
|
{
|
|
/* use client specific key */
|
|
*key_len = (Ip_size_t)client_dbobj->secret.len;
|
|
*key = client_dbobj->secret.key;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
}
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|