From 891ed4eb1ab6e5632a547f4b1e0852733a3f4ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Mon, 13 Jul 2009 20:36:51 +0000 Subject: [PATCH] Verify that cwc utilize correct ECM stream based on provider id. --- src/cwc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/psi.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/tvhead.h | 1 + 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index a2d2afc7..2d5d6a7e 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -162,6 +162,11 @@ typedef struct cwc { uint8_t cwc_buf[256]; int cwc_bufptr; + /* Provder IDs */ + + uint32_t cwc_provider_ids[256]; + int cwc_num_providers; + /* From configuration */ uint8_t cwc_confedkey[14]; @@ -419,7 +424,9 @@ cwc_send_ka(cwc_t *cwc) static int cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) { - int plen; + int plen, i; + unsigned int nprov; + uint32_t id; const char *n; msg += 12; @@ -433,7 +440,14 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) plen = (msg[1] & 0xf) << 8 | msg[2]; if(plen < 14) { - tvhlog(LOG_INFO, "cwc", "Invalid card data reply"); + tvhlog(LOG_INFO, "cwc", "Invalid card data reply (message)"); + return -1; + } + + nprov = msg[14]; + + if(plen < nprov * 11) { + tvhlog(LOG_INFO, "cwc", "Invalid card data reply (provider list)"); return -1; } @@ -446,7 +460,20 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) cwc->cwc_hostname, msg[3], n, cwc->cwc_caid, msg[6], msg[7], msg[8], msg[9], msg[10], msg[11], msg[12], msg[13], - msg[14]); + nprov); + + msg += 15; + plen -= 12; + + cwc->cwc_num_providers = nprov; + + for(i = 0; i < nprov; i++) { + id = (msg[0] << 16) | (msg[1] << 8) | msg[2]; + tvhlog(LOG_INFO, "cwc", "%s: Provider ID #%d: 0x%06x", + cwc->cwc_hostname, i + 1 , id); + cwc->cwc_provider_ids[i] = id; + msg += 11; + } return 0; } @@ -513,6 +540,7 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len) if(ct->ct_keystate != CT_RESOLVED) tvhlog(LOG_INFO, "cwc", "Obtained key for for service \"%s\"",t->tht_svcname); + ct->ct_keystate = CT_RESOLVED; pthread_mutex_lock(&t->tht_stream_mutex); set_control_words(ct->ct_keys, msg + 3, msg + 3 + 8); @@ -784,6 +812,24 @@ cwc_thread(void *aux) } +/** + * + */ +static int +verify_provider(cwc_t *cwc, uint32_t providerid) +{ + int i; + + if(providerid == 0) + return 1; + + for(i = 0; i < cwc->cwc_num_providers; i++) + if(providerid == cwc->cwc_provider_ids[i]) + return 1; + return 0; +} + + /** * */ @@ -798,6 +844,9 @@ cwc_table_input(struct th_descrambler *td, struct th_transport *t, if(cwc->cwc_caid != st->st_caid) return; + if(!verify_provider(cwc, st->st_providerid)) + return; + if((data[0] & 0xf0) != 0x80) return; diff --git a/src/psi.c b/src/psi.c index 9fdf3115..6320fb8d 100644 --- a/src/psi.c +++ b/src/psi.c @@ -161,7 +161,39 @@ psi_build_pat(th_transport_t *t, uint8_t *buf, int maxlen, int pmtpid) } +/** + * Parser for CA descriptor, viaccess + */ +static int +psi_desc_ca_viaccess(th_transport_t *t, th_stream_t *st, uint8_t *ptr, int len) +{ + uint8_t tag, tlen; + uint32_t id; + while(len > 2) { + tag = ptr[0]; + tlen = ptr[1]; + + ptr += 2; + len -= 2; + + if(len < tlen) + return 0; + + switch(tag) { + case 0x14: + id = (ptr[0] << 16) | (ptr[1] << 8) | (ptr[2] & 0xf0); + + if(id != st->st_providerid) { + st->st_providerid = id; + return 1; + } + } + len -= tlen; + ptr += tlen; + } + return 0; +} @@ -169,7 +201,7 @@ psi_build_pat(th_transport_t *t, uint8_t *buf, int maxlen, int pmtpid) * Parser for CA descriptor */ static int -psi_desc_ca(th_transport_t *t, uint8_t *ptr) +psi_desc_ca(th_transport_t *t, uint8_t *ptr, int len) { uint16_t pid = (ptr[2] & 0x1f) << 8 | ptr[3]; th_stream_t *st; @@ -187,6 +219,16 @@ psi_desc_ca(th_transport_t *t, uint8_t *ptr) st->st_caid = caid; r = 1; } + + len -= 4; + ptr += 4; + + switch(caid >> 8) { + case 5: + r |= psi_desc_ca_viaccess(t, st, ptr, len); + break; + } + return r; } @@ -247,7 +289,7 @@ psi_parse_pmt(th_transport_t *t, uint8_t *ptr, int len, int chksvcid) switch(dtag) { case DVB_DESC_CA: - update |= psi_desc_ca(t, ptr); + update |= psi_desc_ca(t, ptr, dlen); break; default: @@ -300,7 +342,7 @@ psi_parse_pmt(th_transport_t *t, uint8_t *ptr, int len, int chksvcid) switch(dtag) { case DVB_DESC_CA: - update |= psi_desc_ca(t, ptr); + update |= psi_desc_ca(t, ptr, dlen); break; case DVB_DESC_VIDEO_STREAM: @@ -647,9 +689,13 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t) if(st->st_lang[0]) htsmsg_add_str(sub, "language", st->st_lang); - if(st->st_type == SCT_CA) + if(st->st_type == SCT_CA) { htsmsg_add_str(sub, "caid", psi_caid2name(st->st_caid)); + if(st->st_providerid) + htsmsg_add_u32(sub, "caproviderid", st->st_providerid); + } + if(st->st_frame_duration) htsmsg_add_u32(sub, "frameduration", st->st_frame_duration); @@ -710,5 +756,7 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t) i = str2val(v, caidnametab); st->st_caid = i < 0 ? strtol(v, NULL, 0) : i; } + + htsmsg_get_u32(c, "caproviderid", &st->st_providerid); } } diff --git a/src/tvhead.h b/src/tvhead.h index 7742f302..2d637dd9 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -306,6 +306,7 @@ typedef struct th_stream { /* ca id for this stream */ uint16_t st_caid; + uint32_t st_providerid; /* Remuxing information */ AVRational st_tb;