Remove non-siahsd sources

These fail to compile and are not required for the space.
This commit is contained in:
polyfloyd 2025-05-08 00:32:16 +02:00
parent 02a670fc49
commit c09d87c6e4
10 changed files with 1 additions and 2168 deletions

View file

@ -1,104 +0,0 @@
Mon Nov 21 20:41:35 2016: ./build/chirond(15512): Log level 0, at ../chirond.c:308 in function handle_message():
chiron message: struct chiron_message
msg_type : CHIRON_ACCOUNT (65)
seq : 0x02 (2)
flags : 0xa8 (168)
msg : union chiron_msg_union(case 65)
account: struct chiron_msg_account
length : 0x04 (4)
account_code: ARRAY(4)
[0] : 0x33 (51)
[1] : 0x35 (53)
[2] : 0x30 (48)
[3] : 0x30 (48)
Mon Nov 21 20:41:35 2016: ./build/chirond(15512): Log level 0, at ../chirond.c:210 in function send_chiron_msg_challenge():
Sending out a challenge
Mon Nov 21 20:41:35 2016: ./build/chirond(15512): Log level 0, at ../chirond.c:278 in function send_chiron_msg_challenge():
The expected md5sum for the next entry is 67305652133a689bb99b3d7e953b30f7
Mon Nov 21 20:41:35 2016: ./build/chirond(15512): Log level 0, at ../chirond.c:308 in function handle_message():
chiron message: struct chiron_message
msg_type : CHIRON_RESPONSE (82)
seq : 0x02 (2)
flags : 0xa8 (168)
msg : union chiron_msg_union(case 82)
response: struct chiron_msg_response
length : 0x46 (70)
md5_check: ARRAY(16)
[0] : 0xc8 (200)
[1] : 0xa8 (168)
[2] : 0xb6 (182)
[3] : 0x50 (80)
[4] : 0x34 (52)
[5] : 0xd5 (213)
[6] : 0x7a (122)
[7] : 0x26 (38)
[8] : 0x90 (144)
[9] : 0x63 (99)
[10] : 0x92 (146)
[11] : 0x56 (86)
[12] : 0xe5 (229)
[13] : 0x4d (77)
[14] : 0xde (222)
[15] : 0xa0 (160)
payload: ARRAY(54)
[0] : 0x6a (106)
[1] : 0x60 (96)
[2] : 0x19 (25)
[3] : 0xdc (220)
[4] : 0x67 (103)
[5] : 0xbb (187)
[6] : 0xe8 (232)
[7] : 0x9e (158)
[8] : 0x8e (142)
[9] : 0xfc (252)
[10] : 0x79 (121)
[11] : 0x55 (85)
[12] : 0xed (237)
[13] : 0x66 (102)
[14] : 0x26 (38)
[15] : 0x21 (33)
[16] : 0x1a (26)
[17] : 0x6b (107)
[18] : 0x4a (74)
[19] : 0x9c (156)
[20] : 0x7c (124)
[21] : 0xe6 (230)
[22] : 0x1d (29)
[23] : 0x01 (1)
[24] : 0xab (171)
[25] : 0x57 (87)
[26] : 0xfb (251)
[27] : 0xd9 (217)
[28] : 0x6d (109)
[29] : 0x15 (21)
[30] : 0xbd (189)
[31] : 0xe6 (230)
[32] : 0xe3 (227)
[33] : 0x94 (148)
[34] : 0xd6 (214)
[35] : 0xe7 (231)
[36] : 0xde (222)
[37] : 0xc3 (195)
[38] : 0x89 (137)
[39] : 0x52 (82)
[40] : 0x65 (101)
[41] : 0x5f (95)
[42] : 0x0c (12)
[43] : 0x97 (151)
[44] : 0x4e (78)
[45] : 0x4f (79)
[46] : 0x6d (109)
[47] : 0x9f (159)
[48] : 0x5a (90)
[49] : 0xb9 (185)
[50] : 0xc2 (194)
[51] : 0x12 (18)
[52] : 0xdd (221)
[53] : 0x74 (116)
Mon Nov 21 20:41:35 2016: ./build/chirond(15512): Log level 0, at ../chirond.c:167 in function handle_chiron_msg_response():
MD5 does not match!
Decrypted outgoing payload:
ZERO LENGTH

View file

@ -1,111 +0,0 @@
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 0, at ../chirond.c:308 in function handle_message():
chiron message: struct chiron_message
msg_type : CHIRON_ACCOUNT (65)
seq : 0x01 (1)
flags : 0xa8 (168)
msg : union chiron_msg_union(case 65)
account: struct chiron_msg_account
length : 0x04 (4)
account_code: ARRAY(4)
[0] : 0x33 (51)
[1] : 0x35 (53)
[2] : 0x30 (48)
[3] : 0x30 (48)
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 0, at ../chirond.c:210 in function send_chiron_msg_challenge():
Sending out a challenge
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 0, at ../chirond.c:278 in function send_chiron_msg_challenge():
The expected md5sum for the next entry is 627fd0b8bc706a21442115b494206298
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 0, at ../chirond.c:308 in function handle_message():
chiron message: struct chiron_message
msg_type : CHIRON_RESPONSE (82)
seq : 0x01 (1)
flags : 0xa8 (168)
msg : union chiron_msg_union(case 82)
response: struct chiron_msg_response
length : 0x37 (55)
md5_check: ARRAY(16)
[0] : 0x62 (98)
[1] : 0x7f (127)
[2] : 0xd0 (208)
[3] : 0xb8 (184)
[4] : 0xbc (188)
[5] : 0x70 (112)
[6] : 0x6a (106)
[7] : 0x44 (68)
[8] : 0x44 (68)
[9] : 0x21 (33)
[10] : 0x15 (21)
[11] : 0xb4 (180)
[12] : 0x94 (148)
[13] : 0x20 (32)
[14] : 0x62 (98)
[15] : 0x98 (152)
payload: ARRAY(39)
[0] : 0x7a (122)
[1] : 0xe2 (226)
[2] : 0xde (222)
[3] : 0xc2 (194)
[4] : 0xed (237)
[5] : 0x76 (118)
[6] : 0x84 (132)
[7] : 0x5f (95)
[8] : 0xe6 (230)
[9] : 0x16 (22)
[10] : 0x2b (43)
[11] : 0x6b (107)
[12] : 0xb9 (185)
[13] : 0x10 (16)
[14] : 0xa3 (163)
[15] : 0x6c (108)
[16] : 0x14 (20)
[17] : 0x44 (68)
[18] : 0x56 (86)
[19] : 0xca (202)
[20] : 0x45 (69)
[21] : 0xc6 (198)
[22] : 0xc2 (194)
[23] : 0xeb (235)
[24] : 0xec (236)
[25] : 0x1b (27)
[26] : 0xd8 (216)
[27] : 0x7a (122)
[28] : 0xa4 (164)
[29] : 0x4c (76)
[30] : 0xc0 (192)
[31] : 0xb4 (180)
[32] : 0x88 (136)
[33] : 0x64 (100)
[34] : 0x6e (110)
[35] : 0x2b (43)
[36] : 0xee (238)
[37] : 0x11 (17)
[38] : 0x54 (84)
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 0, at ../chirond.c:170 in function handle_chiron_msg_response():
Handling the response
Decrypted:
0000 00 ad c7 0c 04 a8 de fe ff 20 01 01 21 01 63 17 ......... ..!.c.
0010 16 49 52 49 53 20 54 6f 75 63 68 20 34 32 30 20 .IRIS Touch 420
0020 76 31 2e 31 34 2e 33 v1.14.3
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 1, at ../chirond.c:192 in function handle_chiron_msg_response():
Type: 12, Length: 4
Data:
0000 a8 de fe ff ....
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 1, at ../chirond.c:192 in function handle_chiron_msg_response():
Type: 32, Length: 1
Data:
0000 01 .
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 1, at ../chirond.c:192 in function handle_chiron_msg_response():
Type: 33, Length: 1
Data:
0000 63 c
Mon Nov 21 20:40:07 2016: ./build/chirond(15477): Log level 1, at ../chirond.c:192 in function handle_chiron_msg_response():
Type: 23, Length: 22
Data:
0000 49 52 49 53 20 54 6f 75 63 68 20 34 32 30 20 76 IRIS Touch 420 v
0010 31 2e 31 34 2e 33 1.14.3
Crypted outgoing payload:
0000 5d 4f 2b ce f1 de 77 a1 ]O+...w.
Decrypted outgoing payload:
0000 27 00 32 00 18 00 2d 00 '.2...-.

View file

