source: branches/cccam-test/module-cccam.c@ 593

Last change on this file since 593 was 593, checked in by cogsi, 11 years ago

cccam reader now selects card at lowest hop

  • Property svn:mime-type set to text/plain
File size: 21.2 KB
Line 
1#include "globals.h"
2
3/******************************** */
4/* LINKED LIST CODE - IF IT'S USEFUL ELSEWHERE, IT SHOULD BE SPLIT OFF INTO linkedlist.h/.c */
5/******************************** */
6
7// Simple, doubly linked
8// This is thread-safe, so requires pthread. Also expect locking if iterators are not destroyed.
9
10#include <pthread.h>
11
12struct llist_node {
13 void *obj;
14 struct llist_node *prv;
15 struct llist_node *nxt;
16};
17
18typedef struct llist {
19 struct llist_node *first;
20 struct llist_node *last;
21 int items;
22 pthread_mutex_t lock;
23} LLIST;
24
25typedef struct llist_itr {
26 LLIST *l;
27 struct llist_node *cur;
28} LLIST_ITR;
29
30LLIST *llist_create(void); // init linked list
31void llist_destroy(LLIST *l); // de-init linked list - frees all objects on the list
32
33void *llist_append(LLIST *l, void *o); // append object onto bottom of list, returns ptr to obj
34
35void *llist_itr_init(LLIST *l, LLIST_ITR *itr); // linked list iterator, returns ptr to first obj
36void llist_itr_release(LLIST_ITR *itr); // release iterator
37void *llist_itr_next(LLIST_ITR *itr); // iterates, returns ptr to next obj
38
39void *llist_itr_insert(LLIST_ITR *itr, void *o); // insert object at itr point, iterates to and returns ptr to new obj
40void *llist_itr_remove(LLIST_ITR *itr); // remove obj at itr, iterates to and returns ptr to next obj
41
42int llist_count(LLIST *l); // returns number of obj in list
43
44/******************************** */
45
46#include <string.h>
47#include <stdlib.h>
48
49LLIST *llist_create(void)
50{
51 LLIST *l = malloc(sizeof(LLIST));
52 bzero(l, sizeof(LLIST));
53
54 pthread_mutex_init(&l->lock, NULL);
55
56 l->items = 0;
57
58 return l;
59}
60
61void llist_destroy(LLIST *l)
62{
63 LLIST_ITR itr;
64 void *o = llist_itr_init(l, &itr);
65 while (o) {
66 free(o);
67 o = llist_itr_remove(&itr);
68 }
69 llist_itr_release(&itr);
70}
71
72void *llist_append(LLIST *l, void *o)
73{
74 pthread_mutex_lock(&l->lock);
75 if (o) {
76 struct llist_node *ln = malloc(sizeof(struct llist_node));
77
78 bzero(ln, sizeof(struct llist_node));
79 ln->obj = o;
80
81 if (l->last) {
82 ln->prv = l->last;
83 ln->prv->nxt = ln;
84 } else {
85 l->first = ln;
86 }
87 l->last = ln;
88
89 l->items++;
90 }
91 pthread_mutex_unlock(&l->lock);
92
93 return o;
94}
95
96void *llist_itr_init(LLIST *l, LLIST_ITR *itr)
97{
98 pthread_mutex_lock(&l->lock);
99 if (l->first) {
100
101 bzero(itr, sizeof(LLIST_ITR));
102 itr->cur = l->first;
103 itr->l = l;
104
105 return itr->cur->obj;
106 }
107
108 return NULL;
109}
110
111void llist_itr_release(LLIST_ITR *itr)
112{
113 pthread_mutex_unlock(&itr->l->lock);
114}
115
116void *llist_itr_next(LLIST_ITR *itr)
117{
118 if (itr->cur->nxt) {
119 itr->cur = itr->cur->nxt;
120 return itr->cur->obj;
121 }
122
123 return NULL;
124}
125
126void *llist_itr_remove(LLIST_ITR *itr) // this needs cleaning - I was lazy
127{
128 itr->l->items--;
129 if ((itr->cur == itr->l->first) && (itr->cur == itr->l->last)) {
130 // cs_log("DEBUG %d: first&last", llist_count(itr->l));
131 free(itr->cur);
132 itr->l->first = NULL;
133 itr->l->last = NULL;
134 return NULL;
135 } else if (itr->cur == itr->l->first) {
136 // cs_log("DEBUG %d: first", llist_count(itr->l));
137 struct llist_node *nxt = itr->cur->nxt;
138 free(itr->cur);
139 nxt->prv = NULL;
140 itr->l->first = nxt;
141 itr->cur = nxt;
142 } else if (itr->cur == itr->l->last) {
143 // cs_log("DEBUG %d: last", llist_count(itr->l));
144 itr->l->last = itr->cur->prv;
145 itr->l->last->nxt = NULL;
146 free(itr->cur);
147 return NULL;
148 } else {
149 // cs_log("DEBUG %d: free middle", llist_count(itr->l));
150 struct llist_node *nxt = itr->cur->nxt;
151 itr->cur->prv->nxt = itr->cur->nxt;
152 itr->cur->nxt->prv = itr->cur->prv;
153 free(itr->cur);
154 itr->cur = nxt;
155 }
156
157 return itr->cur->obj;
158}
159
160int llist_count(LLIST *l)
161{
162 return l->items;
163}
164
165/******************************** */
166
167#define CC_MAXMSGSIZE 512
168#define CC_MAX_PROV 16
169
170#define SWAPC(X, Y) do { char p; p = *X; *X = *Y; *Y = p; } while(0)
171#define B16(X) ( (X)[0] << 8 | (X)[1] )
172#define B24(X) ( (X)[0] << 16 | (X)[1] << 8 | (X)[2] )
173#define B32(X) ( (X)[0] << 24 | (X)[1] << 16 | (X)[2] << 8 | (X)[3] )
174#define B64(X) ( (X)[0] << 56 | (X)[1] << 48 | (X)[2] << 40 | (X)[3] << 32 | (X)[4] << 24 | (X)[5] << 16 | (X)[6] << 8 | (X)[7] )
175#define X_FREE(X) do { if (X) { free(X); X = NULL; } } while(0)
176
177typedef unsigned char uint8;
178typedef unsigned short uint16;
179typedef unsigned int uint32;
180typedef unsigned long long uint64;
181
182typedef enum {
183 DECRYPT,
184 ENCRYPT
185} cc_crypt_mode_t;
186
187typedef enum
188{
189 MSG_CLI_DATA,
190 MSG_CW,
191 MSG_ECM = 1,
192 MSG_CARD_REMOVED = 4,
193 MSG_DCW_SOMETHING, // this still needs to be worked out
194 MSG_PING,
195 MSG_NEW_CARD,
196 MSG_SRV_DATA,
197 MSG_CW_NOK1 = 0xfe,
198 MSG_CW_NOK2 = 0xff,
199 MSG_NO_HEADER = 0xffff
200} cc_msg_type_t;
201
202struct cc_crypt_block
203{
204 uint8 keytable[256];
205 uint8 state;
206 uint8 counter;
207 uint8 sum;
208};
209
210struct cc_card {
211 uint32 id; // cccam card (share) id
212 uint16 caid;
213 uint8 hop;
214 uint8 key[8]; // card serial (for au)
215 LLIST *provs; // providers
216 LLIST *badsids; // sids that have failed to decode
217};
218
219struct cc_data {
220 struct cc_crypt_block block[2]; // crypto state blocks
221
222 uint8 node_id[8], // client node id
223 server_node_id[8], // server node id
224 dcw[16]; // control words
225
226 struct cc_card *cur_card; // ptr to selected card
227 LLIST *cards; // cards list
228
229 uint32 count;
230};
231
232static unsigned int seed;
233static uchar fast_rnd()
234{
235 unsigned int offset = 12923;
236 unsigned int multiplier = 4079;
237
238 seed = seed * multiplier + offset;
239 return (uchar)(seed % 0xFF);
240}
241
242
243static void cc_init_crypt(struct cc_crypt_block *block, uint8 *key, int len)
244{
245 int i = 0 ;
246 uint8 j = 0;
247
248 for (i=0; i<256; i++) {
249 block->keytable[i] = i;
250 }
251
252 for (i=0; i<256; i++) {
253 j += key[i % len] + block->keytable[i];
254 SWAPC(&block->keytable[i], &block->keytable[j]);
255 }
256
257 block->state = *key;
258 block->counter=0;
259 block->sum=0;
260}
261
262static void cc_crypt(struct cc_crypt_block *block, uint8 *data, int len, cc_crypt_mode_t mode)
263{
264 int i;
265 uint8 z;
266
267 for (i = 0; i < len; i++) {
268 block->counter++;
269 block->sum += block->keytable[block->counter];
270 SWAPC(&block->keytable[block->counter], &block->keytable[block->sum]);
271 z = data[i];
272 data[i] = z ^ block->keytable[(block->keytable[block->counter] + block->keytable[block->sum]) & 0xff] ^ block->state;
273 if (!mode) z = data[i];
274 block->state = block->state ^ z;
275 }
276}
277
278static void cc_xor(uint8 *buf)
279{
280 const char cccam[] = "CCcam";
281 uint8 i;
282
283 for ( i = 0; i < 8; i++ ) {
284 buf[8 + i] = i * buf[i];
285 if ( i <= 5 ) {
286 buf[i] ^= cccam[i];
287 }
288 }
289}
290
291static void cc_cw_decrypt(uint8 *cws)
292{
293 struct cc_data *cc = reader[ridx].cc;
294
295 uint32 cur_card = cc->cur_card->id;
296 uint32 node_id_1 = B32(cc->node_id);
297 uint32 node_id_2 = B32(cc->node_id + 4);
298 uint32 tmp;
299 int i;
300
301 for (i = 0; i < 16; i++) {
302 tmp = cws[i] ^ node_id_2;
303 if (i & 1) {
304 tmp = ~tmp;
305 }
306 cws[i] = cur_card ^ tmp;
307 node_id_2 = (node_id_2 >> 4) | (node_id_1 << 28);
308 node_id_1 >>= 4;
309 cur_card >>= 2;
310 }
311}
312
313static int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec)
314{
315 int flags, n, error;
316 socklen_t len;
317 fd_set rset, wset;
318 struct timeval tval;
319
320 flags = fcntl(sockfd, F_GETFL, 0);
321 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
322
323 error = 0;
324 cs_debug("cccam: conn_nb 1 (fd=%d)", sockfd);
325
326 if ( (n = connect(sockfd, saptr, salen)) < 0) {
327 if( errno==EALREADY ) {
328 cs_debug("cccam: conn_nb in progress, errno=%d", errno);
329 return(-1);
330 }
331 else if( errno==EISCONN ) {
332 cs_debug("cccam: conn_nb already connected, errno=%d", errno);
333 goto done;
334 }
335 cs_debug("cccam: conn_nb 2 (fd=%d)", sockfd);
336 if (errno != EINPROGRESS) {
337 cs_debug("cccam: conn_nb 3 (fd=%d)", sockfd);
338 return(-1);
339 }
340 }
341
342 cs_debug("cccam: n = %d\n", n);
343
344 /* Do whatever we want while the connect is taking place. */
345 if (n == 0)
346 goto done; /* connect completed immediately */
347
348 FD_ZERO(&rset);
349 FD_SET(sockfd, &rset);
350 wset = rset;
351 tval.tv_sec = nsec;
352 tval.tv_usec = 0;
353
354 if ( (n = select(sockfd+1, &rset, &wset, 0, nsec ? &tval : 0)) == 0) {
355 //close(sockfd); // timeout
356 cs_debug("cccam: conn_nb 4 (fd=%d)", sockfd);
357 errno = ETIMEDOUT;
358 return(-1);
359 }
360
361 cs_debug("cccam: conn_nb 5 (fd=%d)", sockfd);
362
363 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
364 cs_debug("cccam: conn_nb 6 (fd=%d)", sockfd);
365 len = sizeof(error);
366 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
367 cs_debug("cccam: conn_nb 7 (fd=%d)", sockfd);
368 return(-1); // Solaris pending error
369 }
370 } else {
371 cs_debug("cccam: conn_nb 8 (fd=%d)", sockfd);
372 return -2;
373 }
374
375done:
376cs_debug("cccam: conn_nb 9 (fd=%d)", sockfd);
377 fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
378
379 if (error) {
380 cs_debug("cccam: conn_nb 10 (fd=%d)", sockfd);
381 //close(sockfd); /* just in case */
382 errno = error;
383 return(-1);
384 }
385 return(0);
386}
387
388static int network_tcp_connection_open(uint8 *hostname, uint16 port)
389{
390
391 int flags;
392 if( connect_nonb(client[cs_idx].udp_fd,
393 (struct sockaddr *)&client[cs_idx].udp_sa,
394 sizeof(client[cs_idx].udp_sa), 5) < 0)
395 {
396 cs_log("cccam: connect(fd=%d) failed: (errno=%d)", client[cs_idx].udp_fd, errno);
397 return -1;
398 }
399 flags = fcntl(client[cs_idx].udp_fd, F_GETFL, 0);
400 flags &=~ O_NONBLOCK;
401 fcntl(client[cs_idx].udp_fd, F_SETFL, flags );
402
403 return client[cs_idx].udp_fd;
404}
405
406static int cc_msg_recv(uint8 *buf, int l)
407{
408 int len, flags;
409 uint8 netbuf[CC_MAXMSGSIZE];
410
411 struct cc_data *cc = reader[ridx].cc;
412 int handle = client[cs_idx].udp_fd;
413
414 if (handle < 0) return -1;
415
416 len = recv(handle, netbuf, 4, MSG_WAITALL);
417
418 if (!len) return 0;
419
420 if (len != 4) { // invalid header length read
421 cs_log("cccam: invalid header length");
422 return -1;
423 }
424
425 cc_crypt(&cc->block[DECRYPT], netbuf, 4, DECRYPT);
426 //cs_ddump(netbuf, 4, "cccam: decrypted header:");
427
428 flags = netbuf[0];
429
430 if (((netbuf[2] << 8) | netbuf[3]) != 0) { // check if any data is expected in msg
431 if (((netbuf[2] << 8) | netbuf[3]) > CC_MAXMSGSIZE - 2) {
432 cs_log("cccam: message too big");
433 return -1;
434 }
435
436 len = recv(handle, netbuf+4, (netbuf[2] << 8) | netbuf[3], MSG_WAITALL); // read rest of msg
437
438 if (len != ((netbuf[2] << 8) | netbuf[3])) {
439 cs_log("cccam: invalid message length read");
440 return -1;
441 }
442
443 cc_crypt(&cc->block[DECRYPT], netbuf+4, len, DECRYPT);
444 len += 4;
445 }
446
447 //cs_ddump(netbuf, len, "cccam: full decrypted msg, len=%d:", len);
448
449 memcpy(buf, netbuf, len);
450 return len;
451}
452
453static int cc_cmd_send(uint8 *buf, int len, cc_msg_type_t cmd)
454{
455 int n;
456 uint8 *netbuf = malloc(len+4);
457 struct cc_data *cc = reader[ridx].cc;
458
459 bzero(netbuf, len+4);
460
461 if (cmd == MSG_NO_HEADER) {
462 memcpy(netbuf, buf, len);
463 } else {
464 // build command message
465 netbuf[0] = 0; // flags??
466 netbuf[1] = cmd & 0xff;
467 netbuf[2] = len >> 8;
468 netbuf[3] = len & 0xff;
469 if (buf) memcpy(netbuf+4, buf, len);
470 len += 4;
471 }
472
473 cc_crypt(&cc->block[ENCRYPT], netbuf, len, ENCRYPT);
474
475 cs_ddump(buf, len, "cccam: send:");
476 //cs_ddump(netbuf, len, "cccam: send enc:");
477 n = send(client[cs_idx].udp_fd, netbuf, len, 0);
478
479 X_FREE(netbuf);
480
481 return n;
482}
483
484static int cc_send_cli_data()
485{
486 int i;
487 struct cc_data *cc = reader[ridx].cc;
488
489 cs_debug("cccam: send client data");
490
491 //memcpy(cc->node_id, "\x7A\xDD\xAB\x28\xC9\x39\x4A\x2F", 8);
492
493 seed = (unsigned int) time((time_t*)0);
494 for( i=0; i<8; i++ ) cc->node_id[i]=fast_rnd();
495
496 uint8 buf[CC_MAXMSGSIZE];
497 bzero(buf, CC_MAXMSGSIZE);
498
499 memcpy(buf, reader[ridx].r_usr, strlen(reader[ridx].r_usr) );
500 memcpy(buf + 20, cc->node_id, 8 );
501 memcpy(buf + 29, reader[ridx].cc_version, strlen(reader[ridx].cc_version)); // cccam version (ascii)
502 memcpy(buf + 61, reader[ridx].cc_build, strlen(reader[ridx].cc_build)); // build number (ascii)
503
504 return cc_cmd_send(buf, 20 + 8 + 6 + 26 + 4 + 28 + 1, MSG_CLI_DATA);
505}
506
507static int cc_send_ecm(ECM_REQUEST *er, uchar *buf)
508{
509 int n, h = -1;
510 struct cc_data *cc = reader[ridx].cc;
511 struct cc_card *card;
512 LLIST_ITR itr;
513
514 memcpy(buf, er->ecm, er->l);
515
516 cc->cur_card = NULL;
517
518 card = llist_itr_init(cc->cards, &itr);
519
520 while (card) {
521 if (card->caid == er->caid) { // caid matches
522 LLIST_ITR pitr;
523 char *prov = llist_itr_init(card->provs, &pitr);
524 while (prov) {
525 if (B24(prov) == er->prid) { // provid matches
526 if ((h < 0) || (card->hop < h)) { // card is closer
527 cc->cur_card = card;
528 h = card->hop; // card has been matched
529 }
530 }
531 prov = llist_itr_next(&pitr);
532 }
533 llist_itr_release(&pitr);
534 }
535 card = llist_itr_next(&itr);
536 }
537 llist_itr_release(&itr);
538
539 if (cc->cur_card) {
540 uint8 *ecmbuf = malloc(er->l+13);
541 bzero(ecmbuf, er->l+13);
542
543 // build ecm message
544 ecmbuf[0] = cc->cur_card->caid >> 8;
545 ecmbuf[1] = cc->cur_card->caid & 0xff;
546 ecmbuf[2] = er->prid >> 24;
547 ecmbuf[3] = er->prid >> 16;
548 ecmbuf[4] = er->prid >> 8;
549 ecmbuf[5] = er->prid & 0xff;
550 ecmbuf[6] = cc->cur_card->id >> 24;
551 ecmbuf[7] = cc->cur_card->id >> 16;
552 ecmbuf[8] = cc->cur_card->id >> 8;
553 ecmbuf[9] = cc->cur_card->id & 0xff;
554 ecmbuf[10] = er->srvid >> 8;
555 ecmbuf[11] = er->srvid & 0xff;
556 ecmbuf[12] = er->l & 0xff;
557 memcpy(ecmbuf+13, buf, er->l);
558
559 cc->count = er->idx;
560
561 cs_log("cccam: sending ecm for sid %04x to card %08x, hop %d", er->srvid, cc->cur_card->id, cc->cur_card->hop);
562 n = cc_cmd_send(ecmbuf, er->l+13, MSG_ECM); // send ecm
563
564 X_FREE(ecmbuf);
565 } else {
566 n = -1;
567 cs_log("cccam: no suitable card on server");
568 }
569
570 if (n) return 0;
571 else return -1;
572}
573
574static cc_msg_type_t cc_parse_msg(uint8 *buf, int l)
575{
576 struct cc_data *cc = reader[ridx].cc;
577
578 switch (buf[1]) {
579 case MSG_CLI_DATA:
580 cs_debug("cccam: client data ack");
581 break;
582 case MSG_SRV_DATA:
583 memcpy(cc->server_node_id, buf+4, 8);
584 cs_log("cccam: srv %s running v%s (%s)", cs_hexdump(0, cc->server_node_id, 8), buf+12, buf+44);
585 break;
586 case MSG_NEW_CARD:
587 if (B16(buf+12) == reader[ridx].ctab.caid[0]) { // only add cards with relevant caid (for now)
588 int i;
589 struct cc_card *card = malloc(sizeof(struct cc_card));
590
591 bzero(card, sizeof(struct cc_card));
592
593 card->provs = llist_create();
594 card->id = B32(buf+4);
595 card->caid = B16(buf+12);
596 card->hop = buf[14];
597 memcpy(card->key, buf+16, 8);
598
599 cs_debug("cccam: card %08x added, caid %04x, hop %d, key %s",
600 card->id, card->caid, card->hop, cs_hexdump(0, card->key, 8));
601
602 for (i = 0; i < buf[24]; i++) { // providers
603 uint8 *prov = malloc(3);
604
605 memcpy(prov, buf+25+(7*i), 3);
606 cs_debug(" prov %d, %06x", i+1, B24(prov));
607
608 llist_append(card->provs, prov);
609 }
610
611 llist_append(cc->cards, card);
612 if (!cc->cur_card) cc->cur_card = card;
613 }
614 break;
615 case MSG_CARD_REMOVED:
616 {
617 struct cc_card *card;
618 LLIST_ITR itr;
619
620 card = llist_itr_init(cc->cards, &itr);
621 while (card) {
622 if (card->id == B32(buf+4)) {
623 cs_debug("cccam: card %08x removed, caid %04x", card->id, card->caid);
624
625 llist_destroy(card->provs);
626 free(card);
627
628 card = llist_itr_remove(&itr);
629 break;
630 } else {
631 card = llist_itr_next(&itr);
632 }
633 }
634 llist_itr_release(&itr);
635 }
636 break;
637 case MSG_CW_NOK1:
638 case MSG_CW_NOK2:
639 cs_log("cccam: cw nok");
640 break;
641 case MSG_CW:
642 cc_cw_decrypt(buf+4);
643 memcpy(cc->dcw, buf+4, 16);
644 cs_debug("cccam: cws: %s", cs_hexdump(0, cc->dcw, 16));
645 cc_crypt(&cc->block[DECRYPT], buf+4, l-4, ENCRYPT); // additional crypto step
646 return 0;
647 break;
648 case MSG_PING:
649 cc_cmd_send(NULL, 0, MSG_PING);
650 break;
651 default:
652 break;
653 }
654
655 return buf[1];
656}
657
658static int cc_recv_chk(uchar *dcw, int *rc, uchar *buf, int n)
659{
660 struct cc_data *cc = reader[ridx].cc;
661
662 if (buf[1] == MSG_CW) {
663 memcpy(dcw, cc->dcw, 16);
664 cs_debug("cccam: recv chk - MSG_CW %d - %s", cc->count, cs_hexdump(0, dcw, 16));
665 *rc = 1;
666 //return 0;
667 return(cc->count);
668 }
669
670 return -1;
671}
672
673int cc_recv(uchar *buf, int l)
674{
675 int n;
676 uchar *cbuf = malloc(l);
677
678 memcpy(cbuf, buf, l); // make a copy of buf
679
680 if (!is_server) {
681 if (!client[cs_idx].udp_fd) return(-1);
682 n = cc_msg_recv(cbuf, l); // recv and decrypt msg
683 } else {
684 return -2;
685 }
686
687 cs_ddump(buf, n, "cccam: received %d bytes from %s", n, remote_txt());
688 client[cs_idx].last = time((time_t *) 0);
689
690 if (n < 4) {
691 cs_log("cccam: packet to small (%d bytes)", n);
692 n = -1;
693 } else if (n == 0) {
694 cs_log("cccam: Connection closed to %s", remote_txt());
695 n = -1;
696 }
697
698 cc_parse_msg(cbuf, n);
699
700 memcpy(buf, cbuf, l);
701
702 X_FREE(cbuf);
703
704 return(n);
705}
706
707static int cc_cli_connect(void)
708{
709 int handle;
710 uint8 data[20];
711 uint8 hash[SHA1_DIGEST_SIZE];
712 uint8 buf[CC_MAXMSGSIZE];
713 struct cc_data *cc;
714
715 // init internals data struct
716 cc = malloc(sizeof(struct cc_data));
717 reader[ridx].cc = cc;
718 bzero(reader[ridx].cc, sizeof(struct cc_data));
719 cc->cards = llist_create();
720
721 // check cred config
722 if(reader[ridx].device[0] == 0 || reader[ridx].r_pwd[0] == 0 ||
723 reader[ridx].r_usr[0] == 0 || reader[ridx].r_port == 0)
724 return -5;
725
726 // connect
727 handle = network_tcp_connection_open((uint8 *)reader[ridx].device, reader[ridx].r_port);
728 if(handle < 0) return -1;
729
730 // get init seed
731 if(read(handle, data, 16) != 16) {
732 cs_log("cccam: server does not return 16 bytes");
733 network_tcp_connection_close(handle);
734 return -2;
735 }
736 cs_ddump(data, 16, "cccam: server init seed:");
737
738 cc_xor(data); // XOR init bytes with 'CCcam'
739
740 SHA1_CTX ctx;
741 SHA1_Init(&ctx);
742 SHA1_Update(&ctx, data, 16);
743 SHA1_Final(&ctx, hash);
744
745 cs_ddump(hash, sizeof(hash), "cccam: sha1 hash:");
746
747 //initialisate crypto states
748 cc_init_crypt(&cc->block[DECRYPT], hash, 20);
749 cc_crypt(&cc->block[DECRYPT], data, 16, DECRYPT);
750 cc_init_crypt(&cc->block[ENCRYPT], data, 16);
751 cc_crypt(&cc->block[ENCRYPT], hash, 20, DECRYPT);
752
753 cc_cmd_send(hash, 20, MSG_NO_HEADER); // send crypted hash to server
754
755 bzero(buf, sizeof(buf));
756
757 memcpy(buf, reader[ridx].r_usr, strlen(reader[ridx].r_usr));
758 cs_ddump(buf, 20, "cccam: username '%s':", buf);
759 cc_cmd_send(buf, 20, MSG_NO_HEADER); // send usr '0' padded -> 20 bytes
760
761 bzero(buf, sizeof(buf));
762
763 cs_debug("cccam: 'CCcam' xor");
764 memcpy(buf, "CCcam", 5);
765 cc_crypt(&cc->block[ENCRYPT], (uint8 *)reader[ridx].r_pwd, strlen(reader[ridx].r_pwd), ENCRYPT); // modify encryption state w/ pwd
766 cc_cmd_send(buf, 6, MSG_NO_HEADER); // send 'CCcam' xor w/ pwd
767
768 if (read(handle, data, 20) != 20) {
769 cs_log("ccam: login failed, pwd ack not received");
770 return -2;
771 }
772 cc_crypt(&cc->block[DECRYPT], data, 20, DECRYPT);
773 cs_ddump(data, 20, "cccam: pwd ack received:");
774
775 if (memcmp(data, buf, 5)) { // check server response
776 cs_log("cccam: login failed, usr/pwd invalid");
777 return -2;
778 } else {
779 cs_debug("cccam: login succeeded");
780 }
781
782 reader[ridx].tcp_connected = 1;
783 reader[ridx].last_g = reader[ridx].last_s = time((time_t *)0);
784
785 cs_debug("cccam: last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
786
787 pfd=client[cs_idx].udp_fd;
788
789 if (cc_send_cli_data(cc)<=0) {
790 cs_log("cccam: login failed, could not send client data");
791 return -3;
792 }
793 return 0;
794}
795
796int cc_cli_init(void)
797{
798 static struct sockaddr_in loc_sa;
799 struct protoent *ptrp;
800 int p_proto;
801
802 pfd=0;
803 if (reader[ridx].r_port<=0)
804 {
805 cs_log("cccam: invalid port %d for server %s", reader[ridx].r_port, reader[ridx].device);
806 return(1);
807 }
808 if( (ptrp=getprotobyname("tcp")) )
809 p_proto=ptrp->p_proto;
810 else
811 p_proto=6;
812
813 client[cs_idx].ip=0;
814 memset((char *)&loc_sa,0,sizeof(loc_sa));
815 loc_sa.sin_family = AF_INET;
816#ifdef LALL
817 if (cfg->serverip[0])
818 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
819 else
820#endif
821 loc_sa.sin_addr.s_addr = INADDR_ANY;
822 loc_sa.sin_port = htons(reader[ridx].l_port);
823
824 if ((client[cs_idx].udp_fd=socket(PF_INET, SOCK_STREAM, p_proto))<0)
825 {
826 cs_log("cccam: Socket creation failed (errno=%d)", errno);
827 cs_exit(1);
828 }
829
830#ifdef SO_PRIORITY
831 if (cfg->netprio)
832 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_PRIORITY,
833 (void *)&cfg->netprio, sizeof(ulong));
834#endif
835 if (!reader[ridx].tcp_ito) {
836 ulong keep_alive = reader[ridx].tcp_ito?1:0;
837 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_KEEPALIVE,
838 (void *)&keep_alive, sizeof(ulong));
839 }
840
841 memset((char *)&client[cs_idx].udp_sa,0,sizeof(client[cs_idx].udp_sa));
842 client[cs_idx].udp_sa.sin_family = AF_INET;
843 client[cs_idx].udp_sa.sin_port = htons((u_short)reader[ridx].r_port);
844
845 struct hostent *server;
846 server = gethostbyname(reader[ridx].device);
847 bcopy((char *)server->h_addr, (char *)&client[cs_idx].udp_sa.sin_addr.s_addr, server->h_length);
848
849 cs_log("cccam: proxy %s:%d cccam v%s (%s) (fd=%d)",
850 reader[ridx].device, reader[ridx].r_port, reader[ridx].cc_version,
851 reader[ridx].cc_build, client[cs_idx].udp_fd);
852
853 cc_cli_connect();
854
855 return(0);
856}
857
858void cc_cleanup(void)
859{
860
861}
862
863void module_cccam(struct s_module *ph)
864{
865 strcpy(ph->desc, "cccam");
866 ph->type=MOD_CONN_TCP;
867 ph->logtxt = ", crypted";
868 ph->watchdog=1;
869 ph->recv=cc_recv;
870 ph->cleanup=cc_cleanup;
871 ph->c_multi=1;
872 ph->c_init=cc_cli_init;
873 ph->c_recv_chk=cc_recv_chk;
874 ph->c_send_ecm=cc_send_ecm;
875}
Note: See TracBrowser for help on using the repository browser.