2023-06-12 10:49:35 +08:00
# include <stdint.h>
# include <stdlib.h>
2023-06-26 18:05:38 +08:00
# include <sys/mman.h>
# include <fcntl.h>
# include <errno.h>
# include <string.h>
2023-06-12 10:49:35 +08:00
# include <unistd.h>
# include <pthread.h>
# include "hasp_api.h"
# include "hasp_vcode.h"
2023-06-20 21:49:58 +08:00
# include "hasp_log.h"
2023-06-12 10:49:35 +08:00
2023-06-20 21:49:58 +08:00
# define DEFAULT_INTERVAL_S (30 * 60)
# define MAX_INTERVAL_S (24 * 60 * 60)
2023-06-12 10:49:35 +08:00
2023-06-26 18:05:38 +08:00
# ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
# endif
# define ATOMIC_READ(x) __atomic_fetch_add(x, 0, __ATOMIC_RELAXED)
# define ATOMIC_SET(x, y) __atomic_store_n(x, y, __ATOMIC_RELAXED)
2023-06-20 21:49:58 +08:00
static char * shm_key = " hasp_verify " ;
2023-06-12 10:49:35 +08:00
2023-06-26 18:05:38 +08:00
static uint64_t hasp_monitor_feature_id = 0 ;
static uint64_t hasp_monitor_interval = 0 ;
struct shm_data
{
uint64_t feature_id ;
uint64_t status ;
uint64_t timestamp ;
uint64_t interval ;
} ;
2023-06-12 10:49:35 +08:00
2023-06-20 21:49:58 +08:00
/******************************************************************************
* Utils
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-06-12 10:49:35 +08:00
2023-06-20 21:49:58 +08:00
static uint64_t current_timestamp ( )
2023-06-12 10:49:35 +08:00
{
2023-06-20 21:49:58 +08:00
struct timespec temp ;
clock_gettime ( CLOCK_MONOTONIC , & temp ) ;
return temp . tv_sec ;
2023-06-12 10:49:35 +08:00
}
2023-06-26 18:05:38 +08:00
/******************************************************************************
* For Hasp Verify Master Process
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-06-12 10:49:35 +08:00
// return 0: error
// reutrn 1: succes
static int verify ( uint64_t feature_id )
{
int ret = 0 ;
hasp_handle_t handle ;
hasp_status_t status = hasp_login ( feature_id , ( hasp_vendor_code_t ) vendor_code , & handle ) ;
if ( status = = HASP_STATUS_OK )
{
ret = 1 ;
}
else
{
switch ( status )
{
case HASP_STATUS_OK :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Request was successfully completed " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_HASP_NOT_FOUND :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Required Sentinel protection key not found " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_FEATURE_NOT_FOUND :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Cannot find requested Feature " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_FEATURE_TYPE_NOT_IMPL :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Requested Feature type not available " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_TMOF :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Too many open login sessions " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_INSUF_MEM :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Out of memory " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_INV_VCODE :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Invalid Vendor Code " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_NO_DRIVER :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Driver not installed " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_NO_VLIB :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Vendor library cannot be found " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_INV_VLIB :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Vendor library cannot be loaded " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_OLD_DRIVER :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Driver too old " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_UNKNOWN_VCODE :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Vendor Code not recognized " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_FEATURE_EXPIRED :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Feature has expired " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_TOO_MANY_USERS :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Too many users currently connected " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_OLD_LM :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Sentinel License Manager version too old " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_DEVICE_ERR :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Input/Output error in Sentinel SL/SL-AdminMode/SL-UserMode secure storage, OR in case of a Sentinel HL key, USB communication error " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_TIME_ERR :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: System time has been tampered with " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_HARDWARE_MODIFIED :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Sentinel SL key incompatible with machine hardware; Sentinel SL key is locked to different hardware " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_TS_DETECTED :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Program is running on a Terminal Server " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_LOCAL_COMM_ERR :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Communication error between API and local Sentinel License Manager " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_REMOTE_COMM_ERR :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Communication error between local and remote Sentinel License Manager " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_OLD_VLIB :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Vendor Library version too old " ) ;
2023-06-12 10:49:35 +08:00
break ;
case HASP_CLONE_DETECTED :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Cloned Sentinel SL storage detected. Feature unavailable " ) ;
2023-06-12 10:49:35 +08:00
break ;
default :
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: failed with status %u " , status ) ;
2023-06-12 10:49:35 +08:00
break ;
}
ret = 0 ;
}
hasp_logout ( handle ) ;
return ret ;
}
2023-06-26 18:05:38 +08:00
static int hasp_monitor_write ( struct shm_data * data )
2023-06-20 21:49:58 +08:00
{
2023-06-26 18:05:38 +08:00
char path [ 256 ] ;
char path_old [ 512 ] ;
char path_new [ 512 ] ;
2023-06-20 21:49:58 +08:00
2023-06-26 18:05:38 +08:00
int size = sizeof ( struct shm_data ) ;
int fd = shm_open ( shm_key , O_RDWR , 0777 ) ;
if ( fd < 0 )
{
LOG_INFO ( " hasp_monitor: Could not find shared file '%s', try create it " , shm_key ) ;
2023-06-20 21:49:58 +08:00
2023-06-26 18:05:38 +08:00
sprintf ( path , " %s.%d " , shm_key , getpid ( ) ) ;
fd = shm_open ( path , O_CREAT | O_RDWR , 0777 ) ;
if ( fd < 0 )
{
LOG_INFO ( " hasp_monitor: Could not create shared file '%s', error %d: %s " , shm_key , errno , strerror ( errno ) ) ;
return - 1 ;
}
2023-06-20 21:49:58 +08:00
2023-06-26 18:05:38 +08:00
if ( ftruncate ( fd , size ) < 0 )
{
LOG_INFO ( " hasp_monitor: Could not truncate shared file '%s', error %d: %s " , path , errno , strerror ( errno ) ) ;
shm_unlink ( path ) ;
return - 1 ;
}
void * addr = mmap ( NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , SEEK_SET ) ;
if ( addr = = NULL )
{
LOG_INFO ( " hasp_monitor: Could not mmap shared file '%s', error %d: %s " , path , errno , strerror ( errno ) ) ;
shm_unlink ( path ) ;
return - 1 ;
}
memset ( addr , 0 , size ) ;
munmap ( addr , size ) ;
sprintf ( path_old , " /dev/shm/%s " , path ) ;
sprintf ( path_new , " /dev/shm/%s " , shm_key ) ;
int r = link ( path_old , path_new ) ;
if ( r = = - 1 )
{
LOG_INFO ( " hasp_monitor: Create link('%s', '%s'), error %d: %s " , path_old , path_new , errno , strerror ( errno ) ) ;
}
else
{
LOG_INFO ( " hasp_monitor: Create link('%s', '%s') success " , path_old , path_new ) ;
}
unlink ( path_old ) ;
fd = shm_open ( shm_key , O_RDWR , 0777 ) ;
if ( fd < 0 )
{
LOG_INFO ( " hasp_monitor: Could not open shared file '%s', error %d: %s " , shm_key , errno , strerror ( errno ) ) ;
return - 1 ;
}
}
else
{
LOG_INFO ( " hasp_monitor: Open shared file '%s' success " , shm_key ) ;
}
struct shm_data * shm = ( struct shm_data * ) mmap ( NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , SEEK_SET ) ;
if ( shm = = NULL )
{
LOG_INFO ( " hasp_monitor: Could not mmap shared file '%s', error %d: %s " , shm_key , errno , strerror ( errno ) ) ;
shm_unlink ( shm_key ) ;
return - 1 ;
}
ATOMIC_SET ( & shm - > feature_id , data - > feature_id ) ;
ATOMIC_SET ( & shm - > status , data - > status ) ;
ATOMIC_SET ( & shm - > timestamp , data - > timestamp ) ;
ATOMIC_SET ( & shm - > interval , data - > interval ) ;
/*
* MAP_SHARED
*
* Share this mapping .
* Updates to the mapping are visible to other processes that map this file , and are carried through to the underlying file .
* The file may not actually be updated until msync ( 2 ) or munmap ( ) is called .
*/
munmap ( shm , sizeof ( struct shm_data ) ) ;
/*
* Unlink the shared memory object .
* Even if the peer process is still using the object , this is okay .
* The object will be removed only after all open references are closed .
*/
// shm_unlink(shm_key);
return 0 ;
}
static void * hasp_monitor_cycle ( void * arg )
2023-06-12 10:49:35 +08:00
{
2023-06-26 18:05:38 +08:00
struct shm_data data ;
if ( hasp_monitor_interval > = MAX_INTERVAL_S )
2023-06-20 21:49:58 +08:00
{
2023-06-26 18:05:38 +08:00
hasp_monitor_interval = MAX_INTERVAL_S ;
2023-06-20 21:49:58 +08:00
}
2023-06-12 10:49:35 +08:00
2023-06-26 18:05:38 +08:00
if ( hasp_monitor_interval = = 0 )
2023-06-12 10:49:35 +08:00
{
2023-06-26 18:05:38 +08:00
hasp_monitor_interval = DEFAULT_INTERVAL_S ;
2023-06-12 10:49:35 +08:00
}
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_monitor: Feature ID: %ld, Interval: %ld s " , hasp_monitor_feature_id , hasp_monitor_interval ) ;
2023-06-20 21:49:58 +08:00
2023-06-12 10:49:35 +08:00
while ( 1 )
{
2023-06-26 18:05:38 +08:00
if ( verify ( hasp_monitor_feature_id ) = = 1 )
2023-06-12 10:49:35 +08:00
{
2023-06-26 18:05:38 +08:00
memset ( & data , 0 , sizeof ( data ) ) ;
data . feature_id = hasp_monitor_feature_id ;
data . status = 1 ;
data . timestamp = current_timestamp ( ) ;
data . interval = hasp_monitor_interval ;
if ( hasp_monitor_write ( & data ) = = - 1 )
{
return NULL ;
}
LOG_INFO ( " hasp_monitor: Set feature_id: %ld, timestamp: %ld, interval: %ld, status: %ld " , data . feature_id , data . timestamp , data . interval , data . status ) ;
2023-06-12 10:49:35 +08:00
}
2023-06-20 21:49:58 +08:00
2023-06-26 18:05:38 +08:00
sleep ( hasp_monitor_interval ) ;
2023-06-12 10:49:35 +08:00
}
2023-06-26 18:05:38 +08:00
return NULL ;
}
void hasp_monitor ( uint64_t feature_id , uint64_t interval )
{
pthread_t tid ;
hasp_monitor_feature_id = feature_id ;
hasp_monitor_interval = interval ;
if ( pthread_create ( & tid , NULL , hasp_monitor_cycle , NULL ) < 0 )
{
LOG_INFO ( " hasp_monitor: Could not create hasp monitor thread, error %d: %s " , errno , strerror ( errno ) ) ;
exit ( 0 ) ;
}
pthread_join ( tid , NULL ) ;
2023-06-12 10:49:35 +08:00
}
2023-06-20 21:49:58 +08:00
/******************************************************************************
* For Hasp Verify Slave Process
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-06-26 18:05:38 +08:00
static int hasp_verify_read ( struct shm_data * data )
2023-06-12 10:49:35 +08:00
{
2023-06-26 18:05:38 +08:00
memset ( data , 0 , sizeof ( struct shm_data ) ) ;
int fd = shm_open ( shm_key , O_RDONLY , 0644 ) ;
if ( fd < 0 )
{
LOG_INFO ( " hasp_verify: Could not open shared file '%s', error %d: %s " , shm_key , errno , strerror ( errno ) ) ;
return - 1 ;
}
int size = sizeof ( struct shm_data ) ;
struct shm_data * addr = ( struct shm_data * ) mmap ( NULL , size , PROT_READ , MAP_SHARED , fd , SEEK_SET ) ;
if ( addr = = NULL )
{
LOG_INFO ( " hasp_verify: Could not mmap shared file '%s', error %d: %s " , shm_key , errno , strerror ( errno ) ) ;
shm_unlink ( shm_key ) ;
return - 1 ;
}
data - > feature_id = addr - > feature_id ;
data - > status = addr - > status ;
data - > timestamp = addr - > timestamp ;
data - > interval = addr - > interval ;
/*
* MAP_SHARED
*
* Share this mapping .
* Updates to the mapping are visible to other processes that map this file , and are carried through to the underlying file .
* The file may not actually be updated until msync ( 2 ) or munmap ( ) is called .
*/
munmap ( addr , size ) ;
2023-06-12 10:49:35 +08:00
2023-06-26 18:05:38 +08:00
/*
* Unlink the shared memory object .
* Even if the peer process is still using the object , this is okay .
* The object will be removed only after all open references are closed .
*/
// shm_unlink(shm_key);
return 0 ;
}
static void * hasp_verify_cycle ( void * arg )
{
struct shm_data data ;
uint64_t expect_feature_id = * ( uint64_t * ) arg ;
LOG_INFO ( " hasp_verify: Expect Feature ID: %ld " , expect_feature_id ) ;
2023-06-20 21:49:58 +08:00
while ( 1 )
2023-06-12 10:49:35 +08:00
{
2023-06-26 18:05:38 +08:00
if ( hasp_verify_read ( & data ) = = - 1 )
2023-06-20 21:49:58 +08:00
{
LOG_INFO ( " hasp_verify: Could not get shared data " ) ;
exit ( 0 ) ;
}
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_verify: Get feature_id: %ld, timestamp: %ld, interval: %ld, status: %ld " , data . feature_id , data . timestamp , data . interval , data . status ) ;
2023-06-20 21:49:58 +08:00
2023-06-26 18:05:38 +08:00
if ( expect_feature_id ! = data . feature_id )
2023-06-20 21:49:58 +08:00
{
LOG_INFO ( " hasp_verify: Unexpected feature id " ) ;
exit ( 0 ) ;
}
2023-06-26 18:05:38 +08:00
if ( current_timestamp ( ) - data . timestamp > data . interval * 2 )
2023-06-20 21:49:58 +08:00
{
LOG_INFO ( " hasp_verify: Timestamp not updated for a long time " ) ;
exit ( 0 ) ;
}
2023-06-26 18:05:38 +08:00
if ( data . status = = 0 )
2023-06-20 21:49:58 +08:00
{
LOG_INFO ( " hasp_verify: Invalid authorization information " ) ;
exit ( 0 ) ;
}
sleep ( 1 ) ;
2023-06-12 10:49:35 +08:00
}
2023-06-26 18:05:38 +08:00
free ( arg ) ;
arg = NULL ;
2023-06-20 21:49:58 +08:00
return NULL ;
}
2023-06-12 10:49:35 +08:00
2023-06-20 21:49:58 +08:00
void hasp_verify ( uint64_t feature_id )
{
pthread_t tid ;
2023-06-26 18:05:38 +08:00
uint64_t * hasp_verify_feature_id = ( uint64_t * ) calloc ( 1 , sizeof ( uint64_t ) ) ;
* hasp_verify_feature_id = feature_id ;
if ( pthread_create ( & tid , NULL , hasp_verify_cycle , hasp_verify_feature_id ) < 0 )
2023-06-12 10:49:35 +08:00
{
2023-06-26 18:05:38 +08:00
LOG_INFO ( " hasp_verify: Could not create hasp verify thread, error %d: %s " , errno , strerror ( errno ) ) ;
2023-06-12 10:49:35 +08:00
exit ( 0 ) ;
}
}