@ -1,133 +0,0 @@
interface chiron
{
const int MD5_HASH_LEN = 0x10;
const int CHALLENGE_LEN = 0x9;
const int MSG_HDR_LEN = 0x4;
const int ALTMSG_HDR_LEN = 0x8;
typedef [public,enum8bit] enum {
CHIRON_ACCOUNT = 0x41, /* 'A' */
CHIRON_CHALLENGE = 0x43, /* 'C' */
CHIRON_RESPONSE = 0x52, /* 'R' */
CHIRON_HANDSHAKE1 = 0x4B, /* 'K' */
CHIRON_HANDSHAKE2 = 0x48, /* 'H' = Set new key?? */
CHIRON_ACK = 0x55, /* 'U' */
CHIRON_TRANSPARENT = 0x54, /* 'T' */
CHIRON_SIGNAL = 0x53 /* 'S' */
} chiron_msg_type;
typedef [public,enum8bit] enum {
CHIRON_EL_DEVSTATE = 0x0C,
CHIRON_EL_UNKNOWN_BOOL1 = 0x16,
CHIRON_EL_DEVICEID1 = 0x17,
CHIRON_EL_DEVICEID2 = 0x18,
CHIRON_EL_MODE_ENABLED = 0x20, /* == 0x13 */
CHIRON_EL_GSM_SETTING_G6 = 0x21,
CHIRON_EL_UNKNOWN_BOOL2 = 0x22,
CHIRON_EL_THREEBYTE_STATUS = 0x26,
CHIRON_EL_GSM_SETTING_G3_G19 = 0x27,
CHIRON_EL_UNKNOWN_BYTE1 = 0x2C,
CHIRON_EL_TROUBLE_MESSAGE1 = 0x2D,
CHIRON_EL_TROUBLE_MESSAGE2 = 0x36,
CHIRON_EL_GSM_SETTING_G4 = 0x40
} chiron_element_tag;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 account_code[length];
} chiron_msg_account;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 md5_check[MD5_HASH_LEN];
uint8 challenge[length - 0x10];
} chiron_msg_challenge;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 md5_check[MD5_HASH_LEN];
uint8 payload[length - MD5_HASH_LEN];
} chiron_msg_response;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 data[length];
} chiron_msg_handshake1;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 challenge[length];
} chiron_msg_handshake2;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length; // Always 0
uint8 data[length];
} chiron_msg_ack;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 data[length+6];
} chiron_msg_signal;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 data[length];
} chiron_msg_unknown;
typedef [nodiscriminant,public,flag(LIBNDR_FLAG_NOALIGN)] union {
[case(CHIRON_ACCOUNT)] chiron_msg_account account;
[case(CHIRON_CHALLENGE)] chiron_msg_challenge challenge;
[case(CHIRON_RESPONSE)] chiron_msg_response response;
[case(CHIRON_HANDSHAKE1)] chiron_msg_handshake1 handshake1;
[case(CHIRON_HANDSHAKE2)] chiron_msg_handshake2 handshake2;
[case(CHIRON_ACK)] chiron_msg_ack ack;
[case(CHIRON_SIGNAL)] chiron_msg_signal signal;
[default] chiron_msg_unknown unknown;
} chiron_msg_union;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
chiron_msg_type msg_type;
uint8 seq;
uint8 flags;
[switch_is(msg_type)] chiron_msg_union msg;
} chiron_message;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 length;
uint8 challenge[length];
} chiron_altmsg_challenge;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
chiron_msg_response response;
uint8 floof[3];
} chiron_altmsg_response;
typedef [nodiscriminant,public,flag(LIBNDR_FLAG_NOALIGN)] union {
[case(CHIRON_ACCOUNT)] chiron_msg_account account;
[case(CHIRON_CHALLENGE)] chiron_altmsg_challenge challenge;
[case(CHIRON_RESPONSE)] chiron_altmsg_response response;
[case(CHIRON_HANDSHAKE1)] chiron_msg_handshake1 handshake1;
[case(CHIRON_HANDSHAKE2)] chiron_msg_handshake2 handshake2;
[case(CHIRON_ACK)] chiron_msg_ack ack;
[case(CHIRON_SIGNAL)] chiron_msg_signal signal;
[default] chiron_msg_unknown unknown;
} chiron_altmsg_union;
// Alternative format
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 something01; // seen only 01
uint8 otherthing01; // seen only 01
uint8 seq;
uint8 someflag; // seen 00 and 01, 01 after the response handshake, and message 0x48 'H' is issued.
uint8 something00; //seen only 00
uint8 length;
chiron_msg_type msg_type;
[switch_is(msg_type)] chiron_altmsg_union msg;
} chiron_alt_message;
}

771
chirond.c
View file

