source: trunk/module-gbox.c @ 5375

Last change on this file since 5375 was 5348, checked in by schlocke, 8 years ago

changed locking behaviour on dns resolving, gethostbyname=mutexlock,
getaddrinfo=no mutex lock

  • Property svn:mime-type set to text/plain
File size: 26.8 KB
Line 
1#include "globals.h"
2#ifdef MODULE_GBOX
3#include <pthread.h>
4//#define _XOPEN_SOURCE 600
5#include <semaphore.h>
6#include <time.h>
7#include <sys/time.h>
8
9#include "module-datastruct-llist.h"
10#include "algo/minilzo.h"
11
12enum {
13  MSG_ECM = 0x445c,
14  MSG_CW = 0x4844,
15  MSG_HELLO = 0xddab,
16  MSG_CHECKCODE = 0x41c0,
17  MSG_GOODBYE = 0x9091,
18  MSG_GSMS_ACK = 0x9098,
19  MSG_GSMS = 0xff0,
20  MSG_BOXINFO = 0xa0a1
21};
22
23struct gbox_card {
24  uint16_t peer_id;
25  uint32_t provid;
26  int32_t slot;
27  int32_t dist;
28  int32_t lvl;
29};
30
31struct gbox_peer {
32  uint16_t id;
33  uchar key[4];
34  uchar ver;
35  uchar type;
36  LLIST *cards;
37  uchar checkcode[7];
38  uchar *hostname;
39  int32_t online;
40  int32_t fail_count;
41  int32_t hello_count;
42};
43
44struct gbox_data {
45  uint16_t id;
46  uchar checkcode[7];
47  uchar key[4];
48  uchar ver;
49  uchar type;
50  int32_t ecm_idx;
51  int32_t hello_expired;
52  int32_t hello_initial;
53  uchar cws[16];
54  struct gbox_peer peer;
55  pthread_mutex_t lock;
56  uchar buf[1024];
57  sem_t sem;
58  LLIST *local_cards;
59};
60
61struct gbox_ecm_info {
62  uint16_t peer,
63           extra;
64  uchar version,
65        type,
66        slot,
67        unknwn1,
68        unknwn2,
69        ncards;
70  uchar checksums[14];
71};
72
73static const uchar sbox[] = {
74  0x25, 0x38, 0xd4, 0xcd, 0x17, 0x7a, 0x5e, 0x6c,
75  0x52, 0x42, 0xfe, 0x68, 0xab, 0x3f, 0xf7, 0xbe,
76  0x47, 0x57, 0x71, 0xb0, 0x23, 0xc1, 0x26, 0x6c,
77  0x41, 0xce, 0x94, 0x37, 0x45, 0x04, 0xa2, 0xea,
78  0x07, 0x58, 0x35, 0x55, 0x08, 0x2a, 0x0f, 0xe7,
79  0xac, 0x76, 0xf0, 0xc1, 0xe6, 0x09, 0x10, 0xdd,
80  0xc5, 0x8d, 0x2e, 0xd9, 0x03, 0x9c, 0x3d, 0x2c,
81  0x4d, 0x41, 0x0c, 0x5e, 0xde, 0xe4, 0x90, 0xae
82};
83
84#pragma GCC diagnostic ignored "-Wunused-parameter"
85static void gbox_encrypt_stage1(uchar *buf, int32_t l, uchar *key)
86{
87  int32_t i;
88
89  for (i = 31; i >= 0; i--) {
90    uchar tmp;
91
92    tmp = key[3];
93    int32_t j;
94    for (j = 3; j > 0; j--)
95      key[j] = (key[j - 1] << 7) + (key[j] >> 1);
96    key[0] = (tmp << 7) + (key[0] >> 1);
97
98    buf[i + 1 - ((i + 1) & 0xf8)] += sbox[((key[i + 1 - ((i + 1) & 0xfc)] ^ buf[i - (i & 0xf8)]) >> 2) & 0x3f] * 2;
99    buf[i + 1 - ((i + 1) & 0xf8)] ^= sbox[(buf[i - (i & 0xf8)] - key[i + 1 - ((i + 1) & 0xfc)]) & 0x3f];
100    buf[i + 1 - ((i + 1) & 0xf8)] += key[i - (i & 0xfc)];
101  }
102}
103
104static void gbox_encrypt_stage2(uchar *buf, int32_t l, uchar *key)
105{
106  int32_t i, j;
107
108  for (i = 0; i < 4; i++)
109    for (j = 7; j >= 0; j--) {
110      uchar tmp;
111
112      tmp = key[3];
113      int32_t k;
114      for (k = 3; k > 0; k--)
115        key[k] = (key[k - 1] << 7) + (key[k] >> 1);
116      key[0] = (tmp << 7) + (key[0] >> 1);
117
118      buf[(j + 1) & 7] -= sbox[(buf[j] >> 2) & 0x3f];
119      buf[(j + 1) & 7] ^= sbox[(buf[j] - key[(j + 1) & 3]) & 0x3f];
120      buf[(j + 1) & 7] -= key[j & 3];
121    }
122}
123
124static void gbox_decrypt_stage1(uchar *buf, int32_t l, uchar *key)
125{
126  int32_t i;
127
128  for (i = 0; i < 32; i++) {
129    uchar tmp;
130
131    buf[i + 1 - ((i + 1) & 0xf8)] -= key[i - (i & 0xfc)];
132    buf[i + 1 - ((i + 1) & 0xf8)] ^= sbox[(buf[i - (i & 0xf8)] - key[i + 1 - ((i + 1) & 0xfc)]) & 0x3f];
133    buf[i + 1 - ((i + 1) & 0xf8)] -= sbox[((key[i + 1 - ((i + 1) & 0xfc)] ^ buf[i - (i & 0xf8)]) >> 2) & 0x3f] * 2;
134
135    tmp = key[0];
136    int32_t j;
137    for (j = 0; j < 3; j++)
138      key[j] = ((key[j + 1] & 0x80) >> 7) + (key[j] * 2);
139    key[3] = ((tmp & 0x80) >> 7) + (key[3] * 2);
140  }
141}
142
143static void gbox_decrypt_stage2(uchar *buf, int32_t l, uchar *key)
144{
145  int32_t i, j;
146
147  for (i = 3; i >= 0; i--)
148    for (j = 0; j < 8; j++) {
149      uchar tmp;
150
151      buf[(j + 1) & 7] += key[j & 3];
152      buf[(j + 1) & 7] ^= sbox[(buf[j] - key[(j + 1) & 3]) & 0x3f];
153      buf[(j + 1) & 7] += sbox[(buf[j] >> 2) & 0x3f];
154
155      tmp = key[0];
156      int32_t k;
157      for (k = 0; k < 3; k++)
158        key[k] = ((key[k + 1] & 0x80) >> 7) + (key[k] * 2);
159      key[3] = ((tmp & 0x80) >> 7) + (key[3] * 2);
160    }
161}
162
163static void gbox_encrypt(uchar *buf, int32_t l, uchar *key)
164{
165  int32_t i;
166  uchar tmp_key[4];
167
168  memcpy(tmp_key, key, 4);
169
170  gbox_encrypt_stage1(buf, l, tmp_key);
171
172  for (i = 0; i < l - 2; i++)
173    buf[i] ^= buf[i + 1];
174
175  gbox_encrypt_stage2(buf, l, tmp_key);
176  gbox_decrypt_stage2(buf + l - 9, 9, tmp_key);
177}
178
179static void gbox_decrypt(uchar *buf, int32_t l, uchar *key)
180{
181  uchar tmp_key[4];
182
183  memcpy(tmp_key, key, 4);
184
185  gbox_encrypt_stage2(buf + l - 9, 9, tmp_key);
186  gbox_decrypt_stage2(buf, l, tmp_key);
187
188  int32_t i;
189  for (i = l - 2; i >= 0; i--) {
190    buf[i] ^= buf[i + 1];
191}
192
193  gbox_decrypt_stage1(buf, l, tmp_key);
194}
195
196static void gbox_compress(struct gbox_data *gbox, uchar *buf, int32_t unpacked_len, int32_t *packed_len)
197{
198  unsigned char *tmp, *tmp2;
199  *packed_len = 0;
200  if(!cs_malloc(&tmp,0x40000, -1)) return;
201    if(!cs_malloc(&tmp2,0x40000, -1)){
202        free(tmp);
203        return;
204    }
205
206  unpacked_len -= 12;
207  memcpy(tmp2, buf + 12, unpacked_len);
208
209  lzo_init();
210
211  lzo_voidp wrkmem;
212  if(!cs_malloc(&tmp2,unpacked_len * 0x1000, -1)){
213        free(tmp);
214        free(tmp2);
215        return;
216    }
217  cs_debug_mask(D_READER, "gbox: wrkmem = %p", wrkmem);
218  lzo_uint pl = 0;
219  if (lzo1x_1_compress(tmp2, unpacked_len, tmp, &pl, wrkmem) != LZO_E_OK)
220    cs_log("gbox: compression failed!");
221
222  memcpy(buf + 12, tmp, pl);
223  pl += 12;
224
225  free(tmp);
226  free(tmp2);
227  free(wrkmem);
228
229  *packed_len = pl;
230}
231
232static void gbox_decompress(struct gbox_data *gbox, uchar *buf, int32_t *unpacked_len)
233{
234  uchar tmp[2048];
235
236  int32_t len = buf[12] - 13;
237
238  lzo_init();
239  if (lzo1x_decompress(buf + 12, len, tmp, (lzo_uint *)unpacked_len, NULL) != LZO_E_OK)
240    cs_debug_mask(D_READER, "gbox: decompression failed!");
241
242  memcpy(buf + 12, tmp, *unpacked_len);
243  *unpacked_len += 12;
244}
245
246static int32_t gbox_decode_cmd(uchar *buf)
247{
248  return buf[0] << 8 | buf[1];
249}
250
251void gbox_code_cmd(uchar *buf, int16_t cmd)
252{
253  buf[0] = cmd >> 8;
254  buf[1] = cmd & 0xff;
255}
256
257static void gbox_calc_checkcode(struct gbox_data *gbox)
258{
259  memcpy(gbox->checkcode, "\x15\x30\x2\x4\x19\x19\x66", 7); /* no local cards */
260
261  int32_t slot = 0;
262
263  // for all local cards do:
264  LL_ITER it = ll_iter_create(gbox->local_cards);
265  struct gbox_card *card;
266  while ((card = ll_iter_next(&it))) {
267    gbox->checkcode[0] ^= card->provid >> 24;
268    gbox->checkcode[1] ^= card->provid >> 16;
269    gbox->checkcode[2] ^= card->provid >> 8;
270    gbox->checkcode[3] ^= card->provid & 0xff;
271    gbox->checkcode[4] = ++slot;
272    gbox->checkcode[5] = gbox->peer.id >> 8;
273    gbox->checkcode[6] = gbox->peer.id & 0xff;
274  }
275}
276
277uint32_t gbox_get_ecmchecksum(ECM_REQUEST *er)
278{
279
280  uint8_t checksum[4];
281  int32_t counter;
282
283  uchar ecm[255];
284  memcpy(ecm, er->ecm, er->l);
285
286  checksum[3] = ecm[0];
287  checksum[2] = ecm[1];
288  checksum[1] = ecm[2];
289  checksum[0] = ecm[3];
290
291  for (counter=1; counter < (er->l/4) - 4; counter++) {
292    checksum[3] ^= ecm[counter*4];
293    checksum[2] ^= ecm[counter*4+1];
294    checksum[1] ^= ecm[counter*4+2];
295    checksum[0] ^= ecm[counter*4+3];
296  }
297
298  return checksum[3] << 24 | checksum[2] << 16 | checksum[1] << 8 | checksum[0];
299}
300
301/*
302static void gbox_handle_gsms(uint16_t peerid, char *gsms)
303{
304    cs_log("gbox: gsms received from peer %04x: %s", peerid, gsms);
305
306    if (strlen(cfg.gbox_gsms_path)) {
307        FILE *f = fopen(cfg.gbox_gsms_path, "a");
308        if (f) {
309            f//printf(f, "FROM %04X: %s\n", peerid, gsms);
310            fclose(f);
311        }
312        else
313            cs_log("gbox: error writing to file! (path=%s)", cfg.gbox_gsms_path);
314    }
315}
316*/
317
318static void gbox_expire_hello(struct s_client *cli)
319{
320  //printf("gbox: enter gbox_expire_hello()\n");
321  struct gbox_data *gbox = cli->gbox;
322
323  sem_t sem;
324  sem_init(&sem, 0 , 1);
325
326  struct timespec ts;
327  struct timeval tv;
328  gettimeofday(&tv, NULL);
329  ts.tv_sec = tv.tv_sec;
330  ts.tv_nsec = tv.tv_usec * 1000;
331  ts.tv_sec += 5;
332
333  sem_wait(&sem);
334  if (sem_timedwait(&sem, &ts) == -1) {
335    if (errno == ETIMEDOUT) {
336      //printf("gbox: hello expired!\n");
337      gbox->hello_expired = 0;
338    }
339  }
340
341  //printf("gbox: exit gbox_expire_hello()\n");
342}
343
344static void gbox_wait_for_response(struct s_client *cli)
345{
346    //printf("gbox: enter gbox_wait_for_response()\n");
347    //cs_debug_mask(D_READER, "gbox: enter gbox_wait_for_response()");
348    struct gbox_data *gbox = cli->gbox;
349    struct timespec ts;
350    struct timeval tv;
351    gettimeofday(&tv, NULL);
352    ts.tv_sec = tv.tv_sec;
353    ts.tv_nsec = tv.tv_usec * 1000;
354    ts.tv_sec += 5;
355
356    //sem_wait(&gbox->sem);
357    if (sem_timedwait(&gbox->sem, &ts) == -1) {
358        if (errno == ETIMEDOUT) {
359            gbox->peer.fail_count++;
360            //printf("gbox: sem wait timed-out, fail_count=%d\n", gbox->peer.fail_count);
361#define GBOX_FAIL_COUNT 1
362            if (gbox->peer.fail_count >= GBOX_FAIL_COUNT) {
363                gbox->peer.online = 0;
364                //printf("gbox: fail_count >= %d, peer is offline\n", GBOX_FAIL_COUNT);
365            }
366            //cs_debug_mask(D_READER, "gbox: sem wait timed-out, fail_count=%d\n", gbox->peer.fail_count);
367        }
368    } else {
369        gbox->peer.fail_count = 0;
370        //printf("gbox: sem posted, peer is online\n");
371    }
372    //cs_debug_mask(D_READER, "gbox: sem posted, peer is online");
373
374    //cs_debug_mask(D_READER, "gbox: exit gbox_wait_for_response()");
375    //printf("gbox: exit gbox_wait_for_response()\n");
376}
377
378static void gbox_send(struct s_client *cli, uchar *buf, int32_t l)
379{
380  struct gbox_data *gbox = cli->gbox;
381
382  cs_ddump_mask(D_READER, buf, l, "gbox: decrypted data sent (%d bytes):", l);
383  cs_ddump_mask(D_READER, gbox->key, 4, "gbox: key before encrypt:");
384
385  gbox_encrypt(buf, l, gbox->peer.key);
386  sendto(cli->udp_fd, buf, l, 0, (struct sockaddr *)&cli->udp_sa, sizeof(cli->udp_sa));
387
388  cs_ddump_mask(D_READER, gbox->key, 4, "gbox: key after encrypt:");
389  cs_ddump_mask(D_READER, buf, l, "gbox: encrypted data sent (%d bytes):", l);
390
391  pthread_t t;
392  pthread_create(&t, NULL, (void *)gbox_wait_for_response, cli);
393}
394
395static void gbox_send_boxinfo(struct s_client *cli)
396{
397  struct gbox_data *gbox = cli->gbox;
398
399  int32_t len;
400  uchar buf[256];
401
402  int32_t hostname_len = strlen(cfg.gbox_hostname);
403
404  gbox_code_cmd(buf, MSG_BOXINFO);
405  memcpy(buf + 2, gbox->peer.key, 4);
406  memcpy(buf + 6, gbox->key, 4);
407  buf[10] = gbox->peer.ver;
408  buf[11] = 0x10;
409  memcpy(buf + 12, cfg.gbox_hostname, hostname_len);
410
411  len = 12 + hostname_len;
412
413  // TODO fix this! gbox_send(cli, buf, len);
414}
415
416/*
417static void gbox_send_goodbye(struct s_client *cli)
418{
419  struct gbox_data *gbox = cli->gbox;
420
421 uchar buf[20];
422
423 gbox_code_cmd(buf, MSG_GOODBYE);
424 memcpy(buf + 2, gbox->peer.key, 4);
425 memcpy(buf + 6, gbox->key, 4);
426
427 cs_debug_mask(D_READER, "gbox: send goodbye:", cs_hexdump(0, buf, 10));
428
429 gbox_send(cli, buf, 11);
430}*/
431
432static void gbox_send_hello(struct s_client *cli)
433{
434  struct gbox_data *gbox = cli->gbox;
435
436  // TODO build local card list
437  if (!gbox->local_cards)
438    gbox->local_cards = ll_create();
439  else
440    ll_clear_data(gbox->local_cards);
441
442  // currently this will only work for initialised local cards or single remote cards
443  struct s_client *cl;
444  for (cl=first_client; cl; cl=cl->next) {
445    struct s_reader *rdr = cl->reader;
446    if (rdr) {
447      if (rdr->card_status == CARD_INSERTED) {
448        int32_t i;
449        for (i = 0; i < rdr->nprov; i++) {
450          struct gbox_card *c;
451          if(!cs_malloc(&c,sizeof(struct gbox_card), -1)) continue;
452          c->provid = rdr->caid << 16 | rdr->prid[i][0] << 8 | rdr->prid[i][1];
453          ll_append(gbox->local_cards, c);
454        }
455      }
456    }
457  }
458
459  int32_t len;
460  uchar buf[4096];
461
462  int32_t hostname_len = strlen(cfg.gbox_hostname);
463
464  len = 22 + hostname_len + ll_count(gbox->local_cards) * 9;
465
466  memset(buf, 0, sizeof(buf));
467
468  gbox_code_cmd(buf, MSG_HELLO);
469  memcpy(buf + 2, gbox->peer.key, 4);
470  memcpy(buf + 6, gbox->key, 4);
471  buf[10] = gbox->hello_initial ^ 1;  // initial HELLO = 0, subsequent = 1
472  buf[11] = 0x80;    // TODO this needs adjusting to allow for packet splitting
473
474  uchar *ptr = buf + 11;
475
476  int8_t slot = 0;
477  LL_ITER it = ll_iter_create(gbox->local_cards);
478  struct gbox_card *card;
479  while ((card = ll_iter_next(&it))) {
480    card->slot = ++slot;
481    *(++ptr) = card->provid >> 24;
482    *(++ptr) = card->provid >> 16;
483    *(++ptr) = card->provid >> 8;
484    *(++ptr) = card->provid & 0xff;
485    *(++ptr) = 1;
486    *(++ptr) = card->slot;
487    *(++ptr) = 0x41;  // TODO card->lvl << 4 | card->dist & 0xf
488    *(++ptr) = gbox->id >> 8;
489    *(++ptr) = gbox->id & 0xff;
490  }
491
492  gbox_calc_checkcode(gbox);
493  memcpy(++ptr, gbox->checkcode, 7);
494  ptr += 7;
495  *ptr = 0x73;
496  *(++ptr) = 0x10;
497  memcpy(++ptr, cfg.gbox_hostname, hostname_len);
498  *(ptr + hostname_len) = hostname_len;
499
500  cs_ddump_mask(D_READER, buf, len, "send hello (len=%d):", len);
501
502  gbox_compress(gbox, buf, len, &len);
503
504  cs_ddump_mask(D_READER, buf, len, "send hello, compressed (len=%d):", len);
505
506  if (++gbox->peer.hello_count == 2) gbox->peer.hello_count = 0;
507  gbox->hello_initial = 0;
508
509  gbox_send(cli, buf, len);
510}
511
512static int32_t gbox_recv(struct s_client *cli, uchar *b, int32_t l)
513{
514  struct gbox_data *gbox = cli->gbox;
515
516  if (!gbox)
517      return -1;
518
519  uchar *data = gbox->buf;
520  int32_t n;
521
522  sem_post(&gbox->sem);
523  gbox->peer.online = 1;
524
525  cs_lock(&gbox->lock);
526
527  uint32_t r_addr_len = 0;
528  struct sockaddr_in r_addr;
529  if ((n = recvfrom(cli->udp_fd, data, sizeof(gbox->buf), 0, (struct sockaddr *)&r_addr, &r_addr_len)) < 8) {
530      cs_log("gbox: invalid recvfrom!!!");
531        cs_unlock(&gbox->lock);
532        return -1;
533  }
534
535  cs_ddump_mask(D_READER, data, n, "gbox: encrypted data recvd (%d bytes):", n);
536  cs_ddump_mask(D_READER, gbox->key, 4, "gbox: key before decrypt:");
537
538  gbox_decrypt(data, n, gbox->key);
539
540  cs_ddump_mask(D_READER, gbox->key, 4, "gbox: key after decrypt:");
541  cs_ddump_mask(D_READER, data, n, "gbox: decrypted data recvd (%d bytes):", n);
542
543  memcpy(b, data, l);
544
545  if (!memcmp(data + 2, gbox->key, 4)) {
546      if (memcmp(data + 6, gbox->peer.key, 4) && gbox_decode_cmd(data) != MSG_CW) {
547          cs_log("gbox: INTRUDER ALERT (peer key)!");
548
549          cs_add_violation((uint)cli->ip);
550
551          cs_unlock(&gbox->lock);
552          return -1;
553      }
554  } else {
555    cs_log("gbox: INTRUDER ALERT!");
556
557    cs_add_violation((uint)cli->ip);
558
559    cs_unlock(&gbox->lock);
560      return -1;
561  }
562
563  switch (gbox_decode_cmd(data)) {
564    case MSG_HELLO:
565      {
566        static int32_t exp_seq = 0;
567
568        int32_t ip_clien_gbox = cs_inet_addr(cli->reader->device);
569        cli->ip = ip_clien_gbox;
570        gbox->peer.online = 1;
571
572        int32_t payload_len = n;
573
574        gbox_decompress(gbox, data, &payload_len);
575        cs_ddump_mask(D_READER, data, payload_len, "gbox: decompressed data (%d bytes):", payload_len);
576
577        if (!data[10])
578          gbox->hello_expired = 1;
579
580        int32_t seqno = data[11] & 0x7f;
581        int32_t final = data[11] & 0x80;
582
583        int32_t ncards_in_msg = 0;
584
585        if (seqno != exp_seq) return -1;
586
587        int32_t orig_card_count = ll_count(gbox->peer.cards);
588
589        if (seqno == 0) {
590          exp_seq++;
591
592          if (gbox->peer.cards) ll_destroy_data(gbox->peer.cards);
593          gbox->peer.cards = ll_create();
594
595          int32_t checkcode_len = 7;
596          int32_t hostname_len = data[payload_len - 1];
597          int32_t footer_len = hostname_len + 2;
598
599          // add cards to card list
600          uchar *ptr = data + 12;
601          while (ptr < data + payload_len - footer_len - checkcode_len - 1) {
602            uint32_t provid = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
603            int32_t ncards = ptr[4];
604
605            ptr += 5;
606
607            int32_t i;
608            for (i = 0; i < ncards; i++) {
609              struct gbox_card *card;
610              if(!cs_malloc(&card,sizeof(struct gbox_card), -1)) continue;
611
612              card->provid = provid;
613              card->slot = ptr[0];
614              card->dist = ptr[1] & 0xf;
615              card->lvl = ptr[1] >> 4;
616              card->peer_id = ptr[2] << 8 | ptr[3];
617
618              ptr += 4;
619
620              ll_append(gbox->peer.cards, card);
621
622              ncards_in_msg++;
623
624              cs_debug_mask(D_READER, "   card: provid=%08x, slot=%d, level=%d, dist=%d, peer=%04x", card->provid, card->slot, card->lvl, card->dist, card->peer_id);
625
626              cli->reader->tcp_connected = 2; //we have card
627              cli->reader->card_status = CARD_INSERTED;
628            }
629          }
630
631          NULLFREE(gbox->peer.hostname);
632          if(!cs_malloc(&gbox->peer.hostname,hostname_len + 1, -1)){
633            cs_unlock(&gbox->lock);
634            return -1;
635          }
636          memcpy(gbox->peer.hostname, data + payload_len - 1 - hostname_len, hostname_len);
637          gbox->peer.hostname[hostname_len] = '\0';
638
639          memcpy(gbox->peer.checkcode, data + payload_len - footer_len - checkcode_len - 1, checkcode_len);
640          gbox->peer.ver = data[payload_len - footer_len - 1];
641          gbox->peer.type = data[payload_len - footer_len];
642        } else {
643          // add cards to card list
644          uchar *ptr = data + 12;
645          while (ptr < data + payload_len - 1) {
646            uint32_t provid = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
647            int32_t ncards = ptr[4];
648
649            ptr += 5;
650
651            int32_t i;
652            for (i = 0; i < ncards; i++) {
653              struct gbox_card *card;
654              if(!cs_malloc(&card,sizeof(struct gbox_card), -1)) continue;
655
656              card->provid = provid;
657              card->slot = ptr[0];
658              card->dist = ptr[1] & 0xf;
659              card->lvl = ptr[1] >> 4;
660              card->peer_id = ptr[2] << 8 | ptr[3];
661
662              ptr += 4;
663
664              ll_append(gbox->peer.cards, card);
665
666              ncards_in_msg++;
667
668              cs_debug_mask(D_READER, "   card: provid=%08x, slot=%d, level=%d, dist=%d, peer=%04x", card->provid, card->slot, card->lvl, card->dist, card->peer_id);
669            }
670          }
671        }
672
673        if (final) exp_seq = 0;
674        // write_sahre_info() // TODO
675
676        cs_log("gbox: received hello %d%s, %d providers from %s, version=2.%02X, checkcode=%s",
677                seqno, final ? " (final)" : "", ncards_in_msg, gbox->peer.hostname, gbox->peer.ver, cs_hexdump(0, gbox->peer.checkcode, 7));
678
679        if (!ll_count(gbox->peer.cards))
680              cli->reader->tcp_connected = 1;
681
682        if (orig_card_count != ll_count(gbox->peer.cards))
683          gbox->hello_expired = 1;
684
685        if (final) {
686          if (gbox->hello_expired) {
687            gbox->hello_expired = 0;
688            gbox_send_hello(cli);
689
690            pthread_t t;
691            pthread_create(&t, NULL, (void *)gbox_expire_hello, cli);
692          }
693          gbox_send_boxinfo(cli);
694        }
695      }
696      break;
697    case MSG_BOXINFO:
698      gbox_send_hello(cli);
699      break;
700    case MSG_CW:
701        memcpy(gbox->cws, data + 14, 16);
702
703        cs_debug_mask(D_READER, "gbox: received cws=%s, peer=%04x, ecm_pid=%d, sid=%d",
704            cs_hexdump(0, gbox->cws, 16), data[10] << 8 | data[11], data[6] << 8 | data[7], data[8] << 8 | data[9]);
705        break;
706    case MSG_CHECKCODE:
707        memcpy(gbox->peer.checkcode, data + 10, 7);
708        cs_debug_mask(D_READER, "gbox: received checkcode=%s",  cs_hexdump(0, gbox->peer.checkcode, 7));
709        break;
710    /*case MSG_GSMS: // TODO
711        //gbox_handle_gsms(peerid, gsms);
712        break;
713        */
714    case MSG_ECM: //TODO:
715    {
716      // TODO: This is !!DIRTY!!
717      cli->typ = 'c';
718      cli->ctyp = 6;
719
720      struct s_auth *account;
721      int32_t ok=0;
722      for (ok=0, account=cfg.account; (account) && (!ok); account=account->next)
723        if( (ok=!strcmp(cli->reader->r_usr, account->usr)) )
724          break;
725      cs_auth_client(cli, ok ? account : (struct s_auth *)(-1), "gbox");
726
727      ECM_REQUEST *er = get_ecmtask();
728
729      struct gbox_ecm_info *ei;
730      if(!cs_malloc(&ei,sizeof(struct gbox_ecm_info), -1)){
731        cs_unlock(&gbox->lock);
732        return -1;
733      }
734      er->src_data = ei;
735
736      cli->typ = 'r';
737
738      static uchar ecm_idx = 0;
739      uchar *ecm = data + 18;
740
741      er->idx = ++ecm_idx;
742      er->l = ecm[2] + 3;
743      er->pid = data[10] << 8 | data[11];
744      er->srvid = data[12] << 8 | data[13];
745      ei->extra = data[14] << 8 | data[15];
746      memcpy(er->ecm, data + 18, er->l);
747
748      ei->ncards = data[16];
749
750      ei->peer = ecm[er->l] << 8 | ecm[er->l + 1];
751      ei->version = ecm[er->l + 2];
752      ei->type = ecm[er->l + 4];
753      er->caid = ecm[er->l + 5] << 8 | ecm[er->l + 6];
754      er->prid = ecm[er->l + 7] << 8 | ecm[er->l + 8];
755      ei->slot = ecm[er->l + 12];
756      ei->unknwn1 = ecm[er->l + 3];
757      ei->unknwn2 = ecm[er->l + 13];
758      memcpy(ei->checksums, ecm + er->l + 14, 14);
759
760      cs_log("gbox: ecm received, caid=%04x. provid=%x, sid=%04x, len=%d, peer=%04x", er->caid, er->prid, er->srvid, er->l, ei->peer);
761      get_cw(cli, er);
762    }
763      break;
764    default:
765      cs_ddump_mask(D_READER, data, n, "gbox: unknown data received (%d bytes):", n);
766  }
767  cs_unlock(&gbox->lock);
768
769  return 0;
770}
771
772static void gbox_send_dcw(struct s_client *cli, ECM_REQUEST *er)
773{
774  struct gbox_data *gbox = cli->gbox;
775
776  if( er->rc >= E_NOTFOUND ) {
777    cs_log("gbox: unable to decode!");
778    //TODO: send something better back??
779    //gbox_send_goodbye(cli);
780    return;
781  }
782
783  uchar buf[45];
784  uint32_t crc = gbox_get_ecmchecksum(er);
785  struct gbox_ecm_info *ei =  er->src_data;
786
787  memset(buf, 0, sizeof(buf));
788
789  gbox_code_cmd(buf, MSG_CW);
790  memcpy(buf + 2, gbox->peer.key, 4);
791  buf[6] = er->pid;
792  buf[7] = er->pid;
793  buf[8] = er->srvid >> 8;
794  buf[9] = er->srvid & 0xff;
795  buf[10] = gbox->id >> 8;
796  buf[11] = gbox->id & 0xff;
797  buf[12] = 0x10 | (er->ecm[0] & 1);
798  buf[13] = er->caid >> 8;
799  memcpy(buf + 14, er->cw, 16);
800  buf[30] = crc >> 24;
801  buf[31] = crc >> 16;
802  buf[32] = crc >> 8;
803  buf[33] = crc & 0xff;
804  buf[34] = er->caid >> 8;
805  buf[35] = er->caid & 0xff;
806  buf[36] = ei->ncards;
807  buf[37] = ei->extra >> 8;
808  buf[38] = ei->extra & 0xff;
809  buf[39] = ei->peer;
810  buf[40] = ei->peer;
811  buf[41] = er->pid >> 8;
812  buf[42] = er->pid & 0xff;
813  buf[43] = ei->unknwn1;
814
815  gbox_send(cli, buf, 45);
816}
817
818static int32_t gbox_client_init(struct s_client *cli)
819{
820    if (!strlen(cfg.gbox_hostname)) {
821        cs_log("gbox: error, no hostname configured in oscam.conf!");
822        return -1;
823    }
824
825    if (strlen(cfg.gbox_key) != 8) {
826        cs_log("gbox: error, no/invalid password configured in oscam.conf!");
827        return -1;
828    }
829
830    if (cfg.gbox_port < 1) {
831        cs_log("gbox: no/invalid port configured in oscam.conf!");
832        return -1;
833    }
834    if(!cs_malloc(&cli->gbox,sizeof(struct gbox_data), -1)) return -1;
835
836  struct gbox_data *gbox = cli->gbox;
837  struct s_reader *rdr = cli->reader;
838
839  sem_init(&gbox->sem, 0 , 1);
840
841  rdr->card_status = CARD_FAILURE;
842  rdr->tcp_connected = 0;
843
844  memset(gbox, 0, sizeof(struct gbox_data));
845  memset(&gbox->peer, 0, sizeof(struct gbox_peer));
846
847  uint32_t r_pwd = a2i(rdr->r_pwd, 4);
848  uint32_t key = a2i(cfg.gbox_key, 4);
849  int32_t i;
850  for (i = 3; i >= 0; i--) {
851      gbox->peer.key[3 - i] = (r_pwd >> (8 * i)) & 0xff;
852      gbox->key[3 - i] = (key >> (8 * i)) & 0xff;
853  }
854
855  cs_ddump_mask(D_READER, gbox->peer.key, 4, "r_pwd: %s:", rdr->r_pwd);
856  cs_ddump_mask(D_READER, gbox->key, 4, "cfg.gbox_key: %s:", cfg.gbox_key);
857
858  gbox->peer.id = (gbox->peer.key[0] ^ gbox->peer.key[2]) << 8 | (gbox->peer.key[1] ^ gbox->peer.key[3]);
859  gbox->id = (gbox->key[0] ^ gbox->key[2]) << 8 | (gbox->key[1] ^ gbox->key[3]);
860  gbox->ver = 0x30;
861  gbox->type = 0x32;
862
863  struct sockaddr_in loc_sa;
864  cli->pfd=0;
865  cli->is_udp = 1;
866    cli->ip=0;
867    memset((char *)&loc_sa,0,sizeof(loc_sa));
868    loc_sa.sin_family = AF_INET;
869  loc_sa.sin_addr.s_addr = INADDR_ANY;
870  loc_sa.sin_port = htons(cfg.gbox_port);
871
872  if ((cli->udp_fd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))<0)
873   {
874        cs_log("socket creation failed (errno=%d %s)", errno, strerror(errno));
875        cs_exit(1);
876  }
877
878  int32_t opt = 1;
879  setsockopt(cli->udp_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
880
881#ifdef SO_PRIORITY
882  if (cfg.netprio)
883    setsockopt(cli->udp_fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg.netprio, sizeof(uintptr_t));
884#endif
885
886  if (cfg.gbox_port>0)
887  {
888    if (bind(cli->udp_fd, (struct sockaddr *)&loc_sa, sizeof (loc_sa))<0)
889    {
890      cs_log("bind failed (port=%d, errno=%d %s)", rdr->l_port, errno, strerror(errno));
891      close(cli->udp_fd);
892        return 1;
893    }
894  }
895
896  memset((char *)&cli->udp_sa, 0, sizeof(cli->udp_sa));
897
898  if (!hostResolve(rdr))
899    return 1;
900
901  cli->udp_sa.sin_family=AF_INET;
902  cli->udp_sa.sin_port=htons((uint16_t)rdr->r_port);
903
904  cs_log("proxy %s:%d (fd=%d, peer id=%04x, my id=%04x, my hostname=%s, listen port=%d)",
905    rdr->device, rdr->r_port, cli->udp_fd, gbox->peer.id, gbox->id, cfg.gbox_hostname, cfg.gbox_port);
906
907    cli->pfd=cli->udp_fd;
908
909  pthread_mutex_init(&gbox->lock, NULL);
910
911  gbox->hello_expired = 1;
912  gbox->hello_initial = 1;
913
914  gbox_send_hello(cli);
915
916  return 0;
917}
918
919static int32_t gbox_recv_chk(struct s_client *cli, uchar *dcw, int32_t *rc, uchar *buf, int32_t UNUSED(n))
920{
921  struct gbox_data *gbox = cli->gbox;
922
923  if (gbox_decode_cmd(buf) == MSG_CW) {
924      *rc = 1;
925
926      memcpy(dcw, gbox->cws, 16);
927
928      return gbox->ecm_idx;
929  }
930
931  return -1;
932}
933
934static int32_t gbox_send_ecm(struct s_client *cli, ECM_REQUEST *er, uchar *buf)
935{
936  struct gbox_data *gbox = cli->gbox;
937
938    if (!gbox || !cli->reader->tcp_connected) {
939        er->rc = E_RDR_NOTFOUND;
940        er->rcEx = 0x27;
941        cs_debug_mask(D_READER, "gbox: %s server not init!", cli->reader->label);
942        write_ecm_answer(cli->reader, er);
943
944        return 0;
945    }
946
947    if (!ll_count(gbox->peer.cards)) {
948        er->rc = E_RDR_NOTFOUND;
949        er->rcEx = 0x27;
950        cs_debug_mask(D_READER, "gbox: %s NO CARDS!", cli->reader->label);
951        write_ecm_answer(cli->reader, er);
952        return 0;
953    }
954
955    if (!gbox->peer.online) {
956        er->rc = E_RDR_NOTFOUND;
957        er->rcEx = 0x27;
958        cs_debug_mask(D_READER, "gbox: peer is OFFLINE!");
959        write_ecm_answer(cli->reader, er);
960        return 0;
961    }
962
963  uchar send_buf[0x2048], *ptr;
964
965  if (!er->l) return -1;
966
967  gbox->ecm_idx = er->idx;
968
969  memset(send_buf, 0, sizeof(send_buf));
970
971  gbox_code_cmd(send_buf, MSG_ECM);
972  memcpy(send_buf + 2, gbox->peer.key, 4);
973  memcpy(send_buf + 6, gbox->key, 4);
974  send_buf[10] = er->pid >> 8;
975  send_buf[11] = er->pid;
976  send_buf[12] = er->srvid >> 8;
977  send_buf[13] = er->srvid;
978/*  send_buf[14] = er->prid >> 16;
979  send_buf[15] = er->prid >> 8;
980  send_buf[17] = er->prid;*/
981  memcpy(send_buf + 18, er->ecm, er->l);
982  ptr = send_buf + 18 + er->l;
983  *(ptr) = gbox->id >> 8;
984  *(++ptr) = gbox->id;
985  *(++ptr) = gbox->ver;
986  ptr++;
987  *(++ptr) = gbox->type;
988  *(++ptr) = er->caid >> 8;
989  *(++ptr) = er->prid >> 16;
990  *(++ptr) = er->prid >> 8;
991  *(++ptr) = er->prid;
992  ptr++;
993
994  LL_ITER it = ll_iter_create(gbox->peer.cards);
995  struct gbox_card *card;
996  while ((card = ll_iter_next(&it))) {
997    //if (card->caid == er->caid && card->provid == er->prid) {
998    if (card->provid >> 24 == er->caid >> 8 && (card->provid & 0xffffff) == er->prid) {
999      *(++ptr) = card->peer_id >> 8;
1000      *(++ptr) = card->peer_id;
1001      *(++ptr) = card->slot;
1002      send_buf[16]++;
1003    }
1004  }
1005
1006  if (!send_buf[16]) {
1007        er->rc = E_RDR_NOTFOUND;
1008        er->rcEx = 0x27;
1009        cs_debug_mask(D_READER, "gbox: %s no suitable card found, discarding ecm", cli->reader->label);
1010        write_ecm_answer(cli->reader, er);
1011
1012        return 0;
1013  }
1014
1015  memcpy(++ptr, gbox->checkcode, 7);
1016  ptr += 7;
1017  memcpy(ptr, gbox->peer.checkcode, 7);
1018
1019  gbox_send(cli, send_buf, ptr + 7 - send_buf);
1020
1021  return 0;
1022}
1023
1024static int32_t gbox_send_emm(EMM_PACKET *ep)
1025{
1026  // emms not yet supported
1027
1028  return 0;
1029}
1030
1031void module_gbox(struct s_module *ph)
1032{
1033  cs_strncpy(ph->desc, "gbox", sizeof(ph->desc));
1034  ph->num=R_GBOX;
1035  ph->type=MOD_CONN_UDP;
1036  ph->logtxt = ", crypted";
1037
1038  ph->multi=1;
1039  ph->watchdog=1;
1040  ph->send_dcw=gbox_send_dcw;
1041
1042  ph->recv=gbox_recv;
1043  ph->c_multi=1;
1044  ph->c_init=gbox_client_init;
1045  ph->c_recv_chk=gbox_recv_chk;
1046  ph->c_send_ecm=gbox_send_ecm;
1047  ph->c_send_emm=gbox_send_emm;
1048}
1049#endif
1050
Note: See TracBrowser for help on using the repository browser.