Files
m241Neelima/components/ip_net2-6.9/ipcom/src/ipcom_auth.c
T
2026-07-30 11:19:44 +05:30

764 lines
22 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipcom_auth.c,v $ $Revision: 1.41.10.4 $
* $Source: /home/interpeak/CVSRoot/ipcom/src/ipcom_auth.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Lennart Bang <lob@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "ipcom_config.h"
#ifdef IP_PORT_OSE5
#include "sysparam.h"
#endif
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include "ipcom_clib.h"
#include "ipcom_auth.h"
#include "ipcom_err.h"
#include "ipcom_list.h"
#include "ipcom_syslog.h"
#include "ipcom_os.h"
#include "ipcom_shell.h"
#ifdef IPMCRYPTO
#include <ip/openssl/sha.h>
#include <ip/openssl/encode.h>
#define IPCOM_AUTH_USE_HASH
#endif
#ifdef IPCRYPTO
#include "ipcrypto_config.h"
#include <openssl/sha.h>
#include <openssl/evp.h>
#define IPCOM_AUTH_USE_HASH
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_PRIORITY IPCOM_SYSLOG_IPCOM_PRIORITY
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPCOM
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipcom_auth_user
*===========================================================================
*/
typedef struct Ipcom_auth_user_struct
{
Ipcom_list list;
char* username;
char* password;
Ip_uid_t userid;
Ip_bool pwdhash; /* Cleartext or hashed password */
char salt[IPCOM_AUTH_SALT_LENGTH_MAX];
int salt_len;
}
Ipcom_auth_user;
/*
*===========================================================================
* Global ipcom_auth data
*===========================================================================
* Internal global Ipcom_auth data.
*/
typedef struct Ipcom_auth_data_struct
{
Ipcom_mutex mutex;
Ipcom_list users_head;
}
Ipcom_auth_data;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
IP_PUBLIC int ipcom_cmd_user(int argc, char **argv);
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err ipcom_auth_init(void *unused);
IP_PUBLIC Ip_err ipcom_auth_old_and_unsecure_hash_rtn(const char *password,
const char *salt,
Ip_size_t salt_len,
char *buf);
#ifdef IPCOM_AUTH_USE_HASH
IP_STATIC Ip_err (*ipcom_auth_hash_rtn)(const char *password,
const char *salt,
Ip_size_t salt_len,
char *buf) = IP_NULL;
#endif
IP_STATIC Ip_err ipcom_auth_userid_get(Ip_uid_t *userid);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
*===========================================================================
* Global ipcom_auth data
*===========================================================================
*/
IP_STATIC Ipcom_auth_data ipcom_auth;
IP_STATIC Ipcom_once_t ipcom_auth_once = IPCOM_ONCE_INIT;
#ifdef IPCOM_AUTH_USE_HASH
IP_STATIC Ip_err ipcom_auth_decode(const Ip_u8* in, int inl,
Ip_u8* out, int* outl);
#endif
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_auth_userid_get
*===========================================================================
* Description: Get next available userid
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err ipcom_auth_userid_get(Ip_uid_t *userid)
{
Ipcom_auth_user *user;
Ip_uid_t userid_tmp;
Ip_err err = IPCOM_SUCCESS;
Ip_bool flag;
/* Find next available userid */
for (userid_tmp = 0; (userid_tmp < ipcom_auth.users_head.size) &&
(userid_tmp < (Ip_uid_t)(~0)); userid_tmp++)
{
flag = IP_FALSE;
for (user = IPCOM_LIST_FIRST(&ipcom_auth.users_head); user;
user = IPCOM_LIST_NEXT(&user->list))
{
if(userid_tmp == user->userid)
{
flag = IP_TRUE; /* Userid is in use */
break;
}
}
if (flag == IP_FALSE)
break; /* Userid is not in use */
}
*userid = userid_tmp;
if (*userid == (Ip_uid_t)(~0))
err = IPCOM_ERR_FAILED;
return err;
}
#ifdef IPCOM_AUTH_USE_HASH
/*
*===========================================================================
* ipcom_auth_decode
*===========================================================================
* Description: Decode base64 encoded string
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err ipcom_auth_decode(const Ip_u8* in, int inl,
Ip_u8* out, int* outl)
{
EVP_ENCODE_CTX ctx;
int i, outl_tmp = 0;
EVP_DecodeInit(&ctx);
i = EVP_DecodeUpdate(&ctx, out, outl, in, inl);
outl_tmp = *outl + outl_tmp;
if (i < 0)
return IPCOM_ERR_FAILED;
i = EVP_DecodeFinal(&ctx, out + outl_tmp, outl);
if (i < 0)
return IPCOM_ERR_FAILED;
outl_tmp = *outl + outl_tmp;
*outl = outl_tmp;
return IPCOM_SUCCESS;
}
#endif /* IPCOM_AUTH_USE_HASH */
/*
*===========================================================================
* ipcom_auth_init
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipcom_auth_init(void *unused)
{
Ip_err retval;
(void)unused;
ipcom_memset(&ipcom_auth, 0, sizeof(Ipcom_auth_data));
ipcom_list_init(&ipcom_auth.users_head);
retval = ipcom_mutex_create(&ipcom_auth.mutex);
ip_assert(retval == IPCOM_SUCCESS);
if (retval != IPCOM_SUCCESS)
return retval;
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_auth_useradd
*===========================================================================
* Description: Add IPCOM user with a cleartext password.
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_useradd(const char *username, const char *password, Ip_uid_t userid)
{
/* Cleartext password */
return ipcom_auth_useradd_hash(username, password, userid, IP_FALSE, "");
}
/*
*===========================================================================
* ipcom_auth_useradd_hash
*===========================================================================
* Description: Add IPCOM user with a hashed or cleartext password
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_useradd_hash(const char *username,
const char *password,
Ip_uid_t userid,
Ip_bool hash,
const char *salt)
{
Ipcom_auth_user *user = IP_NULL;
Ip_err err;
#ifdef IPCOM_AUTH_USE_HASH
Ip_u8 hash_buf[IPCOM_AUTH_PASSWORD_MAX];
int salt_len;
#else
IPCOM_UNUSED_ARG(salt);
#endif
err = ipcom_once(&ipcom_auth_once, ipcom_auth_init, IP_NULL);
if (err != IPCOM_SUCCESS)
return err;
if (!username || ipcom_strlen(username) >= IPCOM_AUTH_USERNAME_MAX
|| !password || ipcom_strlen(password) >= IPCOM_AUTH_PASSWORD_MAX)
return IPCOM_ERR_INVALID_ARG;
ipcom_mutex_lock(ipcom_auth.mutex);
/* Get a userid if not provided */
if (userid == (Ip_uid_t) (~0u))
{
if ((err = ipcom_auth_userid_get(&userid)) != IPCOM_SUCCESS)
goto leave;
}
/* Check for duplicate. */
for (user = IPCOM_LIST_FIRST(&ipcom_auth.users_head); user; user = IPCOM_LIST_NEXT(&user->list))
if (ipcom_strcmp(username, user->username) == 0
|| user->userid == userid)
{
err = IPCOM_ERR_DUPLICATE;
user = IP_NULL;
goto leave;
}
/* Create new user. */
user = ipcom_calloc(1, sizeof(Ipcom_auth_user));
if (user == IP_NULL)
{
err = IPCOM_ERR_NO_MEMORY;
goto leave;
}
/* Init user. */
user->pwdhash = hash; /* Hashed or cleartext */
user->userid = userid;
user->username = ipcom_strdup(username);
user->password = ipcom_strdup(password);
if (user->username == IP_NULL || user->password == IP_NULL)
{
err = IPCOM_ERR_NO_MEMORY;
goto leave;
}
if (hash == IP_TRUE)
{
#ifdef IPCOM_AUTH_USE_HASH
/* Decode the SALT */
if (salt)
{
if ((ipcom_auth_decode((Ip_u8*)salt, (int)ipcom_strlen(salt),
hash_buf, &salt_len) != IPCOM_SUCCESS) || (salt_len > IPCOM_AUTH_SALT_LENGTH_MAX))
{
err = IPCOM_ERR_FAILED;
goto leave;
}
ipcom_memcpy(user->salt, hash_buf, salt_len);
user->salt_len = salt_len;
}
#else
err = IPCOM_ERR_NOT_SUPPORTED;
goto leave;
#endif /* IPCOM_AUTH_USE_HASH */
}
ipcom_list_insert_last(&ipcom_auth.users_head, &user->list);
leave:
if (err != IPCOM_SUCCESS)
{
if (user)
{
if (user->username)
ipcom_free(user->username);
if (user->password)
ipcom_free(user->password);
ipcom_free(user);
}
}
ipcom_mutex_unlock(ipcom_auth.mutex);
return err; /*lint !e429 Custodial pointer 'user' has not been freed or returned */
}
/*
*===========================================================================
* ipcom_auth_userdel
*===========================================================================
* Description: Delete IPCOM user.
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_userdel(const char *username)
{
Ipcom_auth_user *user;
Ip_err err;
err = ipcom_once(&ipcom_auth_once, ipcom_auth_init, IP_NULL);
if (err != IPCOM_SUCCESS)
return err;
ip_assert(username);
ipcom_mutex_lock(ipcom_auth.mutex);
/* Find user */
for (user = IPCOM_LIST_FIRST(&ipcom_auth.users_head); user; user = IPCOM_LIST_NEXT(&user->list))
if (ipcom_strcmp(username, user->username) == 0)
break;
if (user == IP_NULL)
{
err = IPCOM_ERR_NOT_FOUND;
goto leave;
}
ipcom_free(user->username);
ipcom_free(user->password);
/* Remove and free user. */
ipcom_list_remove(&user->list);
ipcom_free(user);
leave:
ipcom_mutex_unlock(ipcom_auth.mutex);
return err;
}
/*
*===========================================================================
* ipcom_auth_userget
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_userget(const char *username, Ipcom_auth_userinfo *userinfo)
{
Ipcom_auth_user *user;
Ip_err err;
err = ipcom_once(&ipcom_auth_once, ipcom_auth_init, IP_NULL);
if (err != IPCOM_SUCCESS)
return err;
ip_assert(username);
ipcom_mutex_lock(ipcom_auth.mutex);
#ifdef IP_PORT_OSE5
{
char user[IPCOM_AUTH_USERNAME_MAX];
char password[IPCOM_AUTH_PASSWORD_MAX];
if (sysparam_readattr_string("login", "username", user, sizeof(user)) == 0
&& sysparam_readattr_string("login", "password", password, sizeof(password)) == 0
&& ipcom_strcmp(user, username) == 0)
{
if (userinfo)
{
ipcom_memset(userinfo, 0, sizeof(Ipcom_auth_userinfo));
ipcom_strcpy(userinfo->username, username);
ipcom_strcpy(userinfo->password, password);
userinfo->pwdhash = IP_FALSE;/* Cleartext */
}
goto leave;
}
}
#endif /* IP_PORT_OSE5 */
/* Find user */
for (user = IPCOM_LIST_FIRST(&ipcom_auth.users_head); user; user = IPCOM_LIST_NEXT(&user->list))
if (ipcom_strcmp(username, user->username) == 0)
break;
if (user == IP_NULL)
{
err = IPCOM_ERR_NOT_FOUND;
goto leave;
}
/* Copy over info. */
if (userinfo)
{
ipcom_memset(userinfo, 0, sizeof(Ipcom_auth_userinfo));
ipcom_strncpy(userinfo->username, user->username, IPCOM_AUTH_USERNAME_MAX - 1);
if(user->pwdhash == IP_TRUE)
{
ipcom_strncpy(userinfo->password, user->password, IPCOM_AUTH_PASSWORD_MAX - 1);
ipcom_memcpy(userinfo->salt, user->salt, user->salt_len);
userinfo->salt_len = user->salt_len;
}
else
ipcom_strncpy(userinfo->password, user->password, IPCOM_AUTH_PASSWORD_MAX - 1);
userinfo->userid = user->userid;
userinfo->pwdhash = user->pwdhash;
}
leave:
ipcom_mutex_unlock(ipcom_auth.mutex);
return err;
}
/*
*===========================================================================
* ipcom_auth_userlist
*===========================================================================
* Description: List users
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_userlist(Ip_uid_t *userid, Ipcom_auth_userinfo *userinfo)
{
Ipcom_auth_user *user;
Ip_err err;
if (userid == IP_NULL)
return IPCOM_ERR_INVALID_ARG;
if (userinfo)
ipcom_memset(userinfo, 0, sizeof(Ipcom_auth_userinfo));
err = ipcom_once(&ipcom_auth_once, ipcom_auth_init, IP_NULL);
if (err != IPCOM_SUCCESS)
return IP_NULL;
ipcom_mutex_lock(ipcom_auth.mutex);
/* Find user */
for (user = IPCOM_LIST_FIRST(&ipcom_auth.users_head); user; user = IPCOM_LIST_NEXT(&user->list))
if (*userid == user->userid)
break;
/* No user found, return first user's userid. */
if (user == IP_NULL)
{
user = IPCOM_LIST_FIRST(&ipcom_auth.users_head);
*userid = user ? user->userid : ~0u;
err = IPCOM_ERR_NOT_FOUND;
goto leave;
}
/* Copy over userinfo. */
if (userinfo)
{
ipcom_strncpy(userinfo->username, user->username, sizeof(userinfo->username));
ipcom_strncpy(userinfo->password, user->password, sizeof(userinfo->password));
ip_assert(userinfo->username[sizeof(userinfo->username)-1] == 0);
ip_assert(userinfo->password[sizeof(userinfo->password)-1] == 0);
userinfo->userid = user->userid;
userinfo->pwdhash = user->pwdhash;
}
/* Next user's userid. */
user = IPCOM_LIST_NEXT(&user->list);
*userid = user ? user->userid : ~0u;
leave:
ipcom_mutex_unlock(ipcom_auth.mutex);
return err;
}
#ifdef IPCOM_AUTH_USE_HASH
/*
*===========================================================================
* ipcom_auth_hash_rtn_install
*===========================================================================
* Description: Install hash routine
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err ipcom_auth_hash_rtn_install(Ipcom_auth_hash_hook hash_rtn,
Ip_size_t digest)
{
Ip_err err = IPCOM_SUCCESS;
IPCOM_UNUSED_ARG(digest);
err = ipcom_once(&ipcom_auth_once, ipcom_auth_init, IP_NULL);
if (err != IPCOM_SUCCESS)
return err;
ipcom_mutex_lock(ipcom_auth.mutex);
ipcom_auth_hash_rtn = hash_rtn;
ipcom_mutex_unlock(ipcom_auth.mutex);
return err;
}
/*
*===========================================================================
* ipcom_auth_hash
*===========================================================================
* Description: Hash passwords
* Parameters: password - the input unhashed password string
* salt - buffer to pass the salt, IPCOM_AUTH_SALT_LENGTH bytes
* buf - buffer of length IPCOM_AUTH_PASSWORD_MAX in which
* to store the hashed password string
* Returns:
*/
IP_PUBLIC Ip_err ipcom_auth_hash(const char *password, const char *salt, Ip_size_t salt_len, char *buf)
{
if (ipcom_auth_hash_rtn == IP_NULL)
return ipcom_auth_default_hash_rtn(password, salt, salt_len, buf);
else if((*ipcom_auth_hash_rtn) (password, salt, salt_len, buf) != IPCOM_SUCCESS)
return (IPCOM_ERR_FAILED);
return (IPCOM_SUCCESS);
}
/*
*===========================================================================
* ipcom_auth_default_hash_rtn
*===========================================================================
* Description: Default hash routine
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err ipcom_auth_default_hash_rtn(const char *password, const char *salt, Ip_size_t salt_len, char *buf)
{
char buf1[IPCOM_AUTH_PASSWORD_MAX];
EVP_ENCODE_CTX ctx;
int outl;
int i;
unsigned char* unsigned_buf = (unsigned char*)buf;
/* Store salt + password in buffer */
if (salt_len > IPCOM_AUTH_SALT_LENGTH_MAX || (salt_len+ipcom_strlen(password)+1 > IPCOM_AUTH_PASSWORD_MAX-1))
return IPCOM_ERR_INVALID_ARG;
ipcom_memcpy(buf1, salt, salt_len);
ipcom_strcpy(&buf1[salt_len], password);
/* Hash buffer */
SHA256((unsigned char*)buf1, salt_len+ipcom_strlen(password), unsigned_buf);
/* Base64 encode hash */
EVP_EncodeInit(&ctx);
EVP_EncodeUpdate(&ctx, unsigned_buf, &outl, unsigned_buf, 32);
EVP_EncodeFinal(&ctx, unsigned_buf+outl, &outl);
/* Remove terminating line feed */
for (i=(int)(ipcom_strlen((char*)unsigned_buf)-1); i>0 && unsigned_buf[i]=='\n';i--)
unsigned_buf[i] = 0;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipcom_auth_hash_get
*===========================================================================
* Description: Obsolete function. Only kept in order to simplify the upgrade
* process. loginLib.c has a dependency to this function and we
* do not want to make changes that require an update to
* loginLib.c
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_hash_get(Ip_size_t *digest)
{
*digest = SHA256_DIGEST_LENGTH;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipcom_auth_old_and_unsecure_hash_rtn
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipcom_auth_old_and_unsecure_hash_rtn(const char *password, const char *salt, Ip_size_t salt_len, char *buf)
{
int ix;
Ip_u32 magic = 31695317;
Ip_u32 passwdInt = 0;
IPCOM_UNUSED_ARG(salt);
IPCOM_UNUSED_ARG(salt_len);
if (ipcom_strlen(password) < 8 || ipcom_strlen(password) > 40)
{
return (IPCOM_ERR_FAILED);
}
for (ix = 0; ix < ipcom_strlen(password); ix++) /* Sum the string */
passwdInt += (password[ix]) * (ix+1) ^ (ix+1);
ipcom_sprintf (buf, "%u", (long) (passwdInt * magic)); /* Convert integer to string */
/* Make encrypted passwd printable */
for (ix = 0; ix < ipcom_strlen (buf); ix++)
{
if (buf[ix] < '3')
buf[ix] = (char)(buf[ix] + '!'); /* Arbitrary */
if (buf[ix] < '7')
buf[ix] = (char)(buf[ix] + '/'); /* Arbitrary */
if (buf[ix] < '9')
buf[ix] = (char)(buf[ix] + 'B'); /* Arbitrary */
}
return (IPCOM_SUCCESS);
}
#endif /* IPCOM_AUTH_USE_HASH */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/