@ -1,771 +0,0 @@
/*
Chiron IP Alarm Monitoring Service
Copyright (C) Wilco Baan Hofman <wilco@baanhofman.nl> 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 4 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "build/ndr_chiron.h"
#include "build/chiron.h"
#include <nettle/md5.h>
#include <nettle/arcfour.h>
#define CHIRON_PORT "53165"
// Function was licensed WTFPL, origin stack: overflow
// I am too lazy to write this myself, these days.
void hexdump (const char *desc, const void *addr, const int len) {
int i;
unsigned char buff[17];
unsigned char *pc = (unsigned char*)addr;
// Output description if given.
if (desc != NULL)
fprintf(stderr, "%s:\n", desc);
if (len == 0) {
fprintf(stderr, " ZERO LENGTH\n");
return;
}
if (len < 0) {
fprintf(stderr, " NEGATIVE LENGTH: %i\n",len);
return;
}
for (i = 0; i < len; i++) {
if ((i % 16) == 0) {
if (i != 0)
fprintf(stderr, " %s\n", buff);
fprintf(stderr, " %04x ", i);
}
fprintf(stderr, " %02x", pc[i]);
if ((pc[i] < 0x20) || (pc[i] > 0x7e))
buff[i % 16] = '.';
else
buff[i % 16] = pc[i];
buff[(i % 16) + 1] = '\0';
}
while ((i % 16) != 0) {
fprintf(stderr, " ");
i++;
}
fprintf(stderr, " %s\n", buff);
}
struct chiron_context {
int clientfd;
struct sockaddr *clientaddr;
char *account_code;
char device_id[3];
uint8_t md5_last_out[MD5_HASH_LEN];
uint8_t rc4key[MD5_HASH_LEN];
bool alt_format;
uint8_t seq;
uint8_t flags;
};
/* FIXME This function is a nasty little hack. */
char *ndr_print_chiron_msg_type_enum(TALLOC_CTX *mem_ctx, enum chiron_msg_type msg_type) {
char *ret;
struct ndr_print *ndr_print = talloc_zero(mem_ctx, struct ndr_print);
ndr_print->print = ndr_print_string_helper;
ndr_print->depth = 0;
ndr_print_chiron_msg_type(ndr_print, "", msg_type);
ret = talloc_steal(mem_ctx, ndr_print->private_data);
talloc_free(ndr_print);
return ret;
}
struct ll_tlv {
struct ll_tlv *next;
enum chiron_msg_type type;
uint8_t length;
void *data_ptr;
};
STATUS tlv_to_linked_list(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct ll_tlv **first_element) {
uint8_t *tlvptr = data.data;
struct ll_tlv *prev_elem = NULL;
while (tlvptr + 2 < data.data + data.length) {
struct ll_tlv *element = talloc_zero(mem_ctx, struct ll_tlv);
if (prev_elem == NULL) {
*first_element = element;
} else {
prev_elem->next = element;
}
element->type = *tlvptr++;
element->length = *tlvptr++;
if (tlvptr + element->length > data.data + data.length) {
if (prev_elem != NULL) {
prev_elem->next = NULL;
}
talloc_free(element);
return ST_PARSE_ERROR;
}
element->data_ptr = tlvptr;
tlvptr += element->length;
prev_elem = element;
}
if (tlvptr < data.data + data.length) {
DEBUG(1, "Error: Left over bytes in TLV");
return ST_PARSE_ERROR;
}
return ST_OK;
}
STATUS handle_chiron_msg_ack(struct chiron_context *ctx, struct chiron_msg_ack *ack) {
DEBUG(3, "Received ACK");
return ST_OK;
}
STATUS send_chiron_msg_handshake1(struct chiron_context *ctx, struct chiron_msg_response *response) {
struct chiron_message *out = talloc_zero(response, struct chiron_message);
out->msg_type = CHIRON_HANDSHAKE1;
out->seq = ctx->seq;
out->flags = 0xC0; /* FIXME: What does this do? */
const uint8_t payload[] = { 0x27, 0, 0x32, 0, 0x18, 0, 0x2D, 0 };
out->msg.handshake1.data = talloc_memdup(out, payload, sizeof(payload));
out->msg.handshake1.length = sizeof(payload);
struct arcfour_ctx rc4;
arcfour_set_key(&rc4, MD5_HASH_LEN, ctx->rc4key);
arcfour_crypt(&rc4, sizeof(payload), out->msg.handshake1.data, payload);
hexdump("Crypted outgoing payload", out->msg.handshake1.data, sizeof(payload));
DATA_BLOB raw_out;
enum ndr_err_code ndr_err = ndr_push_struct_blob(&raw_out, out, out, (ndr_push_flags_fn_t)ndr_push_chiron_message);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Error writing NDR data blob.");
return ST_WRITE_ERROR;
}
write(ctx->clientfd, raw_out.data, raw_out.length);
talloc_free(out);
return ST_OK;
}
STATUS send_chiron_altmsg_handshake2(struct chiron_context *ctx, struct chiron_msg_response *response) {
struct chiron_alt_message *alt = talloc_zero(response, struct chiron_alt_message);
DEBUG(0, "Sending out an alt handshake2");
alt = talloc_zero(response, struct chiron_alt_message);
NO_MEM_RETURN(alt);
alt->msg_type = CHIRON_HANDSHAKE2;
alt->seq = ctx->seq;
alt->something01 = 0x01;
alt->otherthing01 = 0x01;
alt->someflag = ctx->flags;
alt->something00 = 0x00;
alt->length = 0x0B;
struct chiron_msg_handshake2 *handshake2 = &alt->msg.handshake2;
//int hdrlen = ALTMSG_HDR_LEN;
handshake2->length = CHALLENGE_LEN;
handshake2->challenge = talloc_zero_array(alt, uint8_t, CHALLENGE_LEN);
NO_MEM_RETURN(handshake2->challenge);
handshake2->challenge[0] = 0x07;
handshake2->challenge[1] = 0x2f;
handshake2->challenge[2] = 0xb9;
handshake2->challenge[3] = 0x81;
handshake2->challenge[4] = 0x3d;
handshake2->challenge[5] = 0x0f;
handshake2->challenge[6] = 0x14;
handshake2->challenge[7] = 0xac;
handshake2->challenge[8] = 0x59;
DATA_BLOB raw_out;
enum ndr_err_code ndr_err = ndr_push_struct_blob(&raw_out, alt, alt, (ndr_push_flags_fn_t)ndr_push_chiron_alt_message);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Error writing NDR data blob.");
return ST_WRITE_ERROR;
}
/* Update the rc4 crypto key, which is seq+challenge */
uint8_t *md5input = talloc_array(response, uint8_t, CHALLENGE_LEN + 1);
NO_MEM_RETURN(md5input);
int count = write(ctx->clientfd, raw_out.data, raw_out.length);
if (count < 0) {
DEBUG(0, "Error during write of %d bytes to fd %d: %s", raw_out.length, ctx->clientfd, strerror(errno));
} else if ((unsigned)count < raw_out.length) {
DEBUG(0, "Short write during writing out the raw_data with length %d", raw_out.length);
}
talloc_free(alt);
return ST_OK;
}
STATUS handle_chiron_msg_response(struct chiron_context *ctx, struct chiron_msg_response *response) {
DATA_BLOB crypted, decrypted;
struct arcfour_ctx rc4;
struct ll_tlv *element;
if (memcmp(response->md5_check, ctx->md5_last_out, 0x10)) {
DEBUG(0, "MD5 does not match!\n");
return ST_PARSE_ERROR;
}
DEBUG(0, "Handling the response");
/* Copy packet to crypted data blob */
crypted.length = response->length - MD5_HASH_LEN;
if (crypted.length > 0) {
crypted.data = talloc_memdup(response, response->payload, crypted.length);
NO_MEM_RETURN(crypted.data);
decrypted.data = talloc_array(response, uint8_t, crypted.length);
NO_MEM_RETURN(decrypted.data);
decrypted.length = crypted.length;
arcfour_set_key(&rc4, MD5_HASH_LEN, ctx->rc4key);
arcfour_crypt(&rc4, crypted.length, decrypted.data, crypted.data);
hexdump("Decrypted", decrypted.data, decrypted.length);
/* The message starts with 3 bytes device_id, and then the TLV starts */
memcpy(ctx->device_id, decrypted.data, 3);
decrypted.data += 3;
decrypted.length -= 3;
tlv_to_linked_list(response, decrypted, &element);
while (element != NULL) {
DEBUG(1, "Type: %x, Length: %d", element->type, element->length);
hexdump("Data", element->data_ptr, element->length);
element = element->next;
}
send_chiron_msg_handshake1(ctx, response);
} else {
send_chiron_altmsg_handshake2(ctx, response);
}
return ST_OK;
}
STATUS send_chiron_altmsg_challenge(struct chiron_context *ctx, struct chiron_msg_account *account) {
struct chiron_alt_message *alt;
struct md5_ctx md5;
uint8_t *md5input;
enum ndr_err_code ndr_err;
DATA_BLOB raw_out;
struct chiron_altmsg_challenge *challenge;
int hdrlen;
DEBUG(0, "Sending out an alt challenge");
alt = talloc_zero(account, struct chiron_alt_message);
NO_MEM_RETURN(alt);
alt->msg_type = CHIRON_CHALLENGE;
alt->seq = ctx->seq;
alt->something01 = 0x01;
alt->otherthing01 = 0x01;
alt->someflag = ctx->flags;
alt->something00 = 0x00;
alt->length = 0x0B;
challenge = &alt->msg.challenge;
hdrlen = ALTMSG_HDR_LEN;
/* FIXME This should be random, but that is annoying for testing purposes */
challenge->length = CHALLENGE_LEN;
challenge->challenge = talloc_zero_array(alt, uint8_t, CHALLENGE_LEN);
NO_MEM_RETURN(challenge->challenge);
challenge->challenge[0] = 0x60;
challenge->challenge[1] = 0x19;
challenge->challenge[2] = 0x12;
challenge->challenge[3] = 0xa8;
challenge->challenge[4] = 0x91;
challenge->challenge[5] = 0x45;
challenge->challenge[6] = 0x89;
challenge->challenge[7] = 0x8f;
challenge->challenge[8] = 0x37;
ndr_err = ndr_push_struct_blob(&raw_out, alt, alt, (ndr_push_flags_fn_t)ndr_push_chiron_alt_message);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Error writing NDR data blob.");
return ST_WRITE_ERROR;
}
/* Update the rc4 crypto key, which is seq+challenge */
md5input = talloc_array(account, uint8_t, CHALLENGE_LEN + 1);
NO_MEM_RETURN(md5input);
md5input[0] = ctx->seq;
memcpy(&md5input[1], &raw_out.data[hdrlen], CHALLENGE_LEN);
md5_init(&md5);
md5_update(&md5, CHALLENGE_LEN + 1, md5input);
md5_digest(&md5, MD5_HASH_LEN, ctx->rc4key);
/* Update the md5 check for the next message (last 9 bytes with the seq byte appended). */
memcpy(md5input, &raw_out.data[hdrlen], CHALLENGE_LEN);
md5input[CHALLENGE_LEN] = ctx->seq;
md5_init(&md5);
md5_update(&md5, CHALLENGE_LEN + 1, md5input);
md5_digest(&md5, MD5_HASH_LEN, ctx->md5_last_out);
int count = write(ctx->clientfd, raw_out.data, raw_out.length);
if (count < 0) {
DEBUG(0, "Error during write of %d bytes to fd %d: %s", raw_out.length, ctx->clientfd, strerror(errno));
} else if ((unsigned)count < raw_out.length) {
DEBUG(0, "Short write during writing out the raw_data with length %d", raw_out.length);
}
/* Update the md5 check for the next message (last 9 bytes with the seq byte appended). */
talloc_free(alt);
return ST_OK;
}
STATUS send_chiron_msg_challenge(struct chiron_context *ctx, struct chiron_msg_account *account) {
struct chiron_message *out;
struct md5_ctx md5;
uint8_t *md5input;
enum ndr_err_code ndr_err;
DATA_BLOB raw_out;
struct chiron_msg_challenge *challenge;
int hdrlen;
DEBUG(0, "Sending out a challenge");
out = talloc_zero(account, struct chiron_message);
NO_MEM_RETURN(out);
out->msg_type = CHIRON_CHALLENGE;
out->seq = ctx->seq;
out->flags = ctx->flags;
challenge = &out->msg.challenge;
hdrlen = MSG_HDR_LEN;
/* Make an md5 hash of the account code with the seq byte appended. */
md5input = talloc_array(account, uint8_t, account->length + 1);
NO_MEM_RETURN(md5input);
memcpy(md5input, account->account_code, account->length);
md5input[account->length] = ctx->seq;
challenge->md5_check = talloc_array(account, uint8_t, MD5_HASH_LEN);
NO_MEM_RETURN(challenge->md5_check);
md5_init(&md5);
md5_update(&md5, account->length + 1, md5input);
md5_digest(&md5, MD5_HASH_LEN, challenge->md5_check);
talloc_free(md5input);
/* FIXME This should be random, but that is annoying for testing purposes */
challenge->length = MD5_HASH_LEN + CHALLENGE_LEN;
challenge->challenge = talloc_zero_array(account, uint8_t, CHALLENGE_LEN);
NO_MEM_RETURN(challenge->challenge);
challenge->challenge[0] = 0xd0;
challenge->challenge[1] = 0x8b;
challenge->challenge[2] = 0x29;
challenge->challenge[3] = 0xd3;
challenge->challenge[4] = 0x7c;
challenge->challenge[5] = 0xfd;
challenge->challenge[6] = 0xb5;
challenge->challenge[7] = 0xc6;
challenge->challenge[8] = 0x1e;
ndr_err = ndr_push_struct_blob(&raw_out, out, out, (ndr_push_flags_fn_t)ndr_push_chiron_message);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Error writing NDR data blob.");
return ST_WRITE_ERROR;
}
/* Update the md5 check for the next message (last 9 bytes with the seq byte appended). */
md5input = talloc_array(account, uint8_t, CHALLENGE_LEN + 1);
NO_MEM_RETURN(md5input);
memcpy(md5input, &raw_out.data[hdrlen + MD5_HASH_LEN], CHALLENGE_LEN);
md5input[CHALLENGE_LEN] = ctx->seq;
md5_init(&md5);
md5_update(&md5, CHALLENGE_LEN + 1, md5input);
md5_digest(&md5, MD5_HASH_LEN, ctx->md5_last_out);
/* Update the rc4 crypto key, which is seq+challenge */
md5input[0] = ctx->seq;
memcpy(&md5input[1], &raw_out.data[hdrlen + MD5_HASH_LEN], CHALLENGE_LEN);
md5_init(&md5);
md5_update(&md5, CHALLENGE_LEN + 1, md5input);
md5_digest(&md5, MD5_HASH_LEN, ctx->rc4key);
DEBUG(0, "The expected md5sum for the next entry is %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
ctx->md5_last_out[0], ctx->md5_last_out[1], ctx->md5_last_out[2], ctx->md5_last_out[3],
ctx->md5_last_out[4], ctx->md5_last_out[5], ctx->md5_last_out[6], ctx->md5_last_out[9],
ctx->md5_last_out[8], ctx->md5_last_out[9], ctx->md5_last_out[10], ctx->md5_last_out[11],
ctx->md5_last_out[12], ctx->md5_last_out[13], ctx->md5_last_out[14], ctx->md5_last_out[15]);
int count = write(ctx->clientfd, raw_out.data, raw_out.length);
if (count < 0) {
DEBUG(0, "Error during write of %d bytes to fd %d: %s", raw_out.length, ctx->clientfd, strerror(errno));
} else if ((unsigned)count < raw_out.length) {
DEBUG(0, "Short write during writing out the raw_data with length %d", raw_out.length);
}
talloc_free(out);
return ST_OK;
}
STATUS handle_chiron_msg_account(struct chiron_context *ctx, struct chiron_msg_account *account) {
ctx->account_code = talloc_memdup(account, account->account_code, account->length);
NO_MEM_RETURN(ctx->account_code);
if (!ctx->alt_format) {
return send_chiron_msg_challenge(ctx, account);
} else {
return send_chiron_altmsg_challenge(ctx, account);
}
}
STATUS send_chiron_altmsg_ack(struct chiron_context *ctx, struct chiron_msg_signal *signal) {
struct chiron_alt_message *alt;
enum ndr_err_code ndr_err;
DATA_BLOB raw_out;
DEBUG(0, "Sending out an alt ack");
alt = talloc_zero(signal, struct chiron_alt_message);
NO_MEM_RETURN(alt);
alt->msg_type = CHIRON_ACCOUNT;
alt->seq = ctx->seq;
alt->something01 = 0x01;
alt->otherthing01 = 0x01;
alt->someflag = ctx->flags;
alt->something00 = 0x00;
alt->length = 0x02;
alt->msg.account.length = 0;
ndr_err = ndr_push_struct_blob(&raw_out, alt, alt, (ndr_push_flags_fn_t)ndr_push_chiron_alt_message);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Error writing NDR data blob.");
return ST_WRITE_ERROR;
}
int count = write(ctx->clientfd, raw_out.data, raw_out.length);
if (count < 0) {
DEBUG(0, "Error during write of %d bytes to fd %d: %s", raw_out.length, ctx->clientfd, strerror(errno));
} else if ((unsigned)count < raw_out.length) {
DEBUG(0, "Short write during writing out the raw_data with length %d", raw_out.length);
}
talloc_free(alt);
return ST_OK;
}
STATUS handle_chiron_msg_signal(struct chiron_context *ctx, struct chiron_msg_signal *signal) {
DATA_BLOB crypted, decrypted;
struct arcfour_ctx rc4;
/* Copy packet to crypted data blob */
crypted.length = signal->length+6;
crypted.data = talloc_memdup(signal, signal->data, crypted.length);
NO_MEM_RETURN(crypted.data);
decrypted.data = talloc_array(signal, uint8_t, crypted.length);
NO_MEM_RETURN(decrypted.data);
decrypted.length = crypted.length;
arcfour_set_key(&rc4, MD5_HASH_LEN, ctx->rc4key);
arcfour_crypt(&rc4, crypted.length, decrypted.data, crypted.data);
hexdump("Decrypted", decrypted.data, decrypted.length);
return send_chiron_altmsg_ack(ctx, signal);
}
STATUS handle_message(struct chiron_context *ctx, DATA_BLOB data) {
struct chiron_message *msg = talloc(data.data, struct chiron_message);
NO_MEM_RETURN(msg);
struct chiron_alt_message *alt_msg = talloc(data.data, struct chiron_alt_message);
NO_MEM_RETURN(msg);
/* Parse the packet */
enum ndr_err_code ndr_err;
if (data.length > 0 && data.data[0] != 1) {
ctx->alt_format = 0;
ndr_err = ndr_pull_struct_blob_all(&data, msg, msg, (ndr_pull_flags_fn_t)ndr_pull_chiron_message);
} else {
ctx->alt_format = 1;
ndr_err = ndr_pull_struct_blob_all(&data, alt_msg, alt_msg, (ndr_pull_flags_fn_t)ndr_pull_chiron_alt_message);
}
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Could not parse this message");
hexdump("Message bytes", data.data, data.length);
return ST_PARSE_ERROR;
}
enum chiron_msg_type msg_type;
if (ctx->alt_format) {
ctx->seq = alt_msg->seq;
ctx->flags = 0;
msg_type = alt_msg->msg_type;
DEBUG(0, "%s", ndr_print_struct_string(msg,(ndr_print_fn_t)ndr_print_chiron_alt_message, "chiron alt message", alt_msg));
} else {
ctx->seq = msg->seq;
ctx->flags = msg->flags;
msg_type = msg->msg_type;
DEBUG(0, "%s", ndr_print_struct_string(msg,(ndr_print_fn_t)ndr_print_chiron_message, "chiron message", msg));
}
STATUS status;
switch (msg_type) {
case CHIRON_ACCOUNT: {
struct chiron_msg_account *account;
if (ctx->alt_format) {
account = talloc_memdup(alt_msg, &alt_msg->msg.account, sizeof(struct chiron_msg_account));
} else {
account = talloc_memdup(msg, &msg->msg.account, sizeof(struct chiron_msg_account));
}
DEBUG(0, "Got chiron_msg_account");
status = handle_chiron_msg_account(ctx, account);
break;
}
case CHIRON_RESPONSE: {
struct chiron_msg_response *response;
if (ctx->alt_format) {
response = talloc_memdup(alt_msg, &alt_msg->msg.response.response, sizeof(struct chiron_msg_response));
} else {
response = talloc_memdup(msg, &msg->msg.response, sizeof(struct chiron_msg_response));
}
DEBUG(0, "Got chiron_msg_response");
status = handle_chiron_msg_response(ctx, response);
break;
}
case CHIRON_ACK: {
struct chiron_msg_ack *ack;
if (ctx->alt_format) {
ack = talloc_memdup(alt_msg, &alt_msg->msg.ack, sizeof(struct chiron_msg_ack));
} else {
ack = talloc_memdup(msg, &msg->msg.ack, sizeof(struct chiron_msg_ack));
}
DEBUG(0, "Got chiron_msg_ack");
status = handle_chiron_msg_ack(ctx, ack);
break;
}
case CHIRON_SIGNAL: {
struct chiron_msg_signal *signal;
if (ctx->alt_format) {
signal = talloc_memdup(alt_msg, &alt_msg->msg.signal, sizeof(struct chiron_msg_signal));
} else {
signal = talloc_memdup(msg, &msg->msg.signal, sizeof(struct chiron_msg_signal));
}
DEBUG(0, "Got chiron_msg_signal");
status = handle_chiron_msg_signal(ctx, signal);
break;
}
default:
DEBUG(0, "Got unexpected message type: %s.",
ndr_print_chiron_msg_type_enum(msg, msg->msg_type));
status = ST_NOT_IMPLEMENTED;
break;
}
if (status != ST_OK) {
return status;
}
talloc_free(msg);
return ST_OK;
}
STATUS handle_connection(struct chiron_context *ctx) {
int n;
char buf[1024]; /* Purposefully static length */
DATA_BLOB data;
while ((n = read(ctx->clientfd, buf, sizeof(buf)))) {
if (n < 0) {
DEBUG( 0, "Error when reading packet from fd %d: %s!", ctx->clientfd, strerror(errno));
return ST_PARSE_ERROR;
} else if (n == sizeof(buf)) {
DEBUG(0, "Maximum packet size exceeded!");
return ST_PARSE_ERROR;
}
/* Copy packet to data blob */
data.length = n;
data.data = talloc_memdup(ctx, buf, n);
NO_MEM_RETURN(data.data);
STATUS status = handle_message(ctx, data);
if (status != ST_OK) {
DEBUG(0,"Got handle_message status %d", status);
return status;
}
talloc_free(data.data);
}
return ST_OK;
}
static STATUS daemonize(char *pid_file) {
FILE *pidfile;
pid_t pid;
fclose(stdin);
fclose(stdout);
fclose(stderr);
if ((pid = fork())) {
/* Write PID file */
pidfile = fopen(pid_file, "w");
if (pidfile == NULL)
exit(1);
fprintf(pidfile, "%d\n", pid);
fclose(pidfile);
exit(0);
}
return ST_OK;
}
static STATUS listen_server(TALLOC_CTX *mem_ctx, const char *bindaddr, const char *bindport, const char *protocol, STATUS (*dispatcher)(struct chiron_context *)) {
int sock;
socklen_t clientlen;
struct addrinfo hints, *server, *first_server;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
getaddrinfo(bindaddr, bindport, &hints, &server);
first_server = server;
while (server) {
sock = socket(server->ai_family, SOCK_STREAM, 0);
if (sock >= 0) {
int optval = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (bind(sock, server->ai_addr, server->ai_addrlen) < 0) {
close(sock);
sock = -1;
} else {
break;
}
}
server = server->ai_next;
}
if (sock < 0) {
DEBUG(0, "Could not create socket in server");
freeaddrinfo(first_server);
return ST_SOCKET_FAILURE;
}
listen(sock, 128);
freeaddrinfo(first_server);
DEBUG(0, "Started %s and waiting for Chiron messages on port %s",
get_process_name(), CHIRON_PORT);
/*
* Wait for connections
*/
clientlen = sizeof(struct addrinfo);
while (1) {
int clientfd;
struct sockaddr_storage clientaddr;
char clienthost[NI_MAXHOST];
char clientservice[NI_MAXSERV];
clientfd = accept(sock, (struct sockaddr *)&clientaddr, &clientlen);
if (clientfd < 0) {
DEBUG(0, "Error on accept: %s", strerror(errno));
continue;
}
getnameinfo((struct sockaddr *)&clientaddr, clientlen,
clienthost, sizeof(clienthost),
clientservice, sizeof(clientservice),
NI_NUMERICHOST | NI_NUMERICSERV);
DEBUG(3, "Received connection from %s:%s", clienthost, clientservice);
if (fork()) {
close(clientfd);
continue;
} else {
struct chiron_context *client_ctx = talloc_zero(mem_ctx, struct chiron_context);
if (client_ctx == NULL) {
close(sock);
close(clientfd);
DEBUG(0, "Out of memory");
return ST_OUT_OF_MEMORY;
}
client_ctx->clientaddr = (struct sockaddr *)&clientaddr;
client_ctx->clientfd = clientfd;
DEBUG(0, "Handling connection for fd %d", clientfd);
STATUS status = dispatcher(client_ctx);
DEBUG(0, "Shutting down connection for fd %d", clientfd);
shutdown(clientfd, SHUT_RDWR);
close(clientfd);
talloc_free(client_ctx);
exit(status);
}
}
shutdown(sock, SHUT_RDWR);
close(sock);
}
static void sigchld_handler(int sig)
{
pid_t p;
int status;
while ((p = waitpid(-1, &status, WNOHANG)) > 0) {
DEBUG(0, "Child process %d exited with status %d", p, status);
}
}
int main (int argc, char **argv) {
TALLOC_CTX *mem_ctx;
STATUS rv;
const configuration *conf;
set_process_name(argv[0]);
/* Initialize a memory context */
mem_ctx = talloc_init("chirond");
/* Read the configuration file */
rv = read_configuration_file(mem_ctx);
if (rv != ST_OK)
return rv;
conf = get_conf();
/* Daemonize if we're not supposed to run in foreground mode */
if (!conf->foreground) {
daemonize(conf->pid_file);
}
/*
* Handle death of children
*/
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigchld_handler;
sigaction(SIGCHLD, &sa, NULL);
/*
* Open up a TCP socket the Chiron port
*/
listen_server(mem_ctx, "::", CHIRON_PORT, "tcp", handle_connection);
talloc_free(mem_ctx);
return 0;
}

