393 lines
11 KiB
C
393 lines
11 KiB
C
/*
|
|
************************************************************************
|
|
**
|
|
** Copyright (c) 2010..2012 by
|
|
** Core|Vision B.V.
|
|
** Cereslaan 10b
|
|
** 5384 VT Heesch
|
|
** The Netherlands
|
|
**
|
|
** All Rights Reserved
|
|
**
|
|
************************************************************************
|
|
*/
|
|
/*
|
|
************************************************************************
|
|
**
|
|
** Project name: Dual Inventive: Server for MTinfo Secure
|
|
** Filename: secureserver.h
|
|
** Author: Jack Weeland
|
|
** Date: February 17, 2010
|
|
** File version: $Revision: 1.14 $
|
|
** $Date: 2014/02/05 10:45:20 $
|
|
**
|
|
************************************************************************
|
|
*/
|
|
/*
|
|
************************************************************************
|
|
**
|
|
** Secure Server
|
|
** Definitions
|
|
**
|
|
************************************************************************
|
|
*/
|
|
|
|
#ifndef _SECURESERVER_H
|
|
#define _SECURESERVER_H
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
|
|
#include <di-util/cp3000.h>
|
|
#include <di-util/cp3000-sign.h>
|
|
#include <di-util/cp3000-sem.h>
|
|
#include <di-util/cp3000-i18n.h>
|
|
#include <di-util/database.h>
|
|
#include <di-util/list.h>
|
|
#include <di-util/util.h>
|
|
|
|
/*
|
|
** Error and status bits (currently only used to give a reason for a disconnect)
|
|
*/
|
|
#define TCP_NO_ERROR 0
|
|
#define TCP_ERROR 1
|
|
#define TCP_DISCONNECTED 2
|
|
#define TCP_TIMEOUT 3
|
|
#define TCP_ABORTED 4
|
|
#define TCP_KILLED 5
|
|
#define TCP_PROTOCOL 6 // protocol violation
|
|
|
|
// device flags
|
|
#define ZKL_ACTIVE 0x0001
|
|
#define ZKL_CAN_SWITCH 0x0002
|
|
#define ZKL_IS_RS3000 0x1000 // currently without meaning
|
|
|
|
// flags to signal a prototol violation or not (boolean flag for
|
|
// 'signal_protocol_violation()'
|
|
#define VIOLATION 0
|
|
#define USER_ERROR 1
|
|
#define DEVICE_ERROR 2
|
|
#define USER_LOCKED 3
|
|
#define INTERNAL_ERROR 4
|
|
#define SERVER_ERROR 5
|
|
|
|
/*
|
|
** Type definitions
|
|
*/
|
|
|
|
// database identifiers for a ZKL, user and project
|
|
typedef unsigned int zkl_t;
|
|
typedef unsigned int user_t;
|
|
typedef unsigned int project_t;
|
|
|
|
// reason why a new work instruction is offered
|
|
typedef enum WI_REASON
|
|
{
|
|
R_INVALID = -1,
|
|
R_NEW = 0,
|
|
R_O_CONCEPT, R_O_READY, R_O_VERIFY, R_O_VALIDATE,
|
|
R_P_CONCEPT, R_P_READY, R_P_VERIFY, R_P_VALIDATE,
|
|
R_S_RELEASE, R_S_WITHDRAW,
|
|
R_S_CHECK,
|
|
R_S_REQ_ON, R_S_ON,
|
|
R_S_REQ_OFF, R_S_OFF,
|
|
R_ALARM,
|
|
R_S_VERIFY,
|
|
R_SECURE, // pseudo reason, the reason below don't work on a work instruction
|
|
R_LED_HIGH, R_LED_LOW,
|
|
R_EXT_ON, R_EXT_OFF,
|
|
R_LANT_ON, R_LANT_OFF,
|
|
R_RELAY_ON, R_RELAY_OFF,
|
|
R_GPS_TRACKTRACE,
|
|
R_RESET_SECUREHANDSHAKE,
|
|
R_CHECK_CONNECTION,
|
|
R_DELETE
|
|
} reason_t;
|
|
|
|
// states
|
|
typedef enum WI_STATE
|
|
{
|
|
S_INVALID = -1,
|
|
S_CONCEPT = 0,
|
|
S_READY,
|
|
S_VERIFY,
|
|
S_VALIDATE,
|
|
S_WITHDRAW,
|
|
S_RELEASE,
|
|
S_REQ_ON, S_ON,
|
|
S_REQ_OFF, S_OFF
|
|
} state_t;
|
|
|
|
// verification methods
|
|
typedef enum WI_VERIFICATION
|
|
{
|
|
VER_INVALID = -1,
|
|
VER_SMS = 0,
|
|
VER_PIN,
|
|
VER_RS3000
|
|
} verification_t;
|
|
|
|
// methods to send an alarm message
|
|
typedef enum WI_ALARM
|
|
{
|
|
ALARM_INVALID = -1,
|
|
ALARM_SMS = 0,
|
|
ALARM_EMAIL
|
|
} alarm_t;
|
|
|
|
// work instructions and supporting classes
|
|
struct WI_DEVICE
|
|
{
|
|
zkl_t id; // identifier for the device
|
|
unsigned int flags; // ZKL_xxx flags
|
|
int status; // status after running a command
|
|
char imei[16]; // IMEI of the device
|
|
char serial[32]; // serial number
|
|
char idcode[32]; // ID-code of the device
|
|
unsigned char rs3000_verification[DIGITAL_SIGNATURE_BITS >> 3];
|
|
char server[PATH_MAX]; // IP-address and port of the TCP-server for this device
|
|
gps_position_t gps; // GPS position after communication with the device and when applicable
|
|
};
|
|
|
|
struct WI_USER
|
|
{
|
|
user_t id; // identifier for the user
|
|
char user_name[32]; // user name
|
|
|
|
char i18n[16]; // translation for the SMS messages
|
|
char tz[64]; // time zone to format the time correctly
|
|
|
|
// user verification
|
|
verification_t method; // method of verification
|
|
unsigned char verification[DIGITAL_SIGNATURE_BITS >> 3];
|
|
char phonenr[16]; // phone number for SMS verification
|
|
};
|
|
|
|
struct WI_NOTIFY
|
|
{
|
|
alarm_t method; // e-mail or SMS
|
|
char da[PATH_MAX]; // e-mail address or phone number
|
|
};
|
|
|
|
// work instruction; user data for the master cp3000_device_t object
|
|
typedef struct WI_HEADER
|
|
{
|
|
project_t id; // identifier for the project/period
|
|
char name[64]; // project name
|
|
user_t mtinfo_user; // user in MTinfo who sent the request
|
|
reason_t reason; // reason for this communication
|
|
state_t req_state; // requested state
|
|
int status; // status code to return to the client
|
|
|
|
// devices and users associated with the request
|
|
int n_devices;
|
|
int n_users;
|
|
lst_t devices;
|
|
lst_t users;
|
|
|
|
// used with a request to switch a device
|
|
user_t user; // actor
|
|
verification_t method; // SMS, PIN or RS3000
|
|
time_t expiration; // expiration time for device check _or_
|
|
// SMS verification code (mutually exclusive)
|
|
unsigned char verification[DIGITAL_SIGNATURE_BITS >> 3];
|
|
|
|
// digital signature
|
|
unsigned char signature[DIGITAL_SIGNATURE_BITS >> 3];
|
|
|
|
// TCP-server for logging
|
|
cp3000_device_t log_server;
|
|
unsigned int log_session;
|
|
|
|
// database handle
|
|
db_t db;
|
|
// tokens for the hash (signature)
|
|
lst_t hash_tokens;
|
|
|
|
// semaphore to protect against simultaneous access to the same work instruction
|
|
cp3000_sem_t semaphore;
|
|
} *wi_t;
|
|
|
|
/*
|
|
** Exported functions
|
|
*/
|
|
|
|
//
|
|
// implemented in "secureserver.c"
|
|
//
|
|
|
|
// debugging enabled?
|
|
extern int debug;
|
|
|
|
// log server
|
|
extern cp3000_device_t log_server;
|
|
|
|
// get the wi_t object
|
|
wi_t get_wi(cp3000_device_t);
|
|
|
|
// get the db_t object
|
|
db_t get_db(cp3000_device_t);
|
|
|
|
// convert reason string to a reason_t, state_t, verification_t, alarm_t
|
|
reason_t get_reason(const char*);
|
|
state_t get_state(const char*);
|
|
verification_t get_verification_method(const char*);
|
|
alarm_t get_notify_method(const char*);
|
|
|
|
// convert reason_t, state_t, verification_t and alarm_t to string
|
|
// (simple look-up array)
|
|
extern const char *reason_str[];
|
|
extern const char *state_str[];
|
|
extern const char *verification_str[];
|
|
extern const char *notification_str[];
|
|
|
|
// get the base name for the mutex/semaphore
|
|
int get_mutex_name(wi_t wi, char *buffer, size_t bufsz);
|
|
|
|
// set security for a cp3000_device_t object (must be done before a
|
|
// connection is made)
|
|
int set_security(cp3000_device_t);
|
|
|
|
// kill this instance of the secure server (signal handler for SIGTERM,
|
|
// but also called after a protocol violation (with SIGUSR1)
|
|
void tcp_terminate(int);
|
|
|
|
//
|
|
// implemented in "wi.c"
|
|
//
|
|
|
|
// command (sequence) and device time-out in seconds
|
|
extern int command_timeout;
|
|
extern int device_timeout;
|
|
|
|
// user lock-out in seconds and number of allowed attempts
|
|
extern int user_lockout_time;
|
|
extern int user_lockout_tries;
|
|
|
|
// validity of a device check
|
|
extern int device_check_validity;
|
|
|
|
// validity and length of an SMS code
|
|
extern int verification_validity;
|
|
extern int verification_code_len;
|
|
|
|
// get a user or device from the transmitted work instruction
|
|
const struct WI_USER *wi_get_user(wi_t, user_t);
|
|
const struct WI_DEVICE *wi_get_device(wi_t, zkl_t);
|
|
|
|
// delete the work instruction after a security violation
|
|
int wi_delete(cp3000_device_t, wi_t);
|
|
|
|
// main entry: read the request from MTinfo, verify it and execute it
|
|
int handle_request(cp3000_device_t, token_info_t, void*);
|
|
|
|
// close and clean-up an open connection
|
|
int secureserver_shutdown(cp3000_device_t, int reason);
|
|
|
|
//
|
|
// implemented in "notify.c"
|
|
//
|
|
|
|
// fixed list (from configuration) of e-mail addresses for protocol violations
|
|
extern char notify_list[];
|
|
// e-mail "from" address, priority and locale
|
|
extern char notify_from[];
|
|
extern char notify_priority[];
|
|
extern char notify_i18n[];
|
|
extern char notify_tz[];
|
|
// line separator for SMS messages (default " * ")
|
|
extern char sms_separator[];
|
|
|
|
// fatal error (protocol violation)
|
|
// the work instruction is deleted in the case of a protocol violaton,
|
|
// but not in the case of a non-fatal error such as TCPERR_ACCESS
|
|
// sends a notification via e-mail and/or sms
|
|
int signal_protocol_violation(
|
|
cp3000_device_t,
|
|
int is_violation,
|
|
int error_code,
|
|
const char *fmt, ...
|
|
);
|
|
|
|
// send verification code via SMS; the generated code is stored (encoded)
|
|
// in the work instruction (wi_t parameter, field 'verification')
|
|
int send_sms_verification_code(cp3000_device_t, wi_t, user_t);
|
|
|
|
//
|
|
// implemented in "log-server.c"
|
|
//
|
|
|
|
// connect and login with a TCP-server for logging (which is stored
|
|
// in the 'wi_t' user data of the device)
|
|
// note: all log entries are also written to syslog(3)
|
|
int log_start(cp3000_device_t, reason_t, user_t, const char *log_server);
|
|
// record overall status and disconnect from log server
|
|
int log_end(cp3000_device_t, int status, const char *fmt, ...);
|
|
|
|
// log device activity and changes to a user in the work instruction
|
|
// (user activity, i.e. the user as actor, is logged via the main entry)
|
|
int log_device(cp3000_device_t, zkl_t, int status, const char *fmt, ...);
|
|
int log_user(cp3000_device_t, user_t, int status, const char *fmt, ...);
|
|
// intermediate messages, not related to a device or a user
|
|
int log_wi(cp3000_device_t, int status, const char *fmt, ...);
|
|
|
|
//
|
|
// implemented in "database-if.c"
|
|
//
|
|
|
|
// flags for 'db_update_xxx()' (the three stages)
|
|
// NB: non-essential data in the device and user list is always updated
|
|
#define WI_UPDATE_DESIGN 0x0001 // i.e. the switchable device list
|
|
#define WI_UPDATE_PLANNING 0x0002 // i.e. the user list and non-switchable devices
|
|
#define WI_UPDATE_SWITCHSTATE 0 // (placeholder)
|
|
#define WI_UPDATE_DEVICES 0 // device list (TCP server address only)
|
|
#define WI_UPDATE_USERS 0 // user list (i18n, tz, phone number or PIN)
|
|
#define WI_UPDATE (WI_UPDATE_DEVICES | WI_UPDATE_USERS)
|
|
#define WI_UPDATE_USER 0x0100 // the user allowed to switch
|
|
#define WI_UPDATE_VERIFICATION 0x0200 // update verification code sent via SMS
|
|
#define WI_SET_EXPIRATION 0x0400 // expiration time for a check on switchability
|
|
#define WI_REPLACE 0x8000 // replace data instead of updating it, where applicable
|
|
|
|
// verify the signature of the database records
|
|
// returns CP3000 status code
|
|
int db_verify_signature(cp3000_device_t, wi_t);
|
|
|
|
// compare the database data with the data in the work instruction
|
|
// returns CP3000 status code
|
|
int db_verify_wi(cp3000_device_t, wi_t);
|
|
|
|
// get project state (design, planning, switching)
|
|
// returns CP3000 status code
|
|
int db_get_state(cp3000_device_t, wi_t, state_t*, state_t*, state_t*);
|
|
|
|
// verify a user and expiry of the device check
|
|
// returns CP3000 status code
|
|
int db_verify_user(cp3000_device_t, wi_t, user_t, const unsigned char*, size_t);
|
|
int db_check_expiration(cp3000_device_t, wi_t);
|
|
// find a user
|
|
int db_find_user(cp3000_device_t, wi_t, user_t, struct WI_USER*);
|
|
|
|
// add a new work instruction, update an existing one (data and state _separately_)
|
|
// or delete a work instruction.
|
|
// all return CP3000 status code
|
|
int db_insert_wi(cp3000_device_t, wi_t, state_t init_state);
|
|
int db_update_wi(cp3000_device_t, wi_t, unsigned int flags);
|
|
int db_update_state(cp3000_device_t, wi_t, state_t new_state, unsigned int flags);
|
|
int db_update_gps_position(cp3000_device_t, wi_t);
|
|
int db_delete_wi(cp3000_device_t, wi_t);
|
|
|
|
// add a list with notification numbers to the work instruction
|
|
// a possible existing list will be replaced
|
|
// returns CP3000 status code
|
|
int db_insert_notify_list(cp3000_device_t, wi_t);
|
|
// get the list; the lists themselves may be NULL if not interested in
|
|
// one or the other
|
|
// returns CP3000 status code
|
|
int db_get_notify_list(cp3000_device_t, wi_t, lst_t email, lst_t sms);
|
|
|
|
// update the signature over the database data
|
|
int db_update_signature(cp3000_device_t device, wi_t wi);
|
|
|
|
#endif /* _SECURESERVER_H */
|