diff --git a/chiron-2nd.log b/chiron-2nd.log deleted file mode 100644 index d956cbe..0000000 --- a/chiron-2nd.log +++ /dev/null @@ -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 diff --git a/chiron-initial.log b/chiron-initial.log deleted file mode 100644 index 9d4b781..0000000 --- a/chiron-initial.log +++ /dev/null @@ -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...-. diff --git a/chiron.idl b/chiron.idl deleted file mode 100644 index 1ce8ccd..0000000 --- a/chiron.idl +++ /dev/null @@ -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; - -} diff --git a/chirond.c b/chirond.c deleted file mode 100644 index 833dec9..0000000 --- a/chirond.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - Chiron IP Alarm Monitoring Service - Copyright (C) Wilco Baan Hofman 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 . -*/ -#include "includes.h" -#include "build/ndr_chiron.h" -#include "build/chiron.h" -#include -#include - -#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; -} diff --git a/crc16.c b/crc16.c deleted file mode 100644 index 1f6e068..0000000 --- a/crc16.c +++ /dev/null @@ -1,20 +0,0 @@ -#include - -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; -} diff --git a/crc16.h b/crc16.h deleted file mode 100644 index 866de6d..0000000 --- a/crc16.h +++ /dev/null @@ -1,2 +0,0 @@ - -uint16_t calculate_crc (const uint8_t *ptr, uint16_t count); diff --git a/secip.idl b/secip.idl deleted file mode 100644 index 0c38bfe..0000000 --- a/secip.idl +++ /dev/null @@ -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; -}; diff --git a/secipd.c b/secipd.c deleted file mode 100644 index 301b842..0000000 --- a/secipd.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - Vebon Sec-IP Alarm Monitoring Service - Copyright (C) Wilco Baan Hofman 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 . -*/ -#include - -#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); - } -} diff --git a/spacestate.c b/spacestate.c deleted file mode 100644 index 2b8fc18..0000000 --- a/spacestate.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - SIA-HS Alarm Monitoring Service - Copyright (C) Wilco Baan Hofman 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 . -*/ -#include "includes.h" -#include "database.h" -#include -#include - -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; -} diff --git a/wscript b/wscript index c543104..0d3b72d 100644 --- a/wscript +++ b/wscript @@ -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