20
crc16.c
View file

@ -1,20 +0,0 @@
#include <stdint.h>
uint16_t calculate_crc (const uint8_t *ptr, uint16_t count) {
#define CRC16_SEED 0x1021
uint16_t crc;
uint8_t i;
crc = 0;
while (count-- > 0) {
crc = crc ^ ((uint16_t) *ptr++ << 8);
for (i = 0; i < 8; i++) {
if (crc & 0x8000) {
crc = crc << 1 ^ CRC16_SEED;
} else {
crc = crc << 1;
}
}
}
return crc;
}

View file

@ -1,2 +0,0 @@
uint16_t calculate_crc (const uint8_t *ptr, uint16_t count);

164
secip.idl
View file

@ -1,164 +0,0 @@
[
helper("../crc16.h")
]
interface secip
{
typedef [public,enum8bit] enum {
SECIP_ERR_SUCCESS = 0x00,
SECIP_ERR_ACKNOWLEDGE = 0x01,
SECIP_ERR_NEGATIVE_ACKNOWLEDGE = 0x02,
SECIP_ERR_ARC_COULD_NOT_PROCESS_MESSAGE = 0x03,
SECIP_ERR_PROTOCOL_ID_NOT_SUPPORTED = 0x04,
SECIP_ERR_PROTOCOL_VERSION_NOT_SUPPORTED = 0x05,
SECIP_ERR_PPK_BLOCK_VERSION_NOT_SUPPORTED = 0x06,
SECIP_ERR_CRC_MODE_NOT_SUPPORTED = 0x07,
SECIP_ERR_ACCOUNT_CODE_NOT_ALLOWED = 0x08,
SECIP_ERR_CONNECTION_NOT_ALLOWED = 0x0D,
SECIP_ERR_SUPERVISION_NOT_SUPPORTED = 0x09,
SECIP_ERR_SUPERVISION_REQUEST_TOO_FAST = 0x0A,
SECIP_ERR_SUPERVISION_REQUEST_TOO_SLOW = 0x0B,
SECIP_ERR_PATHCHECK_NOT_SUPPORTED = 0x0C,
SECIP_ERR_REESTABLISH_CONNECTION = 0x80,
SECIP_ERR_UNKNOWN_ERROR = 0xFF
} secip_error;
typedef [public,enum8bit] enum {
SECIP_MSG_ATE_ENC = 0x01,
SECIP_MSG_ARC_ENC = 0x81,
SECIP_MSG_PPK_COM = 0x02,
SECIP_MSG_PPK_REP = 0x82,
SECIP_MSG_PATH_SUPERVISION_REQUEST = 0x10,
SECIP_MSG_PATH_SUPERVISION_RESPONSE = 0x90,
SECIP_MSG_PATH_CHECK_REQUEST = 0x20,
SECIP_MSG_PATH_CHECK_RESPONSE = 0xA0,
SECIP_MSG_POLL_MESSAGE = 0x11,
SECIP_MSG_POLL_ACKNOWLEDGE = 0x91,
SECIP_MSG_ALARM = 0x30,
SECIP_MSG_ALARM_ACKNOWLEDGE = 0xB0
} secip_message;
typedef [public,enum8bit] enum {
SECIP_PROTO_SIA = 0x01,
SECIP_PROTO_CONTACTID = 0x02,
SECIP_PROTO_SCANCOM = 0x03,
SECIP_PROTO_SIAHS = 0x04
} secip_protocol;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
[value(0)] uint16 session_id;
uint8 padding[202];
} secip_ate_enc;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
[value(0)] uint16 session_id;
uint8 rsa_key[128];
uint8 padding[74];
} secip_ppk_com;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
[value(1)] uint8 version;
uint8 aes_key[16];
} secip_key_message_block;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
[value(1)] uint8 protocol_version;
uint8 manufacturer[20];
uint8 panel_type[12];
uint8 panel_version[8];
uint8 account_code[6];
uint8 crc_mode;
uint16 session_id;
secip_key_message_block key_block;
uint8 padding[136];
} secip_ppk_rep;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
secip_error error_code;
uint16 session_id;
uint8 padding[231];
} secip_arc_enc;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint16 path_id;
uint32 interval_seconds;
uint8 padding[70];
} secip_psup_req;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
secip_error error_code;
uint16 path_id;
uint32 interval_seconds;
uint8 padding[69];
} secip_psup_resp;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 padding[76];
} secip_pathcheck_req;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
secip_error error_code;
uint8 path_check_id;
uint8 padding[74];
} secip_pathcheck_resp;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
secip_protocol protocol_identifier;
[range(0,97)] uint8 length;
int8 message[length];
} secip_alarm;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
secip_error error_code;
uint8 padding[75];
} secip_alarm_ack;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint16 path_check_id;
uint8 padding[74];
} secip_poll_message;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
secip_error error_code;
uint16 path_check_id;
uint8 padding[73];
} secip_poll_ack;
typedef [nodiscriminant,public,flag(LIBNDR_FLAG_NOALIGN)] union {
[case(SECIP_MSG_ATE_ENC)] secip_ate_enc ate_enc;
[case(SECIP_MSG_PPK_COM)] secip_ppk_com ppk_com;
[case(SECIP_MSG_PPK_REP)] secip_ppk_rep ppk_rep;
[case(SECIP_MSG_ARC_ENC)] secip_arc_enc arc_enc;
[case(SECIP_MSG_PATH_SUPERVISION_REQUEST)] secip_psup_req psup_req;
[case(SECIP_MSG_PATH_SUPERVISION_RESPONSE)] secip_psup_resp psup_resp;
[case(SECIP_MSG_PATH_CHECK_REQUEST)] secip_pathcheck_req pathcheck_req;
[case(SECIP_MSG_PATH_CHECK_RESPONSE)] secip_pathcheck_resp pathcheck_resp;
[case(SECIP_MSG_ALARM)] secip_alarm alarm;
[case(SECIP_MSG_ALARM_ACKNOWLEDGE)] secip_alarm_ack alarm_ack;
[case(SECIP_MSG_POLL_MESSAGE)] secip_poll_message poll_message;
[case(SECIP_MSG_POLL_ACKNOWLEDGE)] secip_poll_ack poll_ack;
} secip_msg_union;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint16 connection_id; /* 0xffff is unassigned */
uint8 pad; /* This is a fix for a broken spec. This is necessary because
there is no secure cryptographic padding and you can't
encrypt a 128-byte block with a 1024-bit public key.
*/
secip_message message_id;
uint16 sequence_number;
char device_id[16];
[switch_is(message_id)] secip_msg_union msg;
} secip_packet;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 raw_packet[226];
uint8 padding[30];
[value(calculate_crc(raw_packet, 256))] uint16 crc;
} secip_setup_packet;
typedef [public,flag(LIBNDR_FLAG_NOALIGN)] struct {
uint8 raw_packet[98];
uint8 padding[30];
[value(calculate_crc(raw_packet, 128))] uint16 crc;
} secip_comm_packet;
};

