1297 lines
42 KiB
C
1297 lines
42 KiB
C
/* ipwps_credentials.c - IPWPS Credentials module */
|
|
|
|
/*
|
|
* Copyright (c) 2009 Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute, modify, or otherwise make use
|
|
* of this software may be licensed only pursuant to the terms
|
|
* of an applicable Wind River license agreement.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01a,28Apr09,mry Created
|
|
*/
|
|
|
|
/* DESCRIPTION:
|
|
* ===========
|
|
* Implements the IPWPS Credential configuration/auto-generation.
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
#include "ipwps_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_errno.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_sysvar.h>
|
|
|
|
|
|
#include "ipwps_core.h"
|
|
#include "ipwps_credentials.h"
|
|
#include "ipwps_debug.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipwps_credential_sysvar_list_st {
|
|
char *sysvar_netidx;
|
|
char *sysvar_ssid;
|
|
char *sysvar_auth;
|
|
char *sysvar_encr;
|
|
char *sysvar_keyidx;
|
|
char *sysvar_netkey;
|
|
char *sysvar_8021x;
|
|
char *sysvar_eapid;
|
|
char *sysvar_eaptype;
|
|
} Ipwps_credential_sysvar_list;
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
extern IP_GLOBAL Ip_err ipwps_parse_hex_sysvar(char *sysvar, Ip_u8 *val, Ip_u16 size);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
IP_STATIC IP_CONST char *ipwps_credentials_method_name(Ipwps_credential_method cred_method);
|
|
IP_STATIC Ip_err ipwps_credentials_set_method(Ipwps_ctx* ctx, Ipwps_credential_method cred_method);
|
|
IP_STATIC Ip_err ipwps_credentials_auto_new(Ipwps_ctx* ctx);
|
|
IP_STATIC Ip_err ipwps_credentials_default_set(Ipwps_ctx* ctx);
|
|
IP_STATIC Ip_err ipwps_credentials_interact_add(Ipwps_ctx* ctx, Ip_u16 setid);
|
|
IP_STATIC Ip_err ipwps_credentials_delete(Ipwps_ctx* ctx, Ip_u16 setid);
|
|
|
|
IP_STATIC Ip_err ipwps_credentials_duplicate_builtin_reg(Ipwps_ctx* ctx);
|
|
IP_STATIC Ip_err ipwps_credentials_duplicate_set(Ipwps_ctx* ctx, Ip_u16 to_setid, Ip_u16 from_setid);
|
|
IP_STATIC Ipwps_credential_set *ipwps_credentials_get_cred_ptr(Ipwps_ctx* ctx, Ip_u16 setid);
|
|
|
|
IP_STATIC Ip_err ipwps_credentials_generate_new(Ipwps_ctx* ctx, Ipwps_credential_set *cred);
|
|
IP_STATIC Ip_err ipwps_credentials_default_retrieve(Ipwps_ctx* ctx, Ipwps_credential_set *cred);
|
|
IP_STATIC Ip_err ipwps_credentials_interact_retrieve(Ipwps_ctx* ctx, Ipwps_credential_set *cred);
|
|
|
|
IP_STATIC Ip_err ipwps_credentials_retrieve_from_sysvars(Ipwps_credential_set *cred, Ipwps_credential_sysvar_list *syslist);
|
|
IP_STATIC Ip_err ipwps_credentials_verify_allhex(IP_CONST char *string);
|
|
IP_STATIC Ip_err ipwps_credentials_verify_allascii(IP_CONST char *string);
|
|
IP_STATIC Ip_err ipwps_credentials_verify_netkey(IP_CONST char *netkey);
|
|
|
|
IP_GLOBAL Ip_err ipwps_credentials_gen_random_ascii(char *buf, Ip_u16 size);
|
|
IP_GLOBAL Ip_err ipwps_credentials_gen_random_hex(char *buf, Ip_u16 size);
|
|
|
|
IP_GLOBAL Ip_err ipwps_credentials_notify_register(Ipwps_ctx* ctx, Ipwps_credentials_notify_fn notify_fn);
|
|
IP_GLOBAL Ip_err ipwps_credentials_notify_deregister(Ipwps_ctx* ctx, Ipwps_credentials_notify_fn notify_fn);
|
|
IP_STATIC void ipwps_credentials_notify(Ipwps_ctx* ctx, Ip_u16 setid, Ipwps_credential_notify_type ntype);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_credentials_add_set(Ipwps_ctx* ctx, Ip_u16 setid, Ipwps_credential_set *from_cred);
|
|
IP_GLOBAL void ipwps_credentials_remove_set(Ipwps_ctx* ctx, Ip_u16 setid);
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_init
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipwps_credentials_init(Ipwps_ctx* ctx) {
|
|
char method[IPWPS_CREDENTIALS_CONFIG_METHOD_STRLEN];
|
|
Ip_size_t len;
|
|
Ipwps_credential_method cred_method;
|
|
Ip_err rc = IPCOM_SUCCESS;
|
|
|
|
ip_assert(ctx);
|
|
|
|
if (ctx->public.daemon_status < IPWPSD_STATUS_CONFIGURED) {
|
|
IPCOM_LOG2(CRIT, "ipwps_credentials_init :: Error! Invalid daemon state %s (%d)",
|
|
ipwps_daemon_status(&ctx->public), ctx->public.daemon_status);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
/* Just delete the enrollee credentials when reinitializing */
|
|
ipcom_memset(&ctx->credentials.enrollee_credentials, 0, sizeof(Ipwps_credential_set));
|
|
ctx->credentials.num_enrollee_creds = 0;
|
|
|
|
len = sizeof(method);
|
|
if (!ipcom_sysvar_get(IPWPS_SYSVAR_CREDENTIAL_METHOD, method, &len)) {
|
|
/* This is a valid thing to have. If the sysvar is missing, it means the credentials module was not selected.
|
|
* We will return a success and let other apps that depend on this complain if they need it.
|
|
* This is acceptable if the device is running an Enrollee only.
|
|
*/
|
|
ipcom_strncpy(ctx->public.coop_info.credentials_config_method,
|
|
ipwps_credentials_method_name(IPWPS_CERDENTIAL_METHOD_NOTSET),
|
|
IPWPS_CREDENTIALS_CONFIG_METHOD_STRLEN);
|
|
IPCOM_LOG1(INFO, "Failed to get %s sysvar. Credentials Module is disabled.", IPWPS_SYSVAR_CREDENTIAL_METHOD);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
if (ipcom_strcmp(method, IPWPS_CRED_CONFIG_METHOD_AUTO) == 0) {
|
|
cred_method = IPWPS_CERDENTIAL_METHOD_AUTO;
|
|
} else if (ipcom_strcmp(method, IPWPS_CRED_CONFIG_METHOD_DEFAULT) == 0) {
|
|
cred_method = IPWPS_CERDENTIAL_METHOD_DEFAULT;
|
|
} else if (ipcom_strcmp(method, IPWPS_CRED_CONFIG_METHOD_INTERACT) == 0) {
|
|
cred_method = IPWPS_CERDENTIAL_METHOD_INTERACTIVE;
|
|
} else {
|
|
IPCOM_LOG2(ERR, "ipwps_credentials_init :: Invalid config method \"%s\" specified in sysvar %s.",
|
|
method, IPWPS_SYSVAR_CREDENTIAL_METHOD);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
if (ipwps_credentials_set_method(ctx, cred_method) != IPCOM_SUCCESS) {
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
/* In case we are init in auto mode, we need to gen a new set of credentials */
|
|
if ((cred_method == IPWPS_CERDENTIAL_METHOD_AUTO) && !ctx->credentials.ap_credentials.valid)
|
|
rc = ipwps_credentials_auto_new(ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_shutdown
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipwps_credentials_shutdown(Ipwps_ctx* ctx) {
|
|
|
|
ip_assert(ctx);
|
|
/* Leave AP and registrar credentials alone */
|
|
ipcom_memset(&ctx->credentials.enrollee_credentials, 0, sizeof(ctx->credentials.enrollee_credentials));
|
|
ctx->credentials.num_enrollee_creds =0;
|
|
ipcom_memset(ctx->credential_notify_fn, 0, IPWPS_MAX_CREDENTIAL_NOTIFY_FNS*sizeof(void *));
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_shutdown
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipwps_credentials_clear(Ipwps_ctx* ctx) {
|
|
|
|
ip_assert(ctx);
|
|
|
|
ipcom_memset(&ctx->credentials, 0, sizeof(ctx->credentials));
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_handle_event
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipwps_credentials_handle_event(Ipwps_ctx* ctx) {
|
|
Ip_err rc = IPCOM_ERR_FAILED;
|
|
Ipwps_event_msg *rcv_event_msg = IPWPS_CTX_RCVD_EVENT_MSG(ctx);
|
|
Ipwps_credential_method cred_method;
|
|
Ip_u16 cred_setno;
|
|
|
|
ip_assert(ctx);
|
|
|
|
if (ctx->event != IPWPS_IPD_EVENT_WPSAPI) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_handle_event :: Error! Unsupported event (%d)", ctx->event);
|
|
rc = IPCOM_ERR_NOT_SUPPORTED;
|
|
goto cred_resp;
|
|
}
|
|
if (ctx->rcvd_ipd_msg.wps_msg_type.wpsapi != IPWPS_MSG_TYPE_WPSAPI_CREDENTIAL_EVENT) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_handle_event :: Received WPSAPI event with UNEXPECTED wps_msg_type %d.",
|
|
ctx->rcvd_ipd_msg.wps_msg_type);
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cred_resp;
|
|
}
|
|
switch (rcv_event_msg->event_type.credential_event) {
|
|
case IPWPS_CREDENTIAL_EVENT_SETMETHOD:
|
|
if (!rcv_event_msg->event_data.valid) {
|
|
IPCOM_LOG0(ERR, "Ipwps_pin_handle_event :: Invalid event data");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cred_resp;
|
|
}
|
|
cred_method = rcv_event_msg->event_data.u.credential_method;
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG2(DEBUG2, "ipwps_credentials_handle_event :: Received IPWPS_CREDENTIAL_EVENT_SETMETHOD event with cred_method %d (%s)",
|
|
cred_method, ipwps_credentials_method_name(cred_method));
|
|
#endif
|
|
rc = ipwps_credentials_set_method(ctx, cred_method);
|
|
break;
|
|
case IPWPS_CREDENTIAL_EVENT_ADDCRED:
|
|
if (!rcv_event_msg->event_data.valid) {
|
|
IPCOM_LOG0(ERR, "Ipwps_pin_handle_event :: Invalid event data");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cred_resp;
|
|
}
|
|
cred_setno = rcv_event_msg->event_data.u.credential_setno;
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(DEBUG2, "ipwps_credentials_handle_event :: Received IPWPS_CREDENTIAL_EVENT_ADDCRED event with cred_setno %d",
|
|
cred_setno);
|
|
#endif
|
|
rc = ipwps_credentials_interact_add(ctx, cred_setno);
|
|
break;
|
|
case IPWPS_CREDENTIAL_EVENT_DELCRED:
|
|
if (!rcv_event_msg->event_data.valid) {
|
|
IPCOM_LOG0(ERR, "Ipwps_pin_handle_event :: Invalid event data");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cred_resp;
|
|
}
|
|
cred_setno = rcv_event_msg->event_data.u.credential_setno;
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(DEBUG2, "ipwps_credentials_handle_event :: Received IPWPS_CREDENTIAL_EVENT_DELCRED event with cred_setno %d",
|
|
cred_setno);
|
|
#endif
|
|
rc = ipwps_credentials_delete(ctx, cred_setno);
|
|
break;
|
|
case IPWPS_CREDENTIAL_EVENT_NEWCRED:
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG0(DEBUG2, "ipwps_credentials_handle_event :: Received IPWPS_CREDENTIAL_EVENT_NEWCRED event");
|
|
#endif
|
|
rc = ipwps_credentials_auto_new(ctx);
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_handle_event :: Invalid Credential event %d",
|
|
rcv_event_msg->event_type.credential_event);
|
|
rc = IPCOM_ERR_FAILED;
|
|
break;
|
|
}
|
|
|
|
cred_resp:
|
|
IPWPS_PREPARE_RESPONSE_MSG(ctx, rc);
|
|
ipwps_send_response_msg(ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_set_method
|
|
*===========================================================================
|
|
* Description: Set a credential method. In case of "default" method, the
|
|
* AP credentials, and if applicable 1st built-in registrar credential set,
|
|
* are overwritten.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_set_method(Ipwps_ctx* ctx, Ipwps_credential_method cred_method) {
|
|
Ip_err rc = IPCOM_SUCCESS;
|
|
IP_CONST char *method;
|
|
|
|
ip_assert(ctx);
|
|
|
|
method = ipwps_credentials_method_name(cred_method);
|
|
switch (cred_method) {
|
|
case IPWPS_CERDENTIAL_METHOD_AUTO:
|
|
case IPWPS_CERDENTIAL_METHOD_DEFAULT:
|
|
case IPWPS_CERDENTIAL_METHOD_INTERACTIVE:
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_set_method :: Invalid cred_method %d", cred_method);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
/* Add sysvar so that when we reconfig, it is enabled again */
|
|
IPWPS_SYSVARSET(IPWPS_SYSVAR_CREDENTIAL_METHOD, method, IPCOM_ERR_FAILED);
|
|
ipcom_strncpy(ctx->public.coop_info.credentials_config_method, method, IPWPS_CREDENTIALS_CONFIG_METHOD_STRLEN);
|
|
ctx->public.coop_info.cred_method = cred_method;
|
|
ctx->public.wps_credentials_module.enabled = IP_TRUE;
|
|
ctx->public.wps_credentials_module.status = IPWPSD_MODULE_STATUS_READY;
|
|
if (cred_method == IPWPS_CERDENTIAL_METHOD_DEFAULT)
|
|
rc = ipwps_credentials_default_set(ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_auto_new
|
|
*===========================================================================
|
|
* Description: Auto-generate a new credential set.
|
|
* The AP credentials, and if applicable 1st built-in registrar credential set,
|
|
* are overwritten.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_auto_new(Ipwps_ctx* ctx) {
|
|
Ipwps_credential_set cred;
|
|
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG0(DEBUG2, "ipwps_credentials_auto_new :: called.");
|
|
#endif
|
|
ip_assert(ctx);
|
|
|
|
if (ctx->public.coop_info.cred_method != IPWPS_CERDENTIAL_METHOD_AUTO) {
|
|
IPCOM_LOG2(ERR, "Auto-generating new credentials is only supported for \"%s\" method (current method = \"%s\").",
|
|
IPWPS_CRED_CONFIG_METHOD_AUTO, ctx->public.coop_info.credentials_config_method);
|
|
return IPCOM_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* Auto gen new credentials for cred */
|
|
if (ipwps_credentials_generate_new(ctx, &cred) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_interact_add :: Failed to geherate new Credentials");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
cred.valid = IP_TRUE;
|
|
|
|
if (ipwps_credentials_add_set(ctx, IPWPS_CREDENTIAL_AP_SETID, &cred) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_auto_new :: Failed to add new AP credential set");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return ipwps_credentials_duplicate_builtin_reg(ctx);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_default_set
|
|
*===========================================================================
|
|
* Description: Add the default AP credential set.
|
|
* The AP credentials, and if applicable 1st built-in registrar credential set,
|
|
* are overwritten.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_default_set(Ipwps_ctx* ctx) {
|
|
Ipwps_credential_set cred;
|
|
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG0(DEBUG2, "ipwps_credentials_default_set :: called.");
|
|
#endif
|
|
ip_assert(ctx);
|
|
|
|
if (ctx->public.coop_info.cred_method != IPWPS_CERDENTIAL_METHOD_DEFAULT) {
|
|
IPCOM_LOG2(ERR, "Resetting default credentials is only supported for \"%s\" method (current method = \"%s\").",
|
|
IPWPS_CRED_CONFIG_METHOD_DEFAULT, ctx->public.coop_info.credentials_config_method);
|
|
return IPCOM_ERR_NOT_SUPPORTED;
|
|
}
|
|
/* Verify syvars and copy values into cred */
|
|
if (ipwps_credentials_default_retrieve(ctx, &cred) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_interact_add :: Failed to set default Credentials");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
cred.valid = IP_TRUE;
|
|
|
|
if (ipwps_credentials_add_set(ctx, IPWPS_CREDENTIAL_AP_SETID, &cred) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_default_set :: Failed to add new AP credential set");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return ipwps_credentials_duplicate_builtin_reg(ctx);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_interact_add
|
|
*===========================================================================
|
|
* Description: Add the specified interactive credential set.
|
|
* If the specified credential set already exists and is valid, this call
|
|
* will fail.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_interact_add(Ipwps_ctx* ctx, Ip_u16 setid) {
|
|
Ipwps_credential_set cred;
|
|
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(DEBUG2, "ipwps_credentials_interact_add :: called (setid = %d).", setid);
|
|
#endif
|
|
ip_assert(ctx);
|
|
|
|
if (setid > IPWPS_NUM_CEDENTIALS_MAX) {
|
|
IPCOM_LOG2(ERR, "ipwps_credentials_interact_add :: setid = %d exceeds maximum %d",
|
|
setid, IPWPS_NUM_CEDENTIALS_MAX);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
if (ctx->public.coop_info.cred_method != IPWPS_CERDENTIAL_METHOD_INTERACTIVE) {
|
|
IPCOM_LOG2(ERR, "Adding credentials is only supported for \"%s\" method (current method = \"%s\").",
|
|
IPWPS_CRED_CONFIG_METHOD_INTERACT, ctx->public.coop_info.credentials_config_method);
|
|
return IPCOM_ERR_NOT_SUPPORTED;
|
|
}
|
|
if (ipwps_credentials_get_cred_ptr(ctx, setid)->valid) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_interact_add :: credential set #%d already exists. Please delete before adding.",
|
|
setid);
|
|
return IPCOM_ERR_ALREADY_INSTALLED;
|
|
}
|
|
|
|
/* Verify sysvars and copy values into cred */
|
|
if (ipwps_credentials_interact_retrieve(ctx, &cred) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_interact_add :: Failed to add Credentials for setid = %d",
|
|
setid);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
cred.valid = IP_TRUE;
|
|
|
|
if (ipwps_credentials_add_set(ctx, setid, &cred) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_interact_add :: Failed to add credential set %d", setid);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
if (setid == IPWPS_CREDENTIAL_AP_SETID) {
|
|
ipwps_credentials_duplicate_builtin_reg(ctx);
|
|
}
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_delete
|
|
*===========================================================================
|
|
* Description: Delete the specified credential set.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_delete(Ipwps_ctx* ctx, Ip_u16 setid) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(DEBUG2, "ipwps_credentials_delete :: called (setid = %d).", setid);
|
|
#endif
|
|
ip_assert(ctx);
|
|
|
|
if (setid > IPWPS_NUM_CEDENTIALS_MAX) {
|
|
IPCOM_LOG2(ERR, "ipwps_credentials_delete :: setid = %d exceeds maximum %d",
|
|
setid, IPWPS_NUM_CEDENTIALS_MAX);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
ipwps_credentials_remove_set(ctx, setid);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
*
|
|
*===========================================================================
|
|
* Description: Create a duplicate of the AP credentials into the 1st registrar
|
|
* credential set if built-in registrar is available, otherwise do nothing.
|
|
* This will overwrite the existing set in case of a built-in registrar.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_duplicate_builtin_reg(Ipwps_ctx* ctx) {
|
|
|
|
if ((ctx->public.coop_info.wps_role != IPWPS_ROLE_AP_WITH_BUILTIN_REGISTRAR)
|
|
#ifdef IPWPS_DEBUG
|
|
&& (ctx->public.coop_info.wps_role != IPWPS_ROLE_TESTAPP)
|
|
#endif
|
|
)
|
|
return IPCOM_SUCCESS;
|
|
|
|
return ipwps_credentials_duplicate_set(ctx, IPWPS_CREDENTIAL_BULTIN_REG_SETID, IPWPS_CREDENTIAL_AP_SETID);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_get_cred_ptr
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipwps_credential_set *ipwps_credentials_get_cred_ptr(Ipwps_ctx* ctx, Ip_u16 setid) {
|
|
Ipwps_credential_set *cred = IP_NULL;
|
|
|
|
ip_assert(ctx);
|
|
ip_assert(setid <= IPWPS_NUM_CEDENTIALS_MAX);
|
|
|
|
if (setid == IPWPS_CREDENTIAL_AP_SETID) {
|
|
cred = &ctx->credentials.ap_credentials;
|
|
} else {
|
|
cred = &ctx->credentials.registrar_credentials[setid-1];
|
|
}
|
|
return cred;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_notify_register
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_credentials_notify_register(Ipwps_ctx* ctx, Ipwps_credentials_notify_fn notify_fn) {
|
|
int i;
|
|
|
|
ip_assert(ctx);
|
|
|
|
for (i=0; i < IPWPS_MAX_CREDENTIAL_NOTIFY_FNS; i++) {
|
|
if (ctx->credential_notify_fn[i] == IP_NULL) {
|
|
ctx->credential_notify_fn[i] = (void *)notify_fn;
|
|
break;
|
|
}
|
|
}
|
|
if (i == IPWPS_MAX_CREDENTIAL_NOTIFY_FNS) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_notify_register :: Failed to add notify_fn 0x%x", notify_fn);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_notify_deregister
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_credentials_notify_deregister(Ipwps_ctx* ctx, Ipwps_credentials_notify_fn notify_fn) {
|
|
int i;
|
|
|
|
ip_assert(ctx);
|
|
|
|
for (i=0; i < IPWPS_MAX_CREDENTIAL_NOTIFY_FNS; i++) {
|
|
if (ctx->credential_notify_fn[i] == notify_fn) {
|
|
ctx->credential_notify_fn[i] = IP_NULL;
|
|
break;
|
|
}
|
|
}
|
|
if (i == IPWPS_MAX_CREDENTIAL_NOTIFY_FNS) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_notify_deregister :: Failed to find notify_fn 0x%x", notify_fn);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_notify
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void ipwps_credentials_notify(Ipwps_ctx* ctx, Ip_u16 setid, Ipwps_credential_notify_type ntype) {
|
|
int i;
|
|
|
|
ip_assert(ctx);
|
|
|
|
for (i=0; i < IPWPS_MAX_CREDENTIAL_NOTIFY_FNS; i++) {
|
|
Ipwps_credentials_notify_fn notify_fn = (Ipwps_credentials_notify_fn)ctx->credential_notify_fn[i];
|
|
if (notify_fn)
|
|
notify_fn(ctx, setid, ntype);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_mark_registrar_cred
|
|
*===========================================================================
|
|
* Description: Set/reset the "donotoffer" flag for the specified ap/registrar
|
|
* credential
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipwps_credentials_mark_registrar_cred(Ipwps_ctx* ctx, Ip_u16 cred_set, Ip_bool donotoffer) {
|
|
Ipwps_credential_set *cred;
|
|
|
|
ip_assert(ctx);
|
|
|
|
if (cred_set >= IPWPS_NUM_CEDENTIALS_MAX)
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
|
|
cred = ipwps_credentials_get_cred_ptr(ctx, cred_set+1);
|
|
if (!cred) {
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
cred->donotoffer = donotoffer;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_unmark_all_registrar_creds
|
|
*===========================================================================
|
|
* Description: Reset the "donotoffer" flag for all ap/registrar credentials
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipwps_credentials_unmark_all_registrar_creds(Ipwps_ctx* ctx) {
|
|
int set_id;
|
|
for (set_id = 0; set_id <IPWPS_NUM_CEDENTIALS_MAX ; set_id++) {
|
|
Ipwps_credential_set *cred = ipwps_credentials_get_cred_ptr(ctx, set_id+1);
|
|
if (cred)
|
|
cred->donotoffer = IP_FALSE;
|
|
}
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_add_set
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_credentials_add_set(Ipwps_ctx* ctx, Ip_u16 setid, Ipwps_credential_set *from_cred) {
|
|
Ipwps_credential_set *to_cred;
|
|
|
|
ip_assert(ctx);
|
|
ip_assert(setid <= IPWPS_NUM_CEDENTIALS_MAX);
|
|
ip_assert(from_cred);
|
|
|
|
if (!from_cred->valid) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_add_set :: Invalid credential to add to setid %d", setid);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
to_cred = ipwps_credentials_get_cred_ptr(ctx, setid);
|
|
ip_assert(to_cred);
|
|
|
|
/* Remove before re-adding */
|
|
if (to_cred->valid)
|
|
ipwps_credentials_remove_set(ctx, setid);
|
|
|
|
if (setid == IPWPS_CREDENTIAL_AP_SETID) {
|
|
ctx->credentials.ap_creds = IP_TRUE;
|
|
} else {
|
|
ctx->credentials.num_registrar_creds++;
|
|
ip_assert(ctx->credentials.num_registrar_creds <= IPWPS_NUM_CEDENTIALS_MAX);
|
|
}
|
|
ipcom_memcpy(to_cred, from_cred, sizeof(Ipwps_credential_set));
|
|
to_cred->valid = IP_TRUE; /* redundant */
|
|
|
|
/* Notify any registered apps */
|
|
ipwps_credentials_notify(ctx, setid, IPWPS_CREDENTIAL_ADD);
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_remove_set
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void ipwps_credentials_remove_set(Ipwps_ctx* ctx, Ip_u16 setid) {
|
|
Ipwps_credential_set *cred;
|
|
|
|
ip_assert(ctx);
|
|
ip_assert(setid <= IPWPS_NUM_CEDENTIALS_MAX);
|
|
|
|
cred = ipwps_credentials_get_cred_ptr(ctx, setid);
|
|
ip_assert(cred);
|
|
|
|
if (setid == IPWPS_CREDENTIAL_AP_SETID) {
|
|
ctx->credentials.ap_creds = IP_FALSE;
|
|
} else {
|
|
if (!cred->valid)
|
|
return;
|
|
ip_assert(ctx->credentials.num_registrar_creds);
|
|
ctx->credentials.num_registrar_creds--;
|
|
}
|
|
ipcom_memset(cred, 0, sizeof(Ipwps_credential_set));
|
|
|
|
/* Notify any registered apps */
|
|
ipwps_credentials_notify(ctx, setid, IPWPS_CREDENTIAL_DELETE);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_duplicate_set
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_duplicate_set(Ipwps_ctx* ctx, Ip_u16 to_setid, Ip_u16 from_setid) {
|
|
Ipwps_credential_set *from_cred;
|
|
|
|
ip_assert(ctx);
|
|
|
|
from_cred = ipwps_credentials_get_cred_ptr(ctx, from_setid);
|
|
ip_assert(from_cred);
|
|
if (!from_cred->valid) {
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_duplicate_set :: Invalid credential set %d", from_setid);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return ipwps_credentials_add_set(ctx, to_setid, from_cred);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_generate_new
|
|
*===========================================================================
|
|
* Description: Generate a new credential set based on strongest capability
|
|
* (as retrieved from the driver) and randomly provide a passphrase/PSK
|
|
* and SSID if one is not set.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_generate_new(Ipwps_ctx* ctx, Ipwps_credential_set *cred) {
|
|
char *sysvar;
|
|
Ip_size_t len;
|
|
Ip_u16 auth_cap, encr_cap;
|
|
Ip_u32 netidx;
|
|
|
|
ip_assert(ctx);
|
|
ip_assert(cred);
|
|
|
|
ipcom_memset(cred, 0 , sizeof(Ipwps_credential_set));
|
|
|
|
sysvar = IPWPS_SYSVAR_CREDENTIAL_AUTO_NETINDEX;
|
|
netidx = ipcom_sysvar_get_as_int(sysvar, IPWPS_NETINDEX_DEFAULT);
|
|
if ((netidx < IPWPS_NETINDEX_MIN) || (netidx > IPWPS_NETINDEX_MAX)) {
|
|
cred->network_idx = IPWPS_NETINDEX_DEFAULT;
|
|
} else {
|
|
cred->network_idx = netidx;
|
|
}
|
|
|
|
sysvar = IPWPS_SYSVAR_CREDENTIAL_AUTO_SSID;
|
|
len = sizeof(cred->ssid);
|
|
if (ipcom_sysvar_get(sysvar, cred->ssid, &len)) {
|
|
if (ipwps_credentials_verify_allascii(cred->ssid) != IPCOM_SUCCESS) {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_generate_new :: Invalid auto SSID value");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
if (ipcom_strlen(cred->ssid) == 0) {
|
|
/* Auto-gen an SSID */
|
|
ipcom_memset(cred->ssid, 0, sizeof(cred->ssid));
|
|
ipwps_credentials_gen_random_ascii(cred->ssid, IPWPS_SSID_MAXLEN);
|
|
}
|
|
|
|
auth_cap = ctx->public.cap_info.auth_types;
|
|
encr_cap = ctx->public.cap_info.encr_types;
|
|
|
|
/* Always choose the highest supported capability */
|
|
if (auth_cap & IPWPS_AUTH_TYPE_WPA2PSK) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPA2PSK;
|
|
} else if (auth_cap & IPWPS_AUTH_TYPE_WPAPSK) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPAPSK;
|
|
} else if (auth_cap & IPWPS_AUTH_TYPE_OPEN) {
|
|
return IPCOM_SUCCESS; /* We can only support open mode in this case, so we are done */
|
|
} else {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_generate_new :: Authentication capabilities donnot allow auto credential support");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
if (encr_cap & IPWPS_ENCRYPT_TYPE_AES) {
|
|
cred->encr_type = IPWPS_ENCRYPT_TYPE_AES;
|
|
} else if (encr_cap & IPWPS_ENCRYPT_TYPE_TKIP) {
|
|
cred->encr_type = IPWPS_ENCRYPT_TYPE_TKIP;
|
|
} else {
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_generate_new :: Encryption capabilities donnot allow auto credential support");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
sysvar = IPWPS_SYSVAR_CREDENTIAL_AUTO_KEYLEN;
|
|
cred->netkey_size = ipcom_sysvar_get_as_int(sysvar, IPWPS_PROTO_NETWORK_KEY_MAXLEN);
|
|
if ((cred->netkey_size >= IPWPS_PASSPHRASE_MINLEN) && (cred->netkey_size < IPWPS_PROTO_NETWORK_KEY_MAXLEN)) {
|
|
/* Auto-gen a random Passphrase */
|
|
ipcom_memset(cred->netkey, 0, sizeof(cred->netkey));
|
|
ipwps_credentials_gen_random_ascii((char *)cred->netkey, cred->netkey_size);
|
|
} else {
|
|
/* Auto-gen random PSK */
|
|
cred->netkey_size = IPWPS_PROTO_NETWORK_KEY_MAXLEN; /* This is to fix invalid sizes */
|
|
if (ipwps_credentials_gen_random_hex((char *)cred->netkey, cred->netkey_size)!= IPCOM_SUCCESS){
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_generate_new :: Failed to gen random hex key");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
cred->netkey_idx = IPWPS_KEYINDEX_DEFAULT;
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_default_retrieve
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_default_retrieve(Ipwps_ctx* ctx, Ipwps_credential_set *cred) {
|
|
Ipwps_credential_sysvar_list syslist = {
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_NETINDEX,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_SSID,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_AUTH,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_ENCR,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_KEYINDEX,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_KEY,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_8021X,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_EAP_ID,
|
|
IPWPS_SYSVAR_CREDENTIAL_DEF_EAP_TYPE
|
|
};
|
|
|
|
return ipwps_credentials_retrieve_from_sysvars(cred, &syslist);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_interact_retrieve
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_interact_retrieve(Ipwps_ctx* ctx, Ipwps_credential_set *cred) {
|
|
Ipwps_credential_sysvar_list syslist = {
|
|
IPWPS_SYSVAR_CREDENTIAL_NETINDEX,
|
|
IPWPS_SYSVAR_CREDENTIAL_SSID,
|
|
IPWPS_SYSVAR_CREDENTIAL_AUTH,
|
|
IPWPS_SYSVAR_CREDENTIAL_ENCR,
|
|
IPWPS_SYSVAR_CREDENTIAL_KEYINDEX,
|
|
IPWPS_SYSVAR_CREDENTIAL_KEY,
|
|
IPWPS_SYSVAR_CREDENTIAL_8021X,
|
|
IPWPS_SYSVAR_CREDENTIAL_EAP_ID,
|
|
IPWPS_SYSVAR_CREDENTIAL_EAP_TYPE
|
|
};
|
|
|
|
return ipwps_credentials_retrieve_from_sysvars(cred, &syslist);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_interact_retrieve
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_retrieve_from_sysvars(Ipwps_credential_set *cred, Ipwps_credential_sysvar_list *syslist) {
|
|
char *sysvar;
|
|
Ip_size_t len;
|
|
char keyval[IPWPS_PROTO_NETWORK_KEY_MAXLEN+1];
|
|
char authval[32];
|
|
char encrval[32];
|
|
|
|
ip_assert(cred);
|
|
ip_assert(syslist);
|
|
|
|
ipcom_memset(cred, 0 , sizeof(Ipwps_credential_set));
|
|
|
|
cred->network_idx = ipcom_sysvar_get_as_int(syslist->sysvar_netidx, IPWPS_NETINDEX_DEFAULT);
|
|
|
|
sysvar = syslist->sysvar_ssid;
|
|
len = sizeof(cred->ssid);
|
|
if (!ipcom_sysvar_get(sysvar, cred->ssid, &len)) {
|
|
IPCOM_LOG1(ERR, "Failed to get %s sysvar", sysvar);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
if (ipwps_credentials_verify_allascii(cred->ssid) != IPCOM_SUCCESS) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_interact_retrieve :: ssid value not all ascii");
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
sysvar = syslist->sysvar_auth;
|
|
len = sizeof(authval);
|
|
if (!ipcom_sysvar_get(sysvar, authval, &len)) {
|
|
IPCOM_LOG1(ERR, "Failed to get %s sysvar", sysvar);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_OPEN) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_OPEN;
|
|
cred->encr_type = IPWPS_ENCRYPT_TYPE_NONE;
|
|
/* We're done, all other sysvars are redundant */
|
|
return IPCOM_SUCCESS;
|
|
} else if ((ipcom_strcmp(authval, IPWPS_CRED_AUTH_WPA) != 0) && (ipcom_strcmp(authval, IPWPS_CRED_AUTH_WPA2) != 0)
|
|
&& (ipcom_strcmp(authval, IPWPS_CRED_AUTH_ALL) != 0)) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_interact_retrieve :: Invalid auth value: \"%s\"", authval);
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
sysvar = syslist->sysvar_encr;
|
|
len = sizeof(encrval);
|
|
if (!ipcom_sysvar_get(sysvar, encrval, &len)) {
|
|
IPCOM_LOG1(ERR, "Failed to get %s sysvar", sysvar);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
if (ipcom_strcmp(encrval,IPWPS_CRED_ENCR_TKIP) == 0) {
|
|
cred->encr_type = IPWPS_ENCRYPT_TYPE_TKIP;
|
|
} else if (ipcom_strcmp(encrval, IPWPS_CRED_ENCR_AES) == 0) {
|
|
cred->encr_type = IPWPS_ENCRYPT_TYPE_AES;
|
|
} else if (ipcom_strcmp(encrval,IPWPS_CRED_ENCR_ALL) == 0) {
|
|
cred->encr_type = IPWPS_ENCRYPT_TYPE_TKIP |IPWPS_ENCRYPT_TYPE_AES;
|
|
} else {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_interact_retrieve :: Invalid encr value: \"%s\"", encrval);
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
cred->enabled_8021x = ipcom_sysvar_get_as_int(syslist->sysvar_8021x, 0);
|
|
if (cred->enabled_8021x) {
|
|
sysvar = syslist->sysvar_eapid;
|
|
len = sizeof(cred->eap_id);
|
|
if (!ipcom_sysvar_get(sysvar, cred->eap_id, &len)) {
|
|
IPCOM_LOG1(ERR, "Failed to get %s sysvar", sysvar);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
sysvar = syslist->sysvar_eaptype;
|
|
len = 1; /* try simple eap type 1st */
|
|
if (ipwps_parse_hex_sysvar(sysvar, cred->eap_type, len) != IPCOM_SUCCESS) {
|
|
len = sizeof(cred->eap_type); /* must be extended eap type */
|
|
if (ipwps_parse_hex_sysvar(sysvar, cred->eap_type, len) != IPCOM_SUCCESS) {
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
}
|
|
|
|
if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_WPA) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPA;
|
|
} else if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_WPA2) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPA2;
|
|
} else if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_ALL) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPA | IPWPS_AUTH_TYPE_WPA2;
|
|
}
|
|
} else {
|
|
sysvar = syslist->sysvar_netkey;
|
|
len = sizeof(keyval);
|
|
if (!ipcom_sysvar_get(sysvar, keyval, &len)) {
|
|
IPCOM_LOG1(ERR, "Failed to get %s sysvar", sysvar);
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
if (ipwps_credentials_verify_netkey(keyval) != IPCOM_SUCCESS) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(ERR, "%s sysvar contains invalid passphrase or PSK value.", sysvar);
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
cred->netkey_size = strlen(keyval);
|
|
ipcom_memcpy(cred->netkey, keyval, cred->netkey_size);
|
|
cred->netkey_idx = ipcom_sysvar_get_as_int(syslist->sysvar_keyidx, IPWPS_KEYINDEX_DEFAULT);
|
|
if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_WPA) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPAPSK;
|
|
} else if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_WPA2) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPA2PSK;
|
|
} else if (ipcom_strcmp(authval, IPWPS_CRED_AUTH_ALL) == 0) {
|
|
cred->auth_type = IPWPS_AUTH_TYPE_WPAPSK | IPWPS_AUTH_TYPE_WPA2PSK;
|
|
}
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_verify_netkey
|
|
*===========================================================================
|
|
* Description: Verify proper passphrase of PSK length and format.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_verify_netkey(IP_CONST char *netkey) {
|
|
Ip_u16 size;
|
|
|
|
if (!netkey) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_verify_netkey :: NULL netkey");
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
size = strlen(netkey);
|
|
if (size == IPWPS_PROTO_NETWORK_KEY_MAXLEN) {
|
|
if (ipwps_credentials_verify_allhex(netkey) != IPCOM_SUCCESS) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_verify_netkey :: netkey PSK value not all hex: \"%s\"", netkey);
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
} else if ((size >= IPWPS_PASSPHRASE_MINLEN) && (size < IPWPS_PROTO_NETWORK_KEY_MAXLEN)) {
|
|
if (ipwps_credentials_verify_allascii(netkey) != IPCOM_SUCCESS) {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG0(ERR, "ipwps_credentials_verify_netkey :: netkey passphrase value not all ascii");
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
} else {
|
|
#ifdef IPWPS_DEBUG_CEREDENTIALS
|
|
IPCOM_LOG1(ERR, "ipwps_credentials_verify_netkey :: Invalid netkey length %d", size);
|
|
#endif
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_verify_allhex
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_verify_allhex(IP_CONST char *string) {
|
|
Ip_u16 size, i;
|
|
ip_assert(string);
|
|
|
|
size = strlen(string);
|
|
for (i = 0; i < size; i++) {
|
|
if (!ipcom_isxdigit(string[i]))
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_verify_allascii
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err ipwps_credentials_verify_allascii(IP_CONST char *string) {
|
|
Ip_u16 size, i;
|
|
ip_assert(string);
|
|
|
|
size = strlen(string);
|
|
for (i = 0; i < size; i++) {
|
|
if (!ipcom_isascii(string[i]))
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_random_ascii
|
|
*===========================================================================
|
|
* Description: Generate a specified number of random printable ascii characters.
|
|
* NOTE that the buffer will not be NULL terminated by this routine. It is
|
|
* the callers responsibility to do so.
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_credentials_gen_random_ascii(char *buf, Ip_u16 size) {
|
|
IP_CONST char first_printable_ascii = 0x20, last_printable_ascii = 0x7E;
|
|
Ip_u32 num_printable_ascii = last_printable_ascii - first_printable_ascii +1;
|
|
Ip_u32 i, j, randval, printable_ascii_randval;
|
|
char *tempbuf;
|
|
Ip_bool acceptable;
|
|
char excluded_chars[] = {'\'', '\"', '`', '\'', '\\'}; /* Exclude chars that cause problem in shell data entry */
|
|
#ifdef IPWPS_CRED_TEST_RANDOM_ASCII_RANGE
|
|
char seq_char = last_printable_ascii;
|
|
#endif
|
|
|
|
ip_assert(buf);
|
|
tempbuf = ipcom_calloc(1, size+1);
|
|
if (!tempbuf)
|
|
return IPCOM_ERR_FAILED;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
acceptable = IP_FALSE;
|
|
while (!acceptable) {
|
|
#ifdef IPWPS_CRED_TEST_RANDOM_ASCII_RANGE
|
|
printable_ascii_randval = seq_char--;
|
|
if (seq_char < first_printable_ascii)
|
|
seq_char = last_printable_ascii;
|
|
#else
|
|
randval = ipcom_rand();
|
|
printable_ascii_randval = last_printable_ascii - (randval%num_printable_ascii);
|
|
#endif
|
|
acceptable = IP_TRUE;
|
|
for (j = 0; j < sizeof(excluded_chars); j ++) {
|
|
if (printable_ascii_randval == excluded_chars[j]) {
|
|
acceptable = IP_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
/* Avoid space as the last char as that is confusing */
|
|
if ((i == (size-1)) && (printable_ascii_randval == ' '))
|
|
acceptable = IP_FALSE;
|
|
}
|
|
|
|
ipcom_sprintf(&tempbuf[i], "%c", printable_ascii_randval);
|
|
}
|
|
ipcom_memcpy(buf, tempbuf, size);
|
|
ipcom_free(tempbuf);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_gen_random_hex
|
|
*===========================================================================
|
|
* Description: Generate a specified number of random hex characters.
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_credentials_gen_random_hex(char *buf, Ip_u16 size) {
|
|
Ip_u16 i, max = (size/8)*8+8+1;
|
|
char *tempbuf;
|
|
Ip_u32 randval;
|
|
|
|
ip_assert(buf);
|
|
|
|
tempbuf = ipcom_calloc(1, max);
|
|
if (!tempbuf)
|
|
return IPCOM_ERR_FAILED;
|
|
|
|
i = 0;
|
|
while (i < size) {
|
|
randval = ipcom_rand();
|
|
ipcom_sprintf(&tempbuf[i], "%.8x", randval);
|
|
i+=8;
|
|
}
|
|
ipcom_memcpy(buf, tempbuf, size);
|
|
ipcom_free(tempbuf);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
#ifdef IPWPS_DEBUG
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_test_rand_hex
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_GLOBAL void ipwps_credentials_test_rand_hex(void) {
|
|
char buf[64];
|
|
int size,j;
|
|
for (size = 1; size <= sizeof(buf); size++) {
|
|
ipcom_printf("buf[%d]: ", size);
|
|
ipcom_memset(buf, 0, sizeof(buf));
|
|
ipwps_credentials_gen_random_hex(buf, size);
|
|
for (j = 0; j < size; j++)
|
|
ipcom_printf("%c", buf[j]);
|
|
ipcom_printf("\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_test_rand_ascii
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_GLOBAL void ipwps_credentials_test_rand_ascii(void) {
|
|
char buf[128];
|
|
int size;
|
|
/* leave at least 1 byte for the NULL char */
|
|
for (size = 1; size < sizeof(buf); size++) {
|
|
ipcom_memset(buf, 0, sizeof(buf));
|
|
ipwps_credentials_gen_random_ascii(buf, size);
|
|
ipcom_printf("buf[%d]: %s\n", size, buf);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_credentials_method_name
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_STATIC IP_CONST char *ipwps_credentials_method_name(Ipwps_credential_method cred_method) {
|
|
IP_CONST char *name = "INVALID";
|
|
switch (cred_method) {
|
|
case IPWPS_CERDENTIAL_METHOD_AUTO:
|
|
name = IPWPS_CRED_CONFIG_METHOD_AUTO;
|
|
break;
|
|
case IPWPS_CERDENTIAL_METHOD_DEFAULT:
|
|
name = IPWPS_CRED_CONFIG_METHOD_DEFAULT;
|
|
break;
|
|
case IPWPS_CERDENTIAL_METHOD_INTERACTIVE:
|
|
name = IPWPS_CRED_CONFIG_METHOD_INTERACT;
|
|
break;
|
|
case IPWPS_CERDENTIAL_METHOD_NOTSET:
|
|
name = "NOT SET";
|
|
break;
|
|
}
|
|
return name;
|
|
}
|