src.dualinventive.com/mtinfo/secureserver/include/secureserver.h

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 */