627
secipd.c
View file

@ -1,627 +0,0 @@
/*
Vebon Sec-IP Alarm Monitoring Service
Copyright (C) Wilco Baan Hofman <wilco@baanhofman.nl> 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 4 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <nettle/aes.h>
#include "includes.h"
#include "build/ndr_secip.h"
#include "siahs.h"
/* FIXME Does not handle multiple connections.. should be per connection obviously!! */
static uint8_t global_aes_key[16];
static STATUS send_ppk_com(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
struct secip_setup_packet *setup_pkt;
struct secip_packet *ppk_com;
DATA_BLOB raw_pkt, raw_setup_pkt;
enum ndr_err_code ndr_err;
size_t i;
size_t count;
const configuration *conf = get_conf();
setup_pkt = talloc(mem_ctx, struct secip_setup_packet);
NO_MEM_RETURN(setup_pkt);
ppk_com = talloc(setup_pkt, struct secip_packet);
NO_MEM_RETURN(ppk_com);
ppk_com->pad = 0;
ppk_com->connection_id = 0x1337; /* FIXME */
ppk_com->message_id = SECIP_MSG_PPK_COM;
ppk_com->sequence_number = 1;
ppk_com->msg.ppk_com.session_id = 0;
/* Device ID must not be readable at this stage */
for (i = 0; i < 16; i++) {
ppk_com->device_id[i] = rand();
}
for (i = 0; i < 74; i++) {
ppk_com->msg.ppk_com.padding[i] = rand();
}
mpz_export(&ppk_com->msg.ppk_com.rsa_key, &count, -1, 1, -1, 0, conf->public_key->n);
DEBUG(9, "%s", ndr_print_struct_string(pkt,(ndr_print_fn_t)ndr_print_secip_packet, "ppk_com packet", ppk_com));
ndr_err = ndr_push_struct_blob(&raw_pkt, ppk_com, ppk_com, (ndr_push_flags_fn_t)ndr_push_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
memcpy(setup_pkt->raw_packet, raw_pkt.data, raw_pkt.length);
for (i = 0; i < 30; i++) {
setup_pkt->padding[i] = rand();
}
ndr_err = ndr_push_struct_blob(&raw_setup_pkt, setup_pkt, setup_pkt, (ndr_push_flags_fn_t)ndr_push_secip_setup_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
sendto(sock, raw_setup_pkt.data, raw_setup_pkt.length, 0, (struct sockaddr *)&from, sizeof(from));
talloc_free(setup_pkt);
return 0;
}
static STATUS send_arc_enc(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
struct secip_setup_packet *setup_pkt;
struct secip_packet *arc_enc;
DATA_BLOB raw_pkt, raw_setup_pkt, crypted_setup_pkt;
size_t i;
enum ndr_err_code ndr_err;
struct aes_ctx aes;
aes_set_encrypt_key(&aes, 16, pkt->msg.ppk_rep.key_block.aes_key);
/* FIXME DEATH TO THE GLOBALS! */
memcpy(global_aes_key, pkt->msg.ppk_rep.key_block.aes_key, 16);
setup_pkt = talloc(mem_ctx, struct secip_setup_packet);
NO_MEM_RETURN(setup_pkt);
arc_enc = talloc_zero(setup_pkt, struct secip_packet);
NO_MEM_RETURN(arc_enc);
arc_enc->pad = 0;
arc_enc->connection_id = 0x1337; /* FIXME */
memcpy(arc_enc->device_id, "Bitlair SecIPd!", 16);
arc_enc->message_id = SECIP_MSG_ARC_ENC;
arc_enc->sequence_number = 2;
arc_enc->msg.arc_enc.error_code = SECIP_ERR_SUCCESS;
arc_enc->msg.arc_enc.session_id = pkt->msg.ppk_com.session_id;
for (i = 0; i < 231; i++) {
arc_enc->msg.arc_enc.padding[i] = rand();
}
DEBUG(9, "%s", ndr_print_struct_string(mem_ctx, (ndr_print_fn_t)ndr_print_secip_packet, "arc_enc packet", arc_enc));
ndr_err = ndr_push_struct_blob(&raw_pkt, arc_enc, arc_enc, (ndr_push_flags_fn_t)ndr_push_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
memcpy(setup_pkt->raw_packet, raw_pkt.data, raw_pkt.length);
for (i = 0; i < 30; i++) {
setup_pkt->padding[i] = rand();
}
ndr_err = ndr_push_struct_blob(&raw_setup_pkt, setup_pkt, setup_pkt, (ndr_push_flags_fn_t)ndr_push_secip_setup_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
crypted_setup_pkt.data = talloc_zero_array(mem_ctx, uint8_t, 258);
NO_MEM_RETURN(crypted_setup_pkt.data);
crypted_setup_pkt.length = 258;
memcpy(crypted_setup_pkt.data, raw_setup_pkt.data, 2);
aes_encrypt(&aes, raw_setup_pkt.length-2, crypted_setup_pkt.data+2, raw_setup_pkt.data+2);
sendto(sock, crypted_setup_pkt.data, crypted_setup_pkt.length, 0, (struct sockaddr *)&from, sizeof(from));
return ST_OK;
}
static STATUS send_psup_resp(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
DATA_BLOB raw_pkt, raw_comm_pkt, crypted_comm_pkt;
struct secip_comm_packet *comm_pkt;
struct secip_packet *psup_resp;
enum ndr_err_code ndr_err;
struct aes_ctx aes;
int i;
/* FIXME DEATH TO THE GLOBALS! */
aes_set_encrypt_key(&aes, 16, global_aes_key);
comm_pkt = talloc(mem_ctx, struct secip_comm_packet);
NO_MEM_RETURN(comm_pkt);
psup_resp = talloc_zero(comm_pkt, struct secip_packet);
NO_MEM_RETURN(psup_resp);
psup_resp->pad = 0;
psup_resp->connection_id = 0x1337; /* FIXME */
memcpy(psup_resp->device_id, "Bitlair SecIPd!", 16);
psup_resp->message_id = SECIP_MSG_PATH_SUPERVISION_RESPONSE;
psup_resp->sequence_number = pkt->sequence_number;
psup_resp->msg.psup_resp.error_code = SECIP_ERR_SUCCESS; /* FIXME: Make sure we actually supervise */
psup_resp->msg.psup_resp.path_id = pkt->msg.psup_req.path_id;
psup_resp->msg.psup_resp.interval_seconds = pkt->msg.psup_req.interval_seconds;
for (i = 0; i < 69; i++) {
psup_resp->msg.psup_resp.padding[i] = rand();
}
DEBUG(9, "%s", ndr_print_struct_string(mem_ctx, (ndr_print_fn_t)ndr_print_secip_packet, "psup_resp packet", psup_resp));
ndr_err = ndr_push_struct_blob(&raw_pkt, psup_resp, psup_resp, (ndr_push_flags_fn_t)ndr_push_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
memcpy(comm_pkt->raw_packet, raw_pkt.data, raw_pkt.length);
for (i = 0; i < 30; i++) {
comm_pkt->padding[i] = rand();
}
ndr_err = ndr_push_struct_blob(&raw_comm_pkt, comm_pkt, comm_pkt, (ndr_push_flags_fn_t)ndr_push_secip_comm_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
crypted_comm_pkt.data = talloc_zero_array(mem_ctx, uint8_t, 258);
NO_MEM_RETURN(crypted_comm_pkt.data);
crypted_comm_pkt.length = 130;
memcpy(crypted_comm_pkt.data, raw_comm_pkt.data, 2);
aes_encrypt(&aes, raw_comm_pkt.length-2, crypted_comm_pkt.data+2, raw_comm_pkt.data+2);
sendto(sock, crypted_comm_pkt.data, crypted_comm_pkt.length, 0, (struct sockaddr *)&from, sizeof(from));
return ST_OK;
}
static STATUS send_pathcheck_resp(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
DATA_BLOB raw_pkt, raw_comm_pkt, crypted_comm_pkt;
struct secip_comm_packet *comm_pkt;
struct secip_packet *pathcheck_resp;
enum ndr_err_code ndr_err;
struct aes_ctx aes;
int i;
/* FIXME DEATH TO THE GLOBALS! */
aes_set_encrypt_key(&aes, 16, global_aes_key);
comm_pkt = talloc(mem_ctx, struct secip_comm_packet);
NO_MEM_RETURN(comm_pkt);
pathcheck_resp = talloc_zero(comm_pkt, struct secip_packet);
NO_MEM_RETURN(pathcheck_resp);
pathcheck_resp->pad = 0;
pathcheck_resp->connection_id = 0x1337; /* FIXME */
memcpy(pathcheck_resp->device_id, "Bitlair SecIPd!", 16);
pathcheck_resp->message_id = SECIP_MSG_PATH_SUPERVISION_RESPONSE;
pathcheck_resp->sequence_number = pkt->sequence_number;
pathcheck_resp->msg.pathcheck_resp.error_code = SECIP_ERR_PATHCHECK_NOT_SUPPORTED; /* FIXME */
for (i = 0; i < 74; i++) {
pathcheck_resp->msg.pathcheck_resp.padding[i] = rand();
}
DEBUG(9, "%s", ndr_print_struct_string(mem_ctx, (ndr_print_fn_t)ndr_print_secip_packet, "pathcheck_resp packet", pathcheck_resp));
ndr_err = ndr_push_struct_blob(&raw_pkt, pathcheck_resp, pathcheck_resp, (ndr_push_flags_fn_t)ndr_push_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
memcpy(comm_pkt->raw_packet, raw_pkt.data, raw_pkt.length);
for (i = 0; i < 30; i++) {
comm_pkt->padding[i] = rand();
}
ndr_err = ndr_push_struct_blob(&raw_comm_pkt, comm_pkt, comm_pkt, (ndr_push_flags_fn_t)ndr_push_secip_comm_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
crypted_comm_pkt.data = talloc_zero_array(mem_ctx, uint8_t, 258);
NO_MEM_RETURN(crypted_comm_pkt.data);
crypted_comm_pkt.length = 130;
memcpy(crypted_comm_pkt.data, raw_comm_pkt.data, 2);
aes_encrypt(&aes, raw_comm_pkt.length-2, crypted_comm_pkt.data+2, raw_comm_pkt.data+2);
sendto(sock, crypted_comm_pkt.data, crypted_comm_pkt.length, 0, (struct sockaddr *)&from, sizeof(from));
return ST_OK;
}
static STATUS send_alarm_ack(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
DATA_BLOB raw_pkt, raw_comm_pkt, crypted_comm_pkt;
struct secip_comm_packet *comm_pkt;
struct secip_packet *alarm_ack;
enum ndr_err_code ndr_err;
struct aes_ctx aes;
int i;
char *message;
/* FIXME DEATH TO THE GLOBALS! */
aes_set_encrypt_key(&aes, 16, global_aes_key);
message = talloc_strndup(pkt, (char *)pkt->msg.alarm.message, pkt->msg.alarm.length);
NO_MEM_RETURN(message);
DEBUG(0, "Got message: %s", message);
/* FIXME Hardcoded prom */
if (pkt->msg.alarm.protocol_identifier == SECIP_PROTO_SIAHS) {
parse_siahs_message(pkt, "1337", message);
} else {
DEBUG(0, "Unsupported subprotocol!");
}
comm_pkt = talloc(mem_ctx, struct secip_comm_packet);
NO_MEM_RETURN(comm_pkt);
alarm_ack = talloc_zero(comm_pkt, struct secip_packet);
NO_MEM_RETURN(alarm_ack);
alarm_ack->pad = 0;
alarm_ack->connection_id = 0x1337; /* FIXME */
memcpy(alarm_ack->device_id, "Bitlair SecIPd!", 16);
alarm_ack->message_id = SECIP_MSG_ALARM_ACKNOWLEDGE;
alarm_ack->sequence_number = pkt->sequence_number;
alarm_ack->msg.alarm_ack.error_code = SECIP_ERR_ACKNOWLEDGE;
for (i = 0; i < 75; i++) {
alarm_ack->msg.alarm_ack.padding[i] = rand();
}
DEBUG(9, "%s\n", ndr_print_struct_string(mem_ctx, (ndr_print_fn_t)ndr_print_secip_packet, "alarm_ack packet", alarm_ack));
ndr_err = ndr_push_struct_blob(&raw_pkt, alarm_ack, alarm_ack, (ndr_push_flags_fn_t)ndr_push_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
memcpy(comm_pkt->raw_packet, raw_pkt.data, raw_pkt.length);
for (i = 0; i < 30; i++) {
comm_pkt->padding[i] = rand();
}
ndr_err = ndr_push_struct_blob(&raw_comm_pkt, comm_pkt, comm_pkt, (ndr_push_flags_fn_t)ndr_push_secip_comm_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
crypted_comm_pkt.data = talloc_zero_array(mem_ctx, uint8_t, 258);
NO_MEM_RETURN(crypted_comm_pkt.data);
crypted_comm_pkt.length = 130;
memcpy(crypted_comm_pkt.data, raw_comm_pkt.data, 2);
aes_encrypt(&aes, raw_comm_pkt.length-2, crypted_comm_pkt.data+2, raw_comm_pkt.data+2);
sendto(sock, crypted_comm_pkt.data, crypted_comm_pkt.length, 0, (struct sockaddr *)&from, sizeof(from));
return ST_OK;
}
static STATUS send_poll_ack(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
DATA_BLOB raw_pkt, raw_comm_pkt, crypted_comm_pkt;
struct secip_comm_packet *comm_pkt;
struct secip_packet *poll_ack;
enum ndr_err_code ndr_err;
struct aes_ctx aes;
int i;
/* FIXME DEATH TO THE GLOBALS! */
aes_set_encrypt_key(&aes, 16, global_aes_key);
comm_pkt = talloc(mem_ctx, struct secip_comm_packet);
NO_MEM_RETURN(comm_pkt);
poll_ack = talloc_zero(comm_pkt, struct secip_packet);
NO_MEM_RETURN(poll_ack);
poll_ack->pad = 0;
poll_ack->connection_id = 0x1337; /* FIXME */
memcpy(poll_ack->device_id, "Bitlair SecIPd!", 16);
poll_ack->message_id = SECIP_MSG_PATH_SUPERVISION_RESPONSE;
poll_ack->sequence_number = pkt->sequence_number;
poll_ack->msg.pathcheck_resp.error_code = SECIP_ERR_SUCCESS; /* FIXME */
for (i = 0; i < 73; i++) {
poll_ack->msg.poll_ack.padding[i] = rand();
}
DEBUG(9, "%s", ndr_print_struct_string(mem_ctx, (ndr_print_fn_t)ndr_print_secip_packet, "poll_ack packet", poll_ack));
ndr_err = ndr_push_struct_blob(&raw_pkt, poll_ack, poll_ack, (ndr_push_flags_fn_t)ndr_push_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
memcpy(comm_pkt->raw_packet, raw_pkt.data, raw_pkt.length);
for (i = 0; i < 30; i++) {
comm_pkt->padding[i] = rand();
}
ndr_err = ndr_push_struct_blob(&raw_comm_pkt, comm_pkt, comm_pkt, (ndr_push_flags_fn_t)ndr_push_secip_comm_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Oh holy shitstorm! That didn't work!");
return ST_GENERAL_FAILURE;
}
crypted_comm_pkt.data = talloc_zero_array(mem_ctx, uint8_t, 258);
NO_MEM_RETURN(crypted_comm_pkt.data);
crypted_comm_pkt.length = 130;
memcpy(crypted_comm_pkt.data, raw_comm_pkt.data, 2);
aes_encrypt(&aes, raw_comm_pkt.length-2, crypted_comm_pkt.data+2, raw_comm_pkt.data+2);
sendto(sock, crypted_comm_pkt.data, crypted_comm_pkt.length, 0, (struct sockaddr *)&from, sizeof(from));
return ST_OK;
}
static DATA_BLOB decrypt_setup_packet(TALLOC_CTX *mem_ctx, DATA_BLOB encrypted_blob) {
const configuration *conf = get_conf();
mpz_t encrypted_data;
mpz_t decrypted_data;
DATA_BLOB decrypted_blob;
int pos;
size_t length = 1;
decrypted_blob.length = 258;
decrypted_blob.data = talloc_zero_array(mem_ctx, uint8_t, 258);
memcpy(decrypted_blob.data, encrypted_blob.data, 0x02);
for (pos = 0x02; pos < 258; pos += 128) {
/* Initialize the big numbers */
mpz_init(encrypted_data);
mpz_init(decrypted_data);
/* Do not decrypt the CRC and the connection ID */
mpz_import(encrypted_data, 1, 1, 128, 1, 0, encrypted_blob.data + pos);
rsa_compute_root(conf->private_key, decrypted_data, encrypted_data);
mpz_export(decrypted_blob.data + pos, &length, 1, 128, 1, 0, decrypted_data);
}
return decrypted_blob;
}
static DATA_BLOB decrypt_aes_packet(TALLOC_CTX *mem_ctx, DATA_BLOB encrypted_blob) {
static DATA_BLOB ret;
struct aes_ctx aes;
ret.length = encrypted_blob.length;
ret.data = talloc_zero_array(mem_ctx, uint8_t, ret.length);
memcpy(ret.data, encrypted_blob.data, 2);
aes_set_decrypt_key(&aes, 16, global_aes_key);
aes_decrypt(&aes, encrypted_blob.length-2, ret.data+2, encrypted_blob.data+2);
return ret;
}
int main (int argc, char **argv) {
int sock, n;
socklen_t fromlen;
struct sockaddr_in server;
struct sockaddr_in from;
TALLOC_CTX *mem_ctx;
STATUS rv;
FILE *pidfile;
pid_t pid;
const configuration *conf;
set_process_name(argv[0]);
/* Initialize a memory context */
mem_ctx = talloc_init("secipd");
NO_MEM_RETURN(mem_ctx);
/* Read the configuration file */
rv = read_configuration_file(mem_ctx);
if (rv != ST_OK)
return rv;
conf = get_conf();
/* Daemonize if we're not supposed to run in foreground mode */
if (!conf->foreground) {
fclose(stdin);
fclose(stdout);
fclose(stderr);
if ((pid = fork())) {
/* Write PID file */
pidfile = fopen(conf->pid_file, "w");
if (pidfile == NULL)
return ST_LOG_ERR;
fprintf(pidfile, "%d\n", pid);
fclose(pidfile);
return ST_OK;
}
}
/*
* Open up a UDP socket the configured port
*/
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
DEBUG(0, "Could not create socket in server");
return ST_SOCKET_FAILURE;
}
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(conf->secip_port);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
DEBUG(0, "Could not bind to socket during startup (socket in use?)!");
return ST_BIND_FAILURE;
}
read_rsa_keys();
DEBUG(0, "Started %s and waiting for SecIP packets on port %d",
get_process_name(), conf->secip_port);
/*
* Wait for packets
*/
fromlen = sizeof(struct sockaddr_in);
while (1) {
uint16_t src_port;
struct secip_setup_packet *setup_pkt;
struct secip_comm_packet *comm_pkt;
struct secip_packet *pkt;
char buf[1024]; /* Purposefully static length */
enum ndr_err_code ndr_err;
DATA_BLOB data;
pkt = talloc(mem_ctx, struct secip_packet);
NO_MEM_RETURN(pkt);
n = recvfrom(sock, &buf, sizeof(buf), 0, (struct sockaddr *) &from, &fromlen);
if (n < 0) {
DEBUG( 0, "Error when storing packet in buffer!");
continue;
} else if (n == sizeof(buf)) {
DEBUG(0, "Maximum packet size exceeded!");
continue;
}
src_port = ntohs(from.sin_port);
DEBUG(3, "Received packet with len %d from %u", n, src_port);
/* Copy packet to data blob */
data.length = n;
data.data = talloc_memdup(pkt, buf, n);
NO_MEM_RETURN(data.data);
if (*(uint16_t *)data.data < 0xFF00 && data.length > 256) {
data = decrypt_setup_packet(pkt, data);
if (data.length == 0) {
DEBUG(0, "RSA decryption failed, freeing up memory");
talloc_free(pkt);
continue;
}
} else if (*(uint16_t *)data.data < 0xFF00 && data.length > 128) {
data = decrypt_aes_packet(pkt, data);
if (data.length == 0) {
DEBUG(0, "AES decryption failed, freeing up memory");
talloc_free(pkt);
continue;
}
}
/* Parse the header */
if (data.length > 256) {
setup_pkt = talloc(pkt, struct secip_setup_packet);
NO_MEM_RETURN(setup_pkt);
ndr_err = ndr_pull_struct_blob_all(&data, pkt, setup_pkt, (ndr_pull_flags_fn_t)ndr_pull_secip_setup_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Could not parse this CRC packet");
}
DEBUG(10, "%s", ndr_print_struct_string(setup_pkt,(ndr_print_fn_t)ndr_print_secip_setup_packet, "setup packet", setup_pkt));
} else if (data.length > 128) {
comm_pkt = talloc(pkt, struct secip_comm_packet);
NO_MEM_RETURN(comm_pkt);
ndr_err = ndr_pull_struct_blob_all(&data, pkt, comm_pkt, (ndr_pull_flags_fn_t)ndr_pull_secip_comm_packet);
if (ndr_err != NDR_ERR_SUCCESS) {
DEBUG(0, "Could not parse this CRC packet");
}
DEBUG(10, "%s", ndr_print_struct_string(comm_pkt,(ndr_print_fn_t)ndr_print_secip_comm_packet, "comm packet", comm_pkt));
}
ndr_err = ndr_pull_struct_blob_all(&data, pkt, pkt, (ndr_pull_flags_fn_t)ndr_pull_secip_packet);
if (ndr_err != NDR_ERR_SUCCESS && ndr_err != NDR_ERR_UNREAD_BYTES) {
DEBUG(0, "Could not parse this packet: %s", ndr_map_error2string(ndr_err));
DEBUG(0, "%s", ndr_print_struct_string(pkt,(ndr_print_fn_t)ndr_print_secip_packet, "packet", pkt));
} else {
DEBUG(9, "%s", ndr_print_struct_string(pkt,(ndr_print_fn_t)ndr_print_secip_packet, "packet", pkt));
}
if (pkt->message_id == SECIP_MSG_ATE_ENC && pkt->msg.ate_enc.session_id == 0x0000) {
send_ppk_com(pkt, sock, from, pkt);
} else if (pkt->message_id == SECIP_MSG_PPK_REP) {
send_arc_enc(pkt, sock, from, pkt);
} else if (pkt->message_id == SECIP_MSG_PATH_SUPERVISION_REQUEST) {
send_psup_resp(pkt, sock, from, pkt);
} else if (pkt->message_id == SECIP_MSG_PATH_CHECK_REQUEST) {
send_pathcheck_resp(pkt, sock, from, pkt);
} else if (pkt->message_id == SECIP_MSG_ALARM) {
send_alarm_ack(pkt, sock, from, pkt);
} else if (pkt->message_id == SECIP_MSG_POLL_MESSAGE) {
send_poll_ack(pkt, sock, from, pkt);
}
talloc_free(pkt);
}
}

View file

@ -1,184 +0,0 @@
/*
SIA-HS Alarm Monitoring Service
Copyright (C) Wilco Baan Hofman <wilco@baanhofman.nl> 2013
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "database.h"
#include <signal.h>
#include <sys/wait.h>
static dbi_conn conn;
static void child_handler(int sig) {
pid_t pid;
int status;
/* EXTERMINATE! EXTERMINATE! */
while((pid = waitpid(-1, &status, WNOHANG)) > 0);
}
static void safe_forkexec(TALLOC_CTX *mem_ctx, const char *script_in, const char *prom, const char *code) {
char *script = talloc_strdup(mem_ctx, script_in);
char *argv[32];
unsigned int i, j;
argv[0] = script;
for (i = 0, j = 1; i < strlen(script) && j < 29; i++) {
if (script[i] == ' ') {
script[i] = '\0';
argv[j++] = &script[i+1];
}
}
argv[j++] = talloc_strdup(script, prom);
argv[j++] = talloc_strdup(script, code);
argv[j] = NULL;
DEBUG(4, "About to execute %s %s %s", script_in, prom, code);
if (!fork()) {
execv(argv[0], argv);
exit(0);
}
talloc_free(script);
}
STATUS spacestate_update(TALLOC_CTX *mem_ctx, const char *prom, const char *code, const char *description) {
bool must_close = 0;
bool must_open = 0;
const configuration *conf = get_conf();
STATUS result = ST_OK;
DEBUG(6, "Got event for spacestate: %s %s %s -- %s: %s\n", prom, code, description, sia_code_str(code), sia_code_desc(code));
if (strncmp(code, "CL", 2) == 0 ||
strncmp(code, "CA", 2) == 0 ||
strncmp(code, "CF", 2) == 0 ||
strncmp(code, "CJ", 2) == 0 ||
strncmp(code, "CK", 2) == 0 ||
strncmp(code, "CQ", 2) == 0 ||
strncmp(code, "CS", 2) == 0) {
must_close = 1;
}
if (strncmp(code, "OP", 2) == 0 ||
strncmp(code, "OA", 2) == 0 ||
strncmp(code, "OJ", 2) == 0 ||
strncmp(code, "OK", 2) == 0 ||
strncmp(code, "OQ", 2) == 0 ||
strncmp(code, "OS", 2) == 0) {
must_open = 1;
}
if (must_open) {
DEBUG(3, "Alarm disarmed. Updating space state override.");
result = proper_dbi_queryf(conn, "UPDATE space_state set override=0, override_state='open';");
safe_forkexec(mem_ctx, conf->spacestate_hook_open, prom, code);
} else if (must_close) {
DEBUG(3, "Alarm armed. Updating space state override.");
result = proper_dbi_queryf(conn, "UPDATE space_state set override=1, override_state='closed';");
safe_forkexec(mem_ctx, conf->spacestate_hook_close, prom, code);
}
if (result != ST_OK) {
return result;
}
return ST_OK;
}
STATUS spacestate_init(void)
{
configuration *conf = get_modifiable_conf();
GError *error = NULL;
struct sigaction sa;
dbi_inst dbi_instance = 0;
/* Establish SIGCHLD handler. */
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = child_handler;
sigaction(SIGCHLD, &sa, NULL);
conf->spacestate_host = g_key_file_get_string(conf->keyfile, "spacestate",
"host", &error);
if (error) {
fprintf(stderr, "No spacestate host supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->spacestate_name = g_key_file_get_string(conf->keyfile, "spacestate",
"name", &error);
if (error) {
fprintf(stderr, "No spacestate name supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->spacestate_driver = g_key_file_get_string(conf->keyfile, "spacestate",
"driver", &error);
if (error) {
fprintf(stderr, "No spacestate driver supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->spacestate_username = g_key_file_get_string(conf->keyfile, "spacestate",
"username", &error);
if (error) {
fprintf(stderr, "No spacestate username supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->spacestate_password = g_key_file_get_string(conf->keyfile, "spacestate",
"password", &error);
if (error) {
fprintf(stderr, "No spacestate password supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->spacestate_hook_open = g_key_file_get_string(conf->keyfile, "spacestate",
"open script", &error);
if (error) {
fprintf(stderr, "No spacestate password supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->spacestate_hook_close = g_key_file_get_string(conf->keyfile, "spacestate",
"close script", &error);
if (error) {
fprintf(stderr, "No spacestate password supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
conf->event_handlers = talloc_realloc(conf, conf->event_handlers, event_function, conf->event_handler_cnt+1);
conf->event_handlers[conf->event_handler_cnt] = spacestate_update;
conf->event_handler_cnt++;
DEBUG(1, "Setting properties to %s space state database %s at %s as user %s", conf->spacestate_driver,
conf->spacestate_name, conf->spacestate_host, conf->spacestate_username);
dbi_initialize_r(NULL, &dbi_instance);
conn = dbi_conn_new_r(conf->spacestate_driver, &dbi_instance);
dbi_conn_set_option(conn, "host", conf->spacestate_host);
dbi_conn_set_option(conn, "username", conf->spacestate_username);
dbi_conn_set_option(conn, "password", conf->spacestate_password);
dbi_conn_set_option(conn, "dbname", conf->spacestate_name);
dbi_conn_set_option(conn, "encoding", "UTF-8");
return ST_OK;
}

53
wscript
View file

@ -1,30 +1,5 @@
#! /usr/bin/env python
# encoding: utf-8
from waflib.Task import Task
from waflib.TaskGen import extension
class idl_header(Task):
run_str = '../bin/pidl/pidl --header ${TGT[0].abspath()} ${SRC}'
color = 'BLUE'
ext_out = ['.h']
class idl_parser(Task):
run_str = '../bin/pidl/pidl --ndr-parser ${TGT[0].abspath()} ${SRC}'
color = 'BLUE'
ext_out = ['.h']
@extension('.idl')
def process_idl(self, node):
header_node = node.change_ext('.h')
self.create_task('idl_header', node, [header_node ])
c_node = node.change_ext('.c')
if c_node.name[:len('ndr_')] != 'ndr_':
c_node.name = 'ndr_' + c_node.name
self.create_task('idl_parser', node, [ c_node ])
self.source.append(c_node)
def dist(ctx):
ctx.base_name = 'siahsd'
@ -45,18 +20,9 @@ def configure(conf):
args=['--cflags', '--libs' ])
# Check for tevent
conf.check_cfg(package='tevent', uselib_store='samba',
conf.check_cfg(package='tevent', uselib_store='tevent',
args=['--cflags', '--libs' ])
# Check for samba-4.0
conf.check_cfg(package='samba-util', uselib_store='samba',
args=['--cflags', '--libs' ])
# Check for ndr
conf.check_cfg(package='ndr', uselib_store='samba',
args=['--cflags', '--libs'])
# Check for headers
conf.check(header_name='stdio.h', features='c cprogram')
conf.check(header_name='stdlib.h', features='c cprogram')
@ -72,20 +38,13 @@ def configure(conf):
conf.check(header_name='fcntl.h', features='c cprogram')
conf.check(header_name='errno.h', features='c cprogram')
# Used libraries
conf.check(header_name='talloc.h', use='samba', features='c cprogram')
conf.check(header_name='glib.h', use='glib-2.0', features='c cprogram')
conf.check(header_name='dbi/dbi.h', features='c cprogram')
conf.check(header_name='util/data_blob.h', use='samba', features='c cprogram')
#conf.check(header_name='core/ntstatus.h', use='samba', features='c cprogram')
#conf.check(header_name='charset.h', use='samba', features='c cprogram')
conf.check_cc(lib='dbi', uselib_store='dbi')
conf.check_cc(lib='talloc', uselib_store='samba')
conf.check_cc(lib='ndr', uselib_store='ndr')
conf.check_cc(lib='gmp', uselib_store='nettle')
conf.check_cc(lib='hogweed', uselib_store='nettle')
conf.check_cc(lib='nettle', uselib_store='nettle')
@ -110,15 +69,5 @@ def build(bld):
target = 'siahsd',
use = [ 'database', 'config', 'status', 'sia', 'siahs', 'jsonbot', 'hook_script', 'dbi', 'talloc', 'glib-2.0', 'nettle' ])
bld.program(
source = 'secip.idl secipd.c crc16.c',
target = 'secipd',
use = [ 'database', 'config', 'status', 'sia', 'siahs', 'jsonbot', 'hook_script', 'dbi', 'samba', 'glib-2.0', 'nettle', 'ndr' ])
bld.program(
source = 'chiron.idl chirond.c',
target = 'chirond',
use = [ 'database', 'config', 'status', 'sia', 'jsonbot', 'dbi', 'samba', 'glib-2.0', 'nettle', 'ndr' ])
pass
def clean(ctx):
pass