Remove non-siahsd sources
These fail to compile and are not required for the space.
This commit is contained in:
parent
02a670fc49
commit
c09d87c6e4
10 changed files with 1 additions and 2168 deletions
104
chiron-2nd.log
104
chiron-2nd.log
|
@ -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
|
|
|
@ -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...-.
|
|
133
chiron.idl
133
chiron.idl
|
@ -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
771
chirond.c
|
@ -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
20
crc16.c
|
@ -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;
|
|
||||||
}
|
|
2
crc16.h
2
crc16.h
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
uint16_t calculate_crc (const uint8_t *ptr, uint16_t count);
|
|
164
secip.idl
164
secip.idl
|
@ -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
627
secipd.c
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
184
spacestate.c
184
spacestate.c
|
@ -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
53
wscript
|
@ -1,30 +1,5 @@
|
||||||
#! /usr/bin/env python
|
#! /usr/bin/env python
|
||||||
# encoding: utf-8
|
# 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):
|
def dist(ctx):
|
||||||
ctx.base_name = 'siahsd'
|
ctx.base_name = 'siahsd'
|
||||||
|
@ -45,18 +20,9 @@ def configure(conf):
|
||||||
args=['--cflags', '--libs' ])
|
args=['--cflags', '--libs' ])
|
||||||
|
|
||||||
# Check for tevent
|
# Check for tevent
|
||||||
conf.check_cfg(package='tevent', uselib_store='samba',
|
conf.check_cfg(package='tevent', uselib_store='tevent',
|
||||||
args=['--cflags', '--libs' ])
|
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
|
# Check for headers
|
||||||
conf.check(header_name='stdio.h', features='c cprogram')
|
conf.check(header_name='stdio.h', features='c cprogram')
|
||||||
conf.check(header_name='stdlib.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='fcntl.h', features='c cprogram')
|
||||||
conf.check(header_name='errno.h', features='c cprogram')
|
conf.check(header_name='errno.h', features='c cprogram')
|
||||||
|
|
||||||
|
|
||||||
# Used libraries
|
# Used libraries
|
||||||
conf.check(header_name='talloc.h', use='samba', features='c cprogram')
|
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='glib.h', use='glib-2.0', features='c cprogram')
|
||||||
|
|
||||||
conf.check(header_name='dbi/dbi.h', 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='dbi', uselib_store='dbi')
|
||||||
conf.check_cc(lib='talloc', uselib_store='samba')
|
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='hogweed', uselib_store='nettle')
|
||||||
conf.check_cc(lib='nettle', uselib_store='nettle')
|
conf.check_cc(lib='nettle', uselib_store='nettle')
|
||||||
|
|
||||||
|
@ -110,15 +69,5 @@ def build(bld):
|
||||||
target = 'siahsd',
|
target = 'siahsd',
|
||||||
use = [ 'database', 'config', 'status', 'sia', 'siahs', 'jsonbot', 'hook_script', 'dbi', 'talloc', 'glib-2.0', 'nettle' ])
|
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):
|
def clean(ctx):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue