801 lines
24 KiB
C
801 lines
24 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Copyright (C) 2007 Wind River Systems
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 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_hash.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sysvar.h>
|
|
|
|
#include <ipnet.h>
|
|
#include <ipnet_routesock.h>
|
|
|
|
#include "ipdhcpc6_duid.h"
|
|
#include "ipdhcpc6_cvthex.h"
|
|
#include "ipdhcpc6_authhash.h"
|
|
|
|
#define IPDHCPC6_DUID_LL_ACTUALSIZE 10
|
|
#define IPDHCPC6_DUID_LLT_ACTUALSIZE 14
|
|
#define IPDHCPC6_DUID_EN_ACTUALSIZE 14
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_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
|
|
ipdhcpc6_authdb_obj_hash (Ipdhcpc6_authkey_dbentry *dbentry)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
|
|
ipcom_printf ("ipdhcpc6_authdb_obj_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(dbentry->duid.data.ll.link_addr);
|
|
for (i = 0 ; i < 6 ; i++)
|
|
{ ipcom_printf ("%2x ", cptr [i]);
|
|
}
|
|
ipcom_printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(dbentry->duid.data), dbentry->duid.len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_authdb_key_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value for a DUID key.
|
|
* Parameters: key - Pointer to the Ipdhcpc6_authkey_duid structure
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipdhcpc6_authdb_key_hash(Ipdhcpc6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
ipcom_printf ("ipdhcpc6_authdb_key_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(key->data.ll.link_addr);
|
|
for (i = 0 ; i < 6 ; i++)
|
|
{ ipcom_printf ("%2x ", cptr [i]);
|
|
}
|
|
ipcom_printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(key->data), key->len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_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
|
|
ipdhcpc6_authdb_hash_cmp(Ipdhcpc6_authkey_dbentry *dbentry, Ipdhcpc6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
ipcom_printf ("ipdhcpc6_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;
|
|
}
|
|
|
|
/*************/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_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
|
|
ipdhcpc6_authtrans_obj_hash (Ipdhcpc6_authtrans_dbentry *dbentry)
|
|
{
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
|
|
ipcom_printf ("ipdhcpc6_authtrans_obj_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(dbentry->duid.data);
|
|
|
|
switch (dbentry->duid.data.generic.content)
|
|
{ case IPDHCPC6_DUID_LL:
|
|
ipcom_printf ("LL content\n");
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_LLT:
|
|
ipcom_printf ("LLT content\n");
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_EN:
|
|
ipcom_printf ("EN content\n");
|
|
break;
|
|
|
|
default:
|
|
ipcom_printf ("default case content\n");
|
|
|
|
}
|
|
|
|
for (i = 0 ; i < dbentry->duid.len ; i++)
|
|
{ ipcom_printf ("%2x ", cptr [i]);
|
|
}
|
|
ipcom_printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(dbentry->duid.data), dbentry->duid.len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_authtrans_key_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value for a DUID key.
|
|
* Parameters: key - Pointer to the Ipdhcpc6_authkey_duid structure
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipdhcpc6_authtrans_key_hash(Ipdhcpc6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
int i;
|
|
unsigned char *cptr;
|
|
ipcom_printf ("ipdhcpc6_authtrans_key_hash called: ");
|
|
|
|
cptr = (unsigned char *) &(key->data);
|
|
|
|
switch (key->data.generic.content)
|
|
{ case IPDHCPC6_DUID_LL:
|
|
ipcom_printf ("LL content\n");
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_LLT:
|
|
ipcom_printf ("LLT content\n");
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_EN:
|
|
ipcom_printf ("EN content\n");
|
|
break;
|
|
|
|
default:
|
|
ipcom_printf ("default case content\n");
|
|
}
|
|
|
|
for (i = 0 ; i < key->len ; i++)
|
|
{ ipcom_printf ("%2x ", cptr [i]);
|
|
}
|
|
ipcom_printf ("\n");
|
|
#endif
|
|
|
|
return ipcom_hash_update(&(key->data), key->len, 0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_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
|
|
ipdhcpc6_authtrans_hash_cmp(Ipdhcpc6_authtrans_dbentry *dbentry, Ipdhcpc6_duid *key)
|
|
{
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
ipcom_printf ("ipdhcpc6_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 *server_authkey_db;
|
|
IP_STATIC Ipcom_hash *server_transaction_db;
|
|
|
|
IP_GLOBAL Ipcom_hash *
|
|
ipdhcpc6_authdb_hash_create(void)
|
|
{
|
|
return ipcom_hash_new ((Ipcom_hash_obj_func) ipdhcpc6_authdb_obj_hash,
|
|
(Ipcom_hash_key_func) ipdhcpc6_authdb_key_hash,
|
|
(Ipcom_hash_cmp_func) ipdhcpc6_authdb_hash_cmp);
|
|
}
|
|
|
|
IP_GLOBAL Ipcom_hash *
|
|
ipdhcpc6_authtrans_hash_create(void)
|
|
{
|
|
return ipcom_hash_new ((Ipcom_hash_obj_func) ipdhcpc6_authtrans_obj_hash,
|
|
(Ipcom_hash_key_func) ipdhcpc6_authtrans_key_hash,
|
|
(Ipcom_hash_cmp_func) ipdhcpc6_authtrans_hash_cmp);
|
|
}
|
|
|
|
IP_GLOBAL Ipdhcpc6_duid *ipdhcpc6_authdb_create_ll_duid (int len, Ip_u16 hwtype, Ip_u8 *link_addr)
|
|
{
|
|
Ipdhcpc6_duid *retval = (Ipdhcpc6_duid *)
|
|
ipcom_malloc (sizeof (struct Ipdhcpc6_duid_struct));
|
|
|
|
if (IP_NULL == retval)
|
|
return IP_NULL;
|
|
|
|
retval->len = IPDHCPC6_DUID_LL_ACTUALSIZE;
|
|
retval->data.ll.content = IPDHCPC6_DUID_LL;
|
|
retval->data.ll.hardware_type = hwtype;
|
|
|
|
ipcom_memcpy (retval->data.ll.link_addr, link_addr, 6);
|
|
|
|
return retval;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcpc6_add_server_authkey (Ipdhcpc6_duid *server_duid,
|
|
Ip_u8 *key, int keylen)
|
|
{
|
|
|
|
Ip_u16 duid_content;
|
|
|
|
Ipdhcpc6_authkey_dbentry *new_authdb_entry = (Ipdhcpc6_authkey_dbentry *)
|
|
ipcom_malloc (sizeof (struct Ipdhcpc6_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);
|
|
#if 0
|
|
IPCOM_LOG0 (DEBUG, "ipdhcpc6_add_server_authkey: no memory!\n");
|
|
#endif
|
|
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 = server_duid->len;
|
|
duid_content = server_duid->data.ll.content;
|
|
|
|
switch (duid_content)
|
|
{
|
|
case IPDHCPC6_DUID_LL:
|
|
new_authdb_entry->duid.data.ll.hardware_type = server_duid->data.ll.hardware_type;
|
|
new_authdb_entry->duid.data.ll.content = IPDHCPC6_DUID_LL;
|
|
|
|
ipcom_memcpy (new_authdb_entry->duid.data.ll.link_addr,
|
|
server_duid->data.ll.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_EN: /* not yet implemented */
|
|
case IPDHCPC6_DUID_LLT: /* not yet implemented */
|
|
default:
|
|
ipcom_free (new_authdb_entry);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
if (IPCOM_SUCCESS != ipcom_hash_add (server_authkey_db, new_authdb_entry))
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
}
|
|
|
|
IP_GLOBAL Ipdhcpc6_authtrans_dbentry *
|
|
ipdhcpc6_create_server_authtrans_entry (union Ipdhcpc6_duid_data *server, int len)
|
|
{
|
|
Ip_u16 server_duid_content;
|
|
Ipdhcpc6_authtrans_dbentry *server_dbentry = IP_NULL;
|
|
|
|
server_dbentry = (Ipdhcpc6_authtrans_dbentry *)
|
|
ipcom_malloc (sizeof (struct Ipdhcpc6_authtrans_dbentry));
|
|
if (IP_NULL == server_dbentry)
|
|
return IP_NULL;
|
|
|
|
server_duid_content = ip_ntohs (server->generic.content);
|
|
|
|
switch (server_duid_content)
|
|
{ case IPDHCPC6_DUID_LLT:
|
|
server_dbentry->duid.len = IPDHCPC6_DUID_LLT_ACTUALSIZE;
|
|
server_dbentry->duid.data.llt.content = IPDHCPC6_DUID_LLT;
|
|
server_dbentry->duid.data.llt.hardware_type = server->llt.hardware_type;
|
|
server_dbentry->duid.data.llt.time = server->llt.time;
|
|
ipcom_memcpy (server_dbentry->duid.data.llt.link_addr,
|
|
server->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPC6_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.
|
|
*/
|
|
|
|
server_dbentry->duid.len =
|
|
(Ip_u16)(len < IPDHCPC6_DUID_EN_ACTUALSIZE ?
|
|
len : IPDHCPC6_DUID_EN_ACTUALSIZE);
|
|
|
|
server_dbentry->duid.data.en.content = IPDHCPC6_DUID_EN;
|
|
server_dbentry->duid.data.en.enterprise_number_1 =
|
|
server->en.enterprise_number_1;
|
|
server_dbentry->duid.data.en.enterprise_number_2 =
|
|
server->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (server_dbentry->duid.data.en.id,
|
|
server->en.id, (Ip_size_t)(8 - (IPDHCPC6_DUID_EN_ACTUALSIZE - len)));
|
|
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_LL:
|
|
server_dbentry->duid.len = IPDHCPC6_DUID_LL_ACTUALSIZE;
|
|
server_dbentry->duid.data.ll.content = IPDHCPC6_DUID_LL;
|
|
server_dbentry->duid.data.ll.hardware_type = server->ll.hardware_type;
|
|
ipcom_memcpy (server_dbentry->duid.data.ll.link_addr,
|
|
server->llt.link_addr, 6);
|
|
break;
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
default:
|
|
ipcom_printf ("found %u (%u) duid\n", server_duid_content,
|
|
ip_htons (server_duid_content));
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* set replay counters
|
|
*/
|
|
|
|
server_dbentry->client_replay1 = 0xdeadbeef;
|
|
server_dbentry->client_replay2 = 0x0;
|
|
server_dbentry->server_replay1 = 0x0;
|
|
server_dbentry->server_replay2 = 0x0;
|
|
|
|
if (IPCOM_SUCCESS != ipcom_hash_add (server_transaction_db, server_dbentry))
|
|
return IP_NULL;
|
|
|
|
return server_dbentry;
|
|
|
|
}
|
|
|
|
|
|
IP_GLOBAL Ip_err ipdhcpc6_server_no_auth (Ipdhcpc6_duid *server_dbkey)
|
|
{
|
|
|
|
Ipdhcpc6_authkey_dbentry *server_dbobj = IP_NULL;
|
|
|
|
server_dbobj = ipcom_hash_get (server_authkey_db, server_dbkey);
|
|
if (IP_NULL == server_dbobj)
|
|
{ ipcom_printf ("no server_dbobj\n");
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
ipcom_hash_remove (server_authkey_db, server_dbobj);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
}
|
|
|
|
IP_GLOBAL Ipdhcpc6_authtrans_dbentry *
|
|
ipdhcpc6_get_server_authtrans_entry (union Ipdhcpc6_duid_data *server, int len)
|
|
{
|
|
Ip_u16 server_duid_content;
|
|
Ipdhcpc6_duid server_dbkey;
|
|
Ipdhcpc6_authtrans_dbentry *server_dbobj = IP_NULL;
|
|
|
|
server_duid_content = ip_ntohs (server->generic.content);
|
|
|
|
switch (server_duid_content)
|
|
{ case IPDHCPC6_DUID_LLT:
|
|
server_dbkey.len = IPDHCPC6_DUID_LLT_ACTUALSIZE;
|
|
server_dbkey.data.llt.content = IPDHCPC6_DUID_LLT;
|
|
server_dbkey.data.llt.hardware_type = server->llt.hardware_type;
|
|
server_dbkey.data.llt.time = server->llt.time;
|
|
ipcom_memcpy (server_dbkey.data.llt.link_addr,
|
|
server->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPC6_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.
|
|
*/
|
|
|
|
server_dbkey.len =
|
|
(Ip_u16)(len < IPDHCPC6_DUID_EN_ACTUALSIZE ?
|
|
len : IPDHCPC6_DUID_EN_ACTUALSIZE);
|
|
|
|
server_dbkey.data.en.content = IPDHCPC6_DUID_EN;
|
|
server_dbkey.data.en.enterprise_number_1 =
|
|
server->en.enterprise_number_1;
|
|
server_dbkey.data.en.enterprise_number_2 =
|
|
server->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (server_dbkey.data.en.id,
|
|
server->en.id, (Ip_size_t)(8 - (IPDHCPC6_DUID_EN_ACTUALSIZE - len)));
|
|
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_LL:
|
|
server_dbkey.len = IPDHCPC6_DUID_LL_ACTUALSIZE;
|
|
server_dbkey.data.ll.content = IPDHCPC6_DUID_LL;
|
|
server_dbkey.data.ll.hardware_type = server->ll.hardware_type;
|
|
ipcom_memcpy (server_dbkey.data.ll.link_addr,
|
|
server->llt.link_addr, 6);
|
|
break;
|
|
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
default:
|
|
ipcom_printf ("found %u (%u) duid\n", server_duid_content,
|
|
ip_htons (server_duid_content));
|
|
#endif
|
|
}
|
|
|
|
server_dbobj = ipcom_hash_get (server_transaction_db, &server_dbkey);
|
|
|
|
if (IP_NULL == server_dbobj)
|
|
{ /* no entry yet. Make one. */
|
|
return ipdhcpc6_create_server_authtrans_entry (server, len);
|
|
}
|
|
|
|
return server_dbobj;
|
|
|
|
}
|
|
|
|
IP_STATIC Ip_u8 authKeyFromSysVars [132];
|
|
IP_STATIC Ip_size_t authKeyLenFromSysVars = 0;
|
|
|
|
IP_STATIC Ip_u8 authKey [132];
|
|
IP_STATIC Ip_size_t authKeyLen = 0;
|
|
|
|
#if 0
|
|
IP_STATIC Ip_u8 authRealmFromSysVars [128];
|
|
IP_STATIC Ip_size_t authRealmLenFromSysVars = 0;
|
|
#endif
|
|
|
|
IP_STATIC Ip_u8 ipdhcpc6_authRealm [128];
|
|
IP_STATIC Ip_size_t ipdhcpc6_authRealmlen = 0;
|
|
|
|
IP_STATIC int ipdhcpc6_user_authdb_inited = 0;
|
|
|
|
IP_GLOBAL Ip_err ipdhcpc6_get_default_auth_key (int *len, Ip_u8 **key)
|
|
{
|
|
*len = (int)authKeyLen;
|
|
*key = authKey;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcpc6_set_default_auth_key (int len, Ip_u8 *key)
|
|
{
|
|
if (len <= (int)sizeof (authKey))
|
|
{
|
|
authKeyLen = (Ip_size_t)len;
|
|
ipcom_memcpy (authKey, key, (Ip_size_t)len);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
else
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
|
|
IP_STATIC Ip_err ipdhcpc6_set_default_auth_key_from_sysvars (void)
|
|
{
|
|
authKeyLenFromSysVars = sizeof (authKeyFromSysVars);
|
|
|
|
if (IP_NULL == ipcom_sysvar_get ("ipdhcpc6.authkey",
|
|
(char *) authKeyFromSysVars,
|
|
&authKeyLenFromSysVars))
|
|
{
|
|
authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
/*
|
|
* check if the value we read is a valid hex key; convert to
|
|
* a key buffer.
|
|
*/
|
|
|
|
if (ipdhcpc6_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 (! ipdhcpc6_cvt_hex_to_membuf (kptr, (unsigned char *) authKey, (int)authKeyLen) )
|
|
{ authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
authKeyLen = 0;
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcpc6_get_auth_realm (int *len, Ip_u8 **realm)
|
|
{
|
|
|
|
*len = (int)ipdhcpc6_authRealmlen;
|
|
*realm = ipdhcpc6_authRealm;
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
IP_GLOBAL Ip_err ipdhcpc6_set_auth_realm (int len, Ip_u8 *realm)
|
|
{
|
|
|
|
if (len <= (int)sizeof (ipdhcpc6_authRealm))
|
|
{
|
|
ipdhcpc6_authRealmlen = (Ip_size_t)len;
|
|
ipcom_memcpy (ipdhcpc6_authRealm, realm, (Ip_size_t)len);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
else
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
IP_STATIC Ip_err ipdhcpc6_set_auth_realm_from_sysvars (void)
|
|
{
|
|
|
|
ipdhcpc6_authRealmlen = sizeof (ipdhcpc6_authRealm);
|
|
|
|
if (IP_NULL == ipcom_sysvar_get("ipdhcpc6.authrealm",
|
|
(char *) ipdhcpc6_authRealm,
|
|
&ipdhcpc6_authRealmlen))
|
|
{
|
|
ipdhcpc6_authRealmlen = 0;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
IP_GLOBAL void ipdhcpc6_authdb_init (void)
|
|
{
|
|
server_authkey_db = ipdhcpc6_authdb_hash_create ();
|
|
server_transaction_db = ipdhcpc6_authtrans_hash_create ();
|
|
|
|
ipdhcpc6_set_auth_realm_from_sysvars ();
|
|
ipdhcpc6_set_default_auth_key_from_sysvars ();
|
|
|
|
ipdhcpc6_user_authdb_inited = 0;
|
|
|
|
/* test_server_specific (); */
|
|
};
|
|
|
|
|
|
IP_GLOBAL Ip_err
|
|
ipdhcpc6_find_key_for_server (union Ipdhcpc6_duid_data *server,
|
|
int duid_len,
|
|
Ip_u8 **key, int *key_len)
|
|
{
|
|
|
|
Ip_u16 server_duid_content;
|
|
Ipdhcpc6_duid server_dbkey;
|
|
Ipdhcpc6_authkey_dbentry *server_dbobj = IP_NULL;
|
|
|
|
server_duid_content = ip_ntohs (server->generic.content);
|
|
|
|
switch (server_duid_content)
|
|
{ case IPDHCPC6_DUID_LLT:
|
|
server_dbkey.len = IPDHCPC6_DUID_LL_ACTUALSIZE;
|
|
server_dbkey.data.ll.content = IPDHCPC6_DUID_LL;
|
|
server_dbkey.data.ll.hardware_type = server->llt.hardware_type;
|
|
ipcom_memcpy (server_dbkey.data.ll.link_addr,
|
|
server->llt.link_addr, 6);
|
|
break;
|
|
|
|
case IPDHCPC6_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.
|
|
*/
|
|
|
|
server_dbkey.len =
|
|
(Ip_u16)(duid_len < IPDHCPC6_DUID_EN_ACTUALSIZE ?
|
|
duid_len : IPDHCPC6_DUID_EN_ACTUALSIZE);
|
|
|
|
server_dbkey.data.en.content = IPDHCPC6_DUID_EN;
|
|
server_dbkey.data.en.enterprise_number_1 =
|
|
server->en.enterprise_number_1;
|
|
server_dbkey.data.en.enterprise_number_2 =
|
|
server->en.enterprise_number_2;
|
|
|
|
ipcom_memcpy (server_dbkey.data.en.id,
|
|
server->en.id, (Ip_size_t)(8 - (IPDHCPC6_DUID_EN_ACTUALSIZE - duid_len)));
|
|
break;
|
|
|
|
case IPDHCPC6_DUID_LL:
|
|
server_dbkey.len = IPDHCPC6_DUID_LL_ACTUALSIZE;
|
|
server_dbkey.data.ll.content = IPDHCPC6_DUID_LL;
|
|
server_dbkey.data.ll.hardware_type = server->ll.hardware_type;
|
|
ipcom_memcpy (server_dbkey.data.ll.link_addr,
|
|
server->llt.link_addr, 6);
|
|
break;
|
|
|
|
default:
|
|
#ifdef DEBUG_DHCPV6_AUTH
|
|
ipcom_printf ("find_key_for_server: found %u (%u) duid\n", server_duid_content,
|
|
ip_htons (server_duid_content));
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
server_dbobj = ipcom_hash_get (server_authkey_db, &server_dbkey);
|
|
if (IP_NULL == server_dbobj)
|
|
{
|
|
/* use default system auth key */
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
else
|
|
{
|
|
/* use server specific key */
|
|
*key_len = server_dbobj->secret.len;
|
|
*key = server_dbobj->secret.key;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
}
|
|
|
|
IP_GLOBAL void ipdhcpc6_block_on_user_authdb_config (void)
|
|
{
|
|
while (1)
|
|
{ if (ipdhcpc6_user_authdb_inited)
|
|
return;
|
|
ipcom_millisleep (250);
|
|
}
|
|
|
|
}
|
|
|
|
IP_GLOBAL void ipdhcpc6_user_authdb_config_finished (void)
|
|
{
|
|
ipdhcpc6_user_authdb_inited = 1;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|