49 |
49 |
#define CWS_NETMSGSIZE 256
|
50 |
50 |
#define CWS_FIRSTCMDNO 0xe0
|
51 |
51 |
|
|
52 |
/**
|
|
53 |
* cards for which emm updates are handled
|
|
54 |
*/
|
52 |
55 |
typedef enum {
|
|
56 |
CARD_IRDETO,
|
|
57 |
CARD_CONAX,
|
|
58 |
CARD_SECA,
|
|
59 |
CARD_UNKNOWN
|
|
60 |
} card_type_t;
|
|
61 |
|
|
62 |
typedef enum {
|
53 |
63 |
MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
|
54 |
64 |
MSG_CLIENT_2_SERVER_LOGIN_ACK,
|
55 |
65 |
MSG_CLIENT_2_SERVER_LOGIN_NAK,
|
... | ... | |
195 |
205 |
/* Emm forwarding */
|
196 |
206 |
int cwc_forward_emm;
|
197 |
207 |
|
|
208 |
/* Card type */
|
|
209 |
card_type_t cwc_card_type;
|
|
210 |
|
198 |
211 |
/* From configuration */
|
199 |
212 |
|
200 |
213 |
uint8_t cwc_confedkey[14];
|
... | ... | |
221 |
234 |
|
222 |
235 |
static void cwc_transport_destroy(th_descrambler_t *td);
|
223 |
236 |
extern char *cwc_krypt(const char *key, const char *salt);
|
|
237 |
static void cwc_detect_card_type(cwc_t *cwc);
|
|
238 |
void cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len);
|
|
239 |
void cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len);
|
|
240 |
void cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len);
|
224 |
241 |
|
225 |
|
|
226 |
242 |
/**
|
227 |
243 |
*
|
228 |
244 |
*/
|
... | ... | |
516 |
532 |
cwc->cwc_ua[0], cwc->cwc_ua[1], cwc->cwc_ua[2], cwc->cwc_ua[3], cwc->cwc_ua[4], cwc->cwc_ua[5], cwc->cwc_ua[6], cwc->cwc_ua[7],
|
517 |
533 |
nprov);
|
518 |
534 |
|
|
535 |
cwc_detect_card_type(cwc);
|
|
536 |
|
519 |
537 |
msg += 15;
|
520 |
538 |
plen -= 12;
|
521 |
539 |
|
... | ... | |
557 |
575 |
if (!emm_allowed)
|
558 |
576 |
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (not allowed by server)",
|
559 |
577 |
cwc->cwc_hostname);
|
560 |
|
else if ((cwc->cwc_caid>>8) != 0x0b)
|
561 |
|
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
|
562 |
|
cwc->cwc_hostname);
|
563 |
|
else {
|
|
578 |
else if (cwc->cwc_card_type != CARD_UNKNOWN) {
|
564 |
579 |
tvhlog(LOG_INFO, "cwc", "%s: Will forward EMMs",
|
565 |
580 |
cwc->cwc_hostname);
|
566 |
581 |
cwc->cwc_forward_emm = 1;
|
567 |
|
}
|
|
582 |
} else
|
|
583 |
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
|
|
584 |
cwc->cwc_hostname);
|
568 |
585 |
}
|
569 |
586 |
|
570 |
587 |
return 0;
|
571 |
588 |
}
|
572 |
589 |
|
|
590 |
/**
|
|
591 |
* Detects the cam card type
|
|
592 |
* If you want to add another card, have a look at
|
|
593 |
* http://www.dvbservices.com/identifiers/ca_system_id?page=3
|
|
594 |
*
|
|
595 |
* based on the equivalent in sasc-ng
|
|
596 |
*/
|
|
597 |
static void
|
|
598 |
cwc_detect_card_type(cwc_t *cwc)
|
|
599 |
{
|
|
600 |
uint8_t c_sys = cwc->cwc_caid >> 8;
|
|
601 |
|
|
602 |
switch (c_sys) {
|
|
603 |
case 0x17:
|
|
604 |
case 0x06:
|
|
605 |
cwc->cwc_card_type = CARD_IRDETO;
|
|
606 |
tvhlog(LOG_INFO, "cwc", "%s: irdeto card",
|
|
607 |
cwc->cwc_hostname);
|
|
608 |
break;
|
|
609 |
case 0x01:
|
|
610 |
cwc->cwc_card_type = CARD_SECA;
|
|
611 |
tvhlog(LOG_INFO, "cwc", "%s: seca card",
|
|
612 |
cwc->cwc_hostname);
|
|
613 |
break;
|
|
614 |
case 0x0b:
|
|
615 |
cwc->cwc_card_type = CARD_CONAX;
|
|
616 |
tvhlog(LOG_INFO, "cwc", "%s: conax card",
|
|
617 |
cwc->cwc_hostname);
|
|
618 |
break;
|
|
619 |
default:
|
|
620 |
cwc->cwc_card_type = CARD_UNKNOWN;
|
|
621 |
tvhlog(LOG_INFO, "cwc", "%s: unknown card",
|
|
622 |
cwc->cwc_hostname);
|
|
623 |
}
|
|
624 |
}
|
573 |
625 |
|
574 |
626 |
/**
|
575 |
627 |
* Login command
|
... | ... | |
1036 |
1088 |
|
1037 |
1089 |
lock_assert(&global_lock);
|
1038 |
1090 |
|
1039 |
|
TAILQ_FOREACH(cwc, &cwcs, cwc_link)
|
1040 |
|
if(cwc->cwc_forward_emm && cwc->cwc_writer_running &&
|
1041 |
|
data[0] == 0x82 /* Conax */ ) {
|
1042 |
|
int i;
|
1043 |
|
for (i=0; i < cwc->cwc_num_providers; i++)
|
1044 |
|
if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
|
1045 |
|
cwc_send_msg(cwc, data, len, 0, 1);
|
1046 |
|
break;
|
1047 |
|
}
|
|
1091 |
TAILQ_FOREACH(cwc, &cwcs, cwc_link) {
|
|
1092 |
if(cwc->cwc_forward_emm && cwc->cwc_writer_running) {
|
|
1093 |
switch (cwc->cwc_card_type) {
|
|
1094 |
case CARD_CONAX:
|
|
1095 |
cwc_emm_conax(cwc, data, len);
|
|
1096 |
break;
|
|
1097 |
case CARD_IRDETO:
|
|
1098 |
cwc_emm_irdeto(cwc, data, len);
|
|
1099 |
break;
|
|
1100 |
case CARD_SECA:
|
|
1101 |
cwc_emm_seca(cwc, data, len);
|
|
1102 |
break;
|
|
1103 |
case CARD_UNKNOWN:
|
|
1104 |
break;
|
|
1105 |
}
|
1048 |
1106 |
}
|
|
1107 |
}
|
1049 |
1108 |
}
|
1050 |
1109 |
|
1051 |
1110 |
|
1052 |
1111 |
/**
|
|
1112 |
* conax emm handler
|
|
1113 |
*/
|
|
1114 |
void
|
|
1115 |
cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len)
|
|
1116 |
{
|
|
1117 |
if (data[0] == 0x82) {
|
|
1118 |
int i;
|
|
1119 |
for (i=0; i < cwc->cwc_num_providers; i++) {
|
|
1120 |
if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
|
|
1121 |
cwc_send_msg(cwc, data, len, 0, 1);
|
|
1122 |
break;
|
|
1123 |
}
|
|
1124 |
}
|
|
1125 |
}
|
|
1126 |
}
|
|
1127 |
|
|
1128 |
|
|
1129 |
/**
|
|
1130 |
* irdeto emm handler
|
|
1131 |
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
|
|
1132 |
*/
|
|
1133 |
void
|
|
1134 |
cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len)
|
|
1135 |
{
|
|
1136 |
int emm_mode = data[3] >> 3;
|
|
1137 |
int emm_len = data[3] & 0x07;
|
|
1138 |
int match = 0;
|
|
1139 |
|
|
1140 |
if (emm_mode & 0x10) {
|
|
1141 |
// try to match card
|
|
1142 |
match = (emm_mode == cwc->cwc_ua[4] &&
|
|
1143 |
(!emm_len || // zero length
|
|
1144 |
!memcmp(&data[4], &cwc->cwc_ua[5], emm_len))); // exact match
|
|
1145 |
}
|
|
1146 |
else {
|
|
1147 |
// try to match provider
|
|
1148 |
int i;
|
|
1149 |
for(i=0; i < cwc->cwc_num_providers; i++) {
|
|
1150 |
match = (emm_mode == cwc->cwc_providers[i].sa[4] &&
|
|
1151 |
(!emm_len || // zero length
|
|
1152 |
!memcmp(&data[4], &cwc->cwc_providers[i].sa[5], emm_len))); // exact match
|
|
1153 |
if (match) break;
|
|
1154 |
}
|
|
1155 |
}
|
|
1156 |
|
|
1157 |
if (match)
|
|
1158 |
cwc_send_msg(cwc, data, len, 0, 1);
|
|
1159 |
}
|
|
1160 |
|
|
1161 |
|
|
1162 |
/**
|
|
1163 |
* seca emm handler
|
|
1164 |
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
|
|
1165 |
*/
|
|
1166 |
void
|
|
1167 |
cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len)
|
|
1168 |
{
|
|
1169 |
int match = 0;
|
|
1170 |
|
|
1171 |
if (data[0] == 0x82) {
|
|
1172 |
if (memcmp(&data[3], &cwc->cwc_ua[2], 6) == 0) {
|
|
1173 |
match = 1;
|
|
1174 |
}
|
|
1175 |
}
|
|
1176 |
else if (data[0] == 0x84) {
|
|
1177 |
/* XXX this part is untested */
|
|
1178 |
int i;
|
|
1179 |
for (i=0; i < cwc->cwc_num_providers; i++) {
|
|
1180 |
if (memcmp(&data[5], &cwc->cwc_providers[i].sa[5], 3) == 0) {
|
|
1181 |
match = 1;
|
|
1182 |
break;
|
|
1183 |
}
|
|
1184 |
}
|
|
1185 |
}
|
|
1186 |
|
|
1187 |
if (match)
|
|
1188 |
cwc_send_msg(cwc, data, len, 0, 1);
|
|
1189 |
}
|
|
1190 |
|
|
1191 |
|
|
1192 |
/**
|
1053 |
1193 |
*
|
1054 |
1194 |
*/
|
1055 |
1195 |
static void
|