source: trunk/module-newcamd.c@ 8456

Last change on this file since 8456 was 8456, checked in by gf, 9 years ago

Slim down struct s_port.

struct s_port contains filter array and couple of other fields that are
used only for newcamd and nothing else. They waste more than 2k in common
case.

To stop losing this much space, create private structure only for
newcamd fields and allocate it dynamically. This lowers struct s_port
size a lot and of course struct s_ptab even more because it contains
array of struct s_ports's.

New structure sizes (32-bit):

                  before  after
  struct s_port     2144     12
  struct s_ptab    68612    388
  struct s_config 141260   4812

Size report (32-bit):

    text     data      bss      dec    hex filename
  998222     1944   602344  1602510 1873ce before/oscam-1.20-unstable_svn8453-i486-slackware-linux
  998174     1944    61800  1061918 10341e  after/oscam-1.20-unstable_svn8453-i486-slackware-linux

bloat-o-meter report (32-bit):

  add/remove: 0/1 grow/shrink: 13/16 up/down: 7897/-548383 (-540486)
  function                                     old     new   delta
  modules                                     1840    9520   +7680
  ...
  cfg                                       141260    4812 -136448
  static.ptab                               411672       - -411672
  • Property svn:eol-style set to LF
File size: 42.2 KB
Line 
1#include "globals.h"
2#ifdef MODULE_NEWCAMD
3#include "cscrypt/des.h"
4#include "cscrypt/md5.h"
5#include "module-newcamd.h"
6#include "oscam-chk.h"
7#include "oscam-client.h"
8#include "oscam-ecm.h"
9#include "oscam-emm.h"
10#include "oscam-net.h"
11#include "oscam-reader.h"
12#include "oscam-string.h"
13#include "oscam-time.h"
14
15#define CWS_NETMSGSIZE 362
16#define NCD_CLIENT_ID 0x8888
17
18#define CWS_FIRSTCMDNO 0xe0
19typedef enum
20{
21 MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
22 MSG_CLIENT_2_SERVER_LOGIN_ACK,
23 MSG_CLIENT_2_SERVER_LOGIN_NAK,
24 MSG_CARD_DATA_REQ,
25 MSG_CARD_DATA,
26 MSG_SERVER_2_CLIENT_NAME,
27 MSG_SERVER_2_CLIENT_NAME_ACK,
28 MSG_SERVER_2_CLIENT_NAME_NAK,
29 MSG_SERVER_2_CLIENT_LOGIN,
30 MSG_SERVER_2_CLIENT_LOGIN_ACK,
31 MSG_SERVER_2_CLIENT_LOGIN_NAK,
32 MSG_ADMIN,
33 MSG_ADMIN_ACK,
34 MSG_ADMIN_LOGIN,
35 MSG_ADMIN_LOGIN_ACK,
36 MSG_ADMIN_LOGIN_NAK,
37 MSG_ADMIN_COMMAND,
38 MSG_ADMIN_COMMAND_ACK,
39 MSG_ADMIN_COMMAND_NAK,
40 MSG_KEEPALIVE = CWS_FIRSTCMDNO + 0x1d,
41 MSG_SERVER_2_CLIENT_OSD = 0xd1,
42 MSG_SERVER_2_CLIENT_ALLCARDS = 0xd2,
43 MSG_SERVER_2_CLIENT_ADDCARD = 0xd3,
44 MSG_SERVER_2_CLIENT_REMOVECARD = 0xd4,
45 MSG_SERVER_2_CLIENT_CHANGE_KEY = 0xd5,
46 MSG_SERVER_2_CLIENT_GET_VERSION = 0xd6,
47 MSG_SERVER_2_CLIENT_ADDSID = 0xd7,
48 MSG_CLIENT_2_SERVER_CARDDISCOVER = 0xd8
49} net_msg_type_t;
50
51typedef enum
52{
53 COMMTYPE_CLIENT,
54 COMMTYPE_SERVER
55} comm_type_t;
56
57
58typedef struct custom_data
59{
60 uint16_t sid;
61 uint16_t caid;
62 int32_t provid;
63 uchar x;
64} custom_data_t;
65
66#define REQ_SIZE 2
67
68static int32_t network_message_send(int32_t handle, uint16_t *netMsgId, uint8_t *buffer,
69 int32_t len, uint8_t *deskey, comm_type_t commType,
70 uint16_t sid, custom_data_t *cd)
71{
72 uint8_t netbuf[CWS_NETMSGSIZE];
73 int32_t head_size;
74 struct s_client *cl = cur_client();
75
76 head_size = (cl->ncd_proto==NCD_524)?8:12;
77
78 if (len < 3 || len + head_size > CWS_NETMSGSIZE || handle < 0)
79 return -1;
80 buffer[1] = (buffer[1] & 0xf0) | (((len - 3) >> 8) & 0x0f);
81 buffer[2] = (len - 3) & 0xff;
82 memcpy(netbuf+head_size, buffer, len);
83 len += head_size;
84 if (netMsgId) {
85 if(commType==COMMTYPE_CLIENT) (*netMsgId)++;
86 netbuf[2] = (*netMsgId) >> 8;
87 netbuf[3] = (*netMsgId) & 0xff;
88 }
89 else
90 netbuf[2] = netbuf[3] = 0;
91 memset(netbuf+4, 0, (cl->ncd_proto==NCD_524)?4:8);
92 if( sid ) {
93 if (cl->reader && cl->reader->ncd_disable_server_filt &&
94 sid != NCD_CLIENT_ID && cl->ncd_proto!=NCD_524) { //mgclient send header
95 memcpy(netbuf+4, cl->ncd_header+4, 7);
96 }
97 netbuf[(cl->ncd_proto==NCD_524)?6:4] = (uchar)(sid>>8); //sid
98 netbuf[(cl->ncd_proto==NCD_524)?7:5] = (uchar)(sid);
99 }
100 //if ((!ncd_proto==NCD_524) && (buffer[0] >= 0xd1) && (buffer[0]<= 0xd8)) { // extended proto for mg
101 //cs_debug_mask(D_CLIENT, "newcamd: extended: msg");
102 if (cd) {
103 cs_debug_mask(D_CLIENT, "newcamd: has cd");
104 netbuf[4] = cd->sid >> 8;
105 netbuf[5] = cd->sid & 0xff;
106 netbuf[6] = cd->caid >> 8;
107 netbuf[7] = cd->caid & 0xff;
108 netbuf[8] = (cd->provid >> 16) & 0xFF;
109 netbuf[9] = (cd->provid >> 8) & 0xff;
110 netbuf[10] = cd->provid & 0xff;
111 }
112 //}
113 if (NCD_525 == cl->ncd_proto && cfg.ncd_mgclient &&
114 MSG_CLIENT_2_SERVER_LOGIN_ACK == buffer[0]) {
115 netbuf[4] = 0x6E; //From ExtNewcamSession.java CSP line 65-66 getLoginOkMsg()
116 netbuf[5] = 0x73;
117 netbuf[11] = 0x14;
118 }
119 if (NCD_525 == cl->ncd_proto &&
120 MSG_SERVER_2_CLIENT_ADDSID == buffer[0]) {
121 netbuf[11] = 0x14;
122 }
123// if (buffer[0]==MSG_CLIENT_2_SERVER_LOGIN && cur_client()->reader->ncd_disable_server_filt) {
124// netbuf[11] = 0x11; //From ChameleonCwsConnector.java CSP line 59-61 run()
125// }
126
127 netbuf[0] = (len - 2) >> 8;
128 netbuf[1] = (len - 2) & 0xff;
129 cs_ddump_mask(D_CLIENT, netbuf, len, "send %d bytes to %s", len, remote_txt());
130 if ((len = des_encrypt(netbuf, len, deskey)) < 0)
131 return -1;
132 netbuf[0] = (len - 2) >> 8;
133 netbuf[1] = (len - 2) & 0xff;
134 return send(handle, netbuf, len, 0);
135}
136
137static int32_t send_sid_list(void)
138{
139 struct s_client *cl = cur_client();
140
141 if(1 != cl->ftab.nfilts || !cl->sidtabs.no)
142 {
143 cs_log("SID list will not be send to mgcamd client.");
144 return 0;
145 }
146
147 uchar mbuf[CWS_NETMSGSIZE];
148 int32_t n = 0, nr = 0, portion_sid_num = 0, i = 0, sid_num = 0,
149 portion_num = 0;
150 SIDTAB *sidtab = 0;
151 custom_data_t cd;
152
153 cs_debug_mask(D_TRACE,"Send SID list to mgcamd client.");
154 memset(&cd, 0, sizeof(cd));
155 FILTER *pfilts = cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts;
156
157 /*memset(mbuf, 0, sizeof(mbuf));*/ // not nessesery
158
159 for (nr=0, sidtab=cfg.sidtab; sidtab; sidtab=sidtab->next, nr++)
160 if ((cl->sidtabs.no&((SIDTABBITS)1<<nr)) && (sidtab->num_caid | sidtab->num_provid | sidtab->num_srvid))
161 {
162 for(n = 0; n < pfilts[0].nprids; n++)
163 {
164 if(chk_srvid_match_by_caid_prov(pfilts[0].caid, pfilts[0].prids[n], sidtab))
165 {
166 for(i = 0; i < sidtab->num_srvid; i++)
167 {
168 // First SID goes to header
169 if(0 == portion_sid_num)
170 {
171 cd.sid = sidtab->srvid[i]; // first sid
172 cd.caid = cfg.ncd_ptab.ports[cl->port_idx].s_port; //assigned port
173 cd.provid = 0x1; // mark as deny
174 }
175 mbuf[portion_sid_num*3] = (uchar)(sidtab->srvid[i] >> 8);
176 mbuf[portion_sid_num*3 +1] = (uchar)(sidtab->srvid[i] & 0xFF);
177 mbuf[portion_sid_num*3 +2] = 0x1; // mark as deny
178
179 ++sid_num;
180 ++portion_sid_num;
181
182 if(portion_sid_num >= 50)
183 {
184 ++portion_num;
185 cs_ddump_mask(0x0800, mbuf, (portion_sid_num)*3, "Portion %d contains %d SIDs", portion_num, portion_sid_num);
186 mbuf[0] = MSG_SERVER_2_CLIENT_ADDSID;
187 mbuf[1] = 0x0;
188 mbuf[2] = 0x0;
189 network_message_send(cl->udp_fd, &cl->ncd_msgid,
190 mbuf, portion_sid_num*3, cl->ncd_skey, COMMTYPE_SERVER, 0, &cd);
191 portion_sid_num = 0;
192 }
193 }
194
195 break;
196 }
197 }
198 }
199
200 if(portion_sid_num)
201 {
202 ++portion_num;
203 cs_ddump_mask(0x0800, mbuf, (portion_sid_num)*3, "Portion %d contains %d SIDs", portion_num, portion_sid_num);
204 mbuf[0] = MSG_SERVER_2_CLIENT_ADDSID;
205 mbuf[1] = 0x0;
206 mbuf[2] = 0x0;
207 network_message_send(cl->udp_fd, &cl->ncd_msgid, mbuf, portion_sid_num*3, cl->ncd_skey, COMMTYPE_SERVER, 0, &cd);
208 portion_sid_num = 0;
209 }
210
211 cs_log("%d deny SIDs in the %d messages were sent to the client.", sid_num, portion_num);
212 return sid_num;
213}
214
215static int32_t network_message_receive(int32_t handle, uint16_t *netMsgId, uint8_t *buffer,
216 uint8_t *deskey, comm_type_t commType)
217{
218 int32_t len, ncd_off, msgid;
219 uint8_t netbuf[CWS_NETMSGSIZE];
220 int32_t returnLen;
221 struct s_client *cl = cur_client();
222
223 if (!buffer || handle < 0)
224 return -1;
225 len = recv(handle, netbuf, 2, 0);
226 cs_debug_mask(D_CLIENT, "nmr(): len=%d, errno=%d", len, (len==-1)?errno:0);
227 if (!len) {
228 cs_debug_mask(D_CLIENT, "nmr: 1 return 0");
229 if(commType == COMMTYPE_CLIENT)
230 network_tcp_connection_close(cl->reader, "receive error1");
231 else
232 cs_disconnect_client(cl);
233 return 0;
234 }
235 if (len != 2) {
236 cs_debug_mask(D_CLIENT, "nmr: len!=2");
237 if(commType == COMMTYPE_CLIENT)
238 network_tcp_connection_close(cl->reader, "receive error2");
239 else
240 cs_disconnect_client(cl);
241 return -1;
242 }
243 if (((netbuf[0] << 8) | netbuf[1]) > CWS_NETMSGSIZE - 2) {
244 cs_debug_mask(D_CLIENT, "nmr: received data len=%d lonage than CWS_NETMSGSIZE=%d",((netbuf[0] << 8) | netbuf[1]),CWS_NETMSGSIZE);
245 cs_debug_mask(D_CLIENT, "nmr: 1 return -1");
246 return -1;
247 }
248
249 len = recv(handle, netbuf+2, (netbuf[0] << 8) | netbuf[1], 0);
250 if (!len) {
251 cs_debug_mask(D_CLIENT, "nmr: 2 return 0");
252 return 0;
253 }
254 if (len != ((netbuf[0] << 8) | netbuf[1])) {
255 cs_debug_mask(D_CLIENT, "nmr: 2 return -1");
256 return -1;
257 }
258 len += 2;
259 if ((len = des_decrypt(netbuf, len, deskey)) < 11 ) { // 15(newcamd525) or 11 ???
260 cs_debug_mask(D_CLIENT, "nmr: can't decrypt, invalid des key?");
261 cs_sleepms(2000);
262 return -1;
263 }
264 //cs_ddump_mask(D_CLIENT, netbuf, len, "nmr: decrypted data, len=%d", len);
265 msgid = (netbuf[2] << 8) | netbuf[3];
266
267 if( cl->ncd_proto==NCD_AUTO ) {
268 // auto detect
269 int32_t l5 = (((netbuf[13] & 0x0f) << 8) | netbuf[14]) + 3;
270 int32_t l4 = (((netbuf[9] & 0x0f) << 8) | netbuf[10]) + 3;
271
272 if( (l5<=len-12) && ((netbuf[12]&0xF0)==0xE0 || (netbuf[12]&0xF0)==0x80) )
273 cl->ncd_proto = NCD_525;
274 else if( (l4<=len-8) && ((netbuf[8]&0xF0)==0xE0 || (netbuf[9]&0xF0)==0x80) )
275 cl->ncd_proto = NCD_524;
276 else {
277 cs_debug_mask(D_CLIENT, "nmr: 4 return -1");
278 return -1;
279 }
280
281 cs_debug_mask(D_CLIENT, "nmr: autodetect: newcamd52%d used", (cl->ncd_proto==NCD_525)?5:4);
282 }
283
284 ncd_off=(cl->ncd_proto==NCD_525)?4:0;
285
286 returnLen = (((netbuf[9+ncd_off] & 0x0f) << 8) | netbuf[10+ncd_off]) + 3;
287 if ( returnLen > (len-(8+ncd_off)) ) {
288 cs_debug_mask(D_CLIENT, "nmr: 4 return -1");
289 return -1;
290 }
291
292 //cs_ddump_mask(D_CLIENT, netbuf, len, "nmr: decrypted data");
293 if (netMsgId)
294 {
295 switch (commType)
296 {
297 case COMMTYPE_SERVER:
298 *netMsgId = msgid;
299 break;
300
301 case COMMTYPE_CLIENT:
302 //if (*netMsgId != ((netbuf[2] << 8) | netbuf[3])) {
303 cs_debug_mask(D_CLIENT, "nmr: netMsgId=%d, from server=%d, ", *netMsgId, msgid );
304 //return -2;
305 //}
306 break;
307
308 default:
309 cs_debug_mask(D_CLIENT, "nmr: 5 return -1");
310 return -1;
311 break;
312 }
313 }
314 switch(commType)
315 {
316 case COMMTYPE_SERVER:
317 memcpy(cl->ncd_header, netbuf, (8+ncd_off));
318 buffer[0]=(cl->ncd_proto==NCD_525)?netbuf[4]:netbuf[6]; // sid
319 buffer[1]=(cl->ncd_proto==NCD_525)?netbuf[5]:netbuf[7];
320 break;
321 case COMMTYPE_CLIENT:
322 memcpy(cl->ncd_header, netbuf, (8+ncd_off));
323 buffer[0]=netbuf[2]; // msgid
324 buffer[1]=netbuf[3];
325 break;
326 }
327
328 memcpy(buffer+2, netbuf+(8+ncd_off), returnLen);
329 return returnLen+2;
330}
331
332static void network_cmd_no_data_send(int32_t handle, uint16_t *netMsgId,
333 net_msg_type_t cmd, uint8_t *deskey,
334 comm_type_t commType)
335{
336 uint8_t buffer[3];
337
338 buffer[0] = cmd;
339 buffer[1] = 0;
340 buffer[2] = 0;
341 network_message_send(handle, netMsgId, buffer, 3, deskey, commType, 0, NULL);
342}
343
344static int32_t network_cmd_no_data_receive(int32_t handle, uint16_t *netMsgId,
345 uint8_t *deskey, comm_type_t commType)
346{
347 uint8_t buffer[CWS_NETMSGSIZE];
348
349 if (network_message_receive(handle, netMsgId, buffer, deskey, commType) != 3+2)
350 return -1;
351 return buffer[2];
352}
353
354void newcamd_reply_ka(void)
355{
356 struct s_client *cl = cur_client();
357
358 if (!cl) return;
359
360 if(!cl->udp_fd) {
361 cs_debug_mask(D_CLIENT, "invalid client fd=%d", cl->udp_fd);
362 return;
363 }
364
365 cs_debug_mask(D_CLIENT, "send keepalive to client fd=%d", cl->udp_fd);
366
367 if (cl->reader)
368 cl->reader->last_s = time((time_t *)0);
369
370 network_cmd_no_data_send(cl->udp_fd, &cl->ncd_msgid, MSG_KEEPALIVE, cl->ncd_skey,COMMTYPE_SERVER);
371}
372
373static int32_t connect_newcamd_server(void)
374{
375 int32_t i;
376 uint8_t buf[CWS_NETMSGSIZE];
377 uint8_t keymod[14];
378 uint8_t key[16];
379 int32_t handle=0;
380
381 uint32_t idx;
382 uchar passwdcrypt[120];
383 uint8_t login_answer;
384 int32_t bytes_received;
385 struct s_client *cl = cur_client();
386
387 if(cl->reader->device[0] == 0 || cl->reader->r_pwd[0] == 0 ||
388 cl->reader->r_usr[0] == 0 || cl->reader->r_port == 0)
389 return -5;
390
391 // 1. Connect
392 handle = network_tcp_connection_open(cl->reader);
393 if(handle < 0) return -1;
394
395 // 2. Get init sequence
396 cl->ncd_msgid = 0;
397 if( read(handle, keymod, sizeof(keymod)) != sizeof(keymod)) {
398 cs_log("server does not return 14 bytes");
399 network_tcp_connection_close(cl->reader, "connect error");
400 return -2;
401 }
402 cs_ddump_mask(D_CLIENT, keymod, sizeof(cl->reader->ncd_key), "server init sequence:");
403 des_login_key_get(keymod, cl->reader->ncd_key, sizeof(cl->reader->ncd_key), key);
404
405 // 3. Send login info
406 idx = 3;
407 buf[0] = MSG_CLIENT_2_SERVER_LOGIN;
408 buf[1] = 0;
409 cs_strncpy((char *)buf+idx, cl->reader->r_usr, sizeof(buf)-idx);
410 __md5_crypt(cl->reader->r_pwd, "$1$abcdefgh$", (char *)passwdcrypt);
411 idx += strlen(cl->reader->r_usr)+1;
412 cs_strncpy((char *)buf+idx, (const char *)passwdcrypt, sizeof(buf)-idx);
413
414 network_message_send(handle, 0, buf, idx+strlen((char *)passwdcrypt)+1, key,
415 COMMTYPE_CLIENT, NCD_CLIENT_ID, NULL);
416
417 // 3.1 Get login answer
418 login_answer=network_cmd_no_data_receive(handle, &cl->ncd_msgid,
419 key, COMMTYPE_CLIENT);
420 if( login_answer == MSG_CLIENT_2_SERVER_LOGIN_NAK )
421 {
422 cs_log("login failed for user '%s'", cl->reader->r_usr);
423 network_tcp_connection_close(cl->reader, "login error1");
424 return -3;
425 }
426 if( login_answer != MSG_CLIENT_2_SERVER_LOGIN_ACK )
427 {
428 cs_log("expected MSG_CLIENT_2_SERVER_LOGIN_ACK (%02X), received %02X",
429 MSG_CLIENT_2_SERVER_LOGIN_ACK, login_answer);
430 network_tcp_connection_close(cl->reader, "login error2");
431 return -3;
432 }
433
434 // 3.2 Set connection info
435 cl->reader->tcp_connected = 1;
436 cl->crypted = 1;
437
438 // 4. Send MSG_CARD_DATE_REQ
439 des_login_key_get(cl->reader->ncd_key, passwdcrypt, strlen((char *)passwdcrypt), key);
440
441 network_cmd_no_data_send(handle, &cl->ncd_msgid, MSG_CARD_DATA_REQ,
442 key, COMMTYPE_CLIENT);
443 bytes_received = network_message_receive(handle, &cl->ncd_msgid, buf,
444 key, COMMTYPE_CLIENT);
445 if( bytes_received < 16 || buf[2] != MSG_CARD_DATA ) {
446 cs_log("expected MSG_CARD_DATA (%02X), received %02X",
447 MSG_CARD_DATA, buf[2]);
448 network_tcp_connection_close(cl->reader, "receive error");
449 return -4;
450 }
451
452 // 5. Parse CAID and PROVID(s)
453 cl->reader->caid = (uint16_t)((buf[6]<<8) | buf[7]);
454
455 /* handle special serial format in newcamd. See newcamd_auth_client */
456 newcamd_to_hexserial(buf+10, cl->reader->hexserial, cl->reader->caid);
457 cs_log("Newcamd Server: %s:%d - UserID: %i", cl->reader->device, cl->reader->r_port, buf[3+2]);
458 cs_log("CAID: %04X - UA: %02X%02X%02X%02X%02X%02X%02X%02X - Provider # %i", cl->reader->caid, cl->reader->hexserial[0], cl->reader->hexserial[1], cl->reader->hexserial[2], cl->reader->hexserial[3], cl->reader->hexserial[4], cl->reader->hexserial[5], cl->reader->hexserial[6], cl->reader->hexserial[7], buf[14+2]);
459 cl->reader->nprov = buf[14+2];
460 memset(cl->reader->prid, 0x00, sizeof(cl->reader->prid));
461 for (i=0; i < cl->reader->nprov; i++) {
462 cl->reader->availkeys[i][0] = 1;
463 if (((cl->reader->caid >> 8) == 0x17) ||
464 ((cl->reader->caid >> 8) == 0x06)) //Betacrypt or Irdeto
465 {
466 memcpy(&cl->reader->prid[i], buf+22+2+11*i, 4);
467 }
468 else
469 {
470 cl->reader->prid[i][1] = buf[15+2+11*i];
471 cl->reader->prid[i][2] = buf[16+2+11*i];
472 cl->reader->prid[i][3] = buf[17+2+11*i];
473 }
474 memcpy(&cl->reader->sa[i], buf+22+2+11*i, 4); // the 4 first bytes are not read
475 cs_log("Provider ID: %02X%02X%02X - SA: %02X%02X%02X%02X", cl->reader->prid[i][1], cl->reader->prid[i][2], cl->reader->prid[i][3], cl->reader->sa[i][0], cl->reader->sa[i][1], cl->reader->sa[i][2], cl->reader->sa[i][3]);
476 }
477 memcpy(cl->reader->ncd_skey, key, 16);
478
479 // 6. Set card inserted
480 cl->reader->tcp_connected = 2;
481 cl->reader->card_status = CARD_INSERTED;
482 cl->reader->last_g = cl->reader->last_s = time((time_t *)0);
483
484 // Only after connect() on cl->udp_fd (Linux)
485 cl->pfd=cl->udp_fd;
486
487 if (cl->reader->ncd_disable_server_filt) { //act like mgclient
488 network_cmd_no_data_send(handle, &cl->ncd_msgid, MSG_SERVER_2_CLIENT_GET_VERSION,
489 key, COMMTYPE_CLIENT);
490 }
491
492 return 0;
493}
494
495static int32_t newcamd_connect(void)
496{
497 struct s_client *cl = cur_client();
498
499 if (cl->reader->tcp_connected < 2 && connect_newcamd_server() < 0)
500 return 0;
501
502 if (!cl->udp_fd)
503 return 0;
504
505 return 1;
506}
507
508
509static int32_t newcamd_send(uchar *buf, int32_t ml, uint16_t sid)
510{
511 struct s_client *cl = cur_client();
512
513 if(!newcamd_connect())
514 return(-1);
515
516 return(network_message_send(cl->udp_fd, &cl->ncd_msgid,
517 buf, ml, cl->reader->ncd_skey, COMMTYPE_CLIENT, sid, NULL));
518}
519
520static int32_t newcamd_recv(struct s_client *client, uchar *buf, int32_t UNUSED(l))
521{
522 int32_t rc, rs;
523
524 if (client->typ == 'c')
525 {
526 rs=network_message_receive(client->udp_fd,
527 &client->ncd_msgid, buf,
528 client->ncd_skey, COMMTYPE_SERVER);
529 }
530 else
531 {
532 if (!client->udp_fd) return(-1);
533 rs=network_message_receive(client->udp_fd,
534 &client->ncd_msgid,buf,
535 client->reader->ncd_skey, COMMTYPE_CLIENT);
536 }
537
538 if (rs<5) rc=(-1);
539 else rc=rs;
540
541 cs_ddump_mask(D_CLIENT, buf, rs, "received %d bytes from %s", rs, remote_txt());
542 client->last = time((time_t *) 0);
543
544 if( rc==-1 )
545 {
546 if (rs > 0)
547 cs_log("packet is too small (%d bytes)", rs);
548 else
549 cs_log("Connection closed to %s", remote_txt());
550 }
551 return(rc);
552}
553
554static FILTER mk_user_au_ftab(struct s_reader *aureader)
555{
556 int32_t i,j,found;
557 struct s_client *cl = cur_client();
558 FILTER filt;
559 FILTER *pufilt;
560
561 filt.caid = aureader->caid;
562 if (filt.caid == 0) filt.caid = cl->ftab.filts[0].caid;
563 filt.nprids = 0;
564 memset(&filt.prids, 0, sizeof(filt.prids));
565 pufilt = &cl->ftab.filts[0];
566
567 for( i=0; i<aureader->nprov; i++ )
568 filt.prids[filt.nprids++] = b2i(3, &aureader->prid[i][1]);
569
570 for( i=0; i<pufilt->nprids; i++ )
571 {
572 for( j=found=0; (!found)&&(j<filt.nprids); j++ )
573 if (pufilt->prids[i] == filt.prids[j]) found=1;
574 if( !found )
575 filt.prids[filt.nprids++] = pufilt->prids[i];
576 }
577
578 return filt;
579}
580
581static FILTER mk_user_ftab(void)
582{
583 FILTER *psfilt = 0;
584 FILTER filt;
585 int32_t port_idx,i,j,k,c;
586 struct s_client *cl = cur_client();
587
588 filt.caid = 0;
589 filt.nprids = 0;
590 memset(&filt.prids, 0, sizeof(filt.prids));
591
592 port_idx = cl->port_idx;
593 psfilt = &cfg.ncd_ptab.ports[port_idx].ncd->ncd_ftab.filts[0];
594
595 // 1. CAID
596 // search server CAID in client CAID
597 for( c=i=0; i<CS_MAXCAIDTAB; i++ )
598 {
599 int32_t ctab_caid;
600 ctab_caid = cl->ctab.caid[i]&cl->ctab.mask[i];
601 if( ctab_caid ) c++;
602
603 if( psfilt->caid==ctab_caid )
604 {
605 filt.caid=ctab_caid;
606 break;
607 }
608 }
609 if( c && !filt.caid )
610 {
611 cs_log("no valid CAID found in CAID for user '%s'", cl->account->usr);
612 return filt;
613 }
614
615 // search CAID in client IDENT
616 cs_debug_mask(D_CLIENT, "client[%8lX].%s nfilts=%d, filt.caid=%04X", (unsigned long)pthread_self(),
617 cl->account->usr, cl->ftab.nfilts, filt.caid);
618
619 if( !filt.caid && cl->ftab.nfilts )
620 {
621 int32_t fcaids;
622 for( i=fcaids=0; i<cl->ftab.nfilts; i++ )
623 {
624 uint16_t ucaid=cl->ftab.filts[i].caid;
625 if( ucaid ) fcaids++;
626 if( ucaid && psfilt->caid==ucaid )
627 {
628 filt.caid = ucaid;
629 break;
630 }
631 }
632 if( fcaids==cl->ftab.nfilts && !filt.caid )
633 {
634 cs_log("no valid CAID found in IDENT for user '%s'", cl->account->usr);
635 //cs_disconnect_client();
636 return filt;
637 }
638 }
639 // empty client CAID - use server CAID
640 if( !filt.caid ) filt.caid=psfilt->caid;
641
642 // 2. PROVID
643 if( !cl->ftab.nfilts )
644 {
645 int32_t add;
646 for (i=0; i<psfilt->nprids; i++) {
647 // use server PROVID(s) (and only those which are in user's groups)
648 add = 0;
649 struct s_reader *rdr;
650 for (rdr=first_active_reader; rdr ; rdr=rdr->next)
651 if (rdr->grp & cl->grp) {
652 if (!rdr->ftab.nfilts) {
653 if (is_network_reader(rdr)) add = 1;
654 for (j=0; !add && j<rdr->nprov; j++)
655 if (b2i(3, &rdr->prid[j][1]) == psfilt->prids[i]) add = 1;
656 } else {
657 for (j=0; !add && j<rdr->ftab.nfilts; j++) {
658 uint32_t rcaid = rdr->ftab.filts[j].caid;
659 if (!rcaid || rcaid == filt.caid) {
660 for (k=0; !add && k<rdr->ftab.filts[j].nprids; k++)
661 if (rdr->ftab.filts[j].prids[k] == psfilt->prids[i]) add = 1;
662 }
663 }
664 }
665 }
666 if (add) filt.prids[filt.nprids++] = psfilt->prids[i];
667 }
668 memcpy(&filt, psfilt, sizeof(filt));
669 return filt;
670 }
671
672 // search in client IDENT
673 for( j=0; j<cl->ftab.nfilts; j++ )
674 {
675 uint32_t ucaid = cl->ftab.filts[j].caid;
676 cs_debug_mask(D_CLIENT, "client caid #%d: %04X", j, ucaid);
677 if( !ucaid || ucaid==filt.caid )
678 {
679 for (i=0; i<psfilt->nprids; i++)
680 {
681 cs_debug_mask(D_CLIENT, "search server provid #%d: %06X", i, psfilt->prids[i]);
682 if( cl->ftab.filts[j].nprids )
683 {
684 for( k=0; k<cl->ftab.filts[j].nprids; k++ )
685 if (cl->ftab.filts[j].prids[k] == psfilt->prids[i])
686 filt.prids[filt.nprids++]=cl->ftab.filts[j].prids[k];
687 } else {
688 filt.prids[filt.nprids++] = psfilt->prids[i];
689 // allow server PROVID(s) if no PROVID(s) specified in IDENT
690 }
691 }
692 }
693 }
694
695 if( !filt.nprids )
696 {
697 cs_log("no valid PROVID(s) found in CAID for user '%s'", cl->account->usr);
698 //cs_disconnect_client();
699 }
700
701 return filt;
702}
703
704static int8_t newcamd_auth_client(IN_ADDR_T ip, uint8_t *deskey)
705{
706 int32_t i, ok, rc, sid_list;
707 uchar *usr = NULL, *pwd = NULL;
708 struct s_auth *account;
709 uchar buf[14];
710 uchar key[16];
711 uchar passwdcrypt[120];
712 struct s_reader *aureader = NULL, *rdr = NULL;
713 struct s_client *cl = cur_client();
714 uchar mbuf[CWS_NETMSGSIZE];
715
716 sid_list = 0;
717
718 ok = cfg.ncd_allowed ? check_ip(cfg.ncd_allowed, ip) : 1;
719
720 if (!ok)
721 {
722 cs_auth_client(cl, (struct s_auth *)0, NULL);
723 return -1;
724 }
725
726 // make random 14 bytes
727 get_random_bytes(buf, 14);
728
729 // send init sequence
730 send(cl->udp_fd, buf, 14, 0);
731 des_login_key_get(buf, deskey, 14, key);
732 memcpy(cl->ncd_skey, key, 16);
733 cl->ncd_msgid = 0;
734
735 i=process_input(mbuf, sizeof(mbuf), cfg.cmaxidle);
736 if ( i>0 )
737 {
738 if( mbuf[2] != MSG_CLIENT_2_SERVER_LOGIN )
739 {
740 cs_debug_mask(D_CLIENT, "expected MSG_CLIENT_2_SERVER_LOGIN (%02X), received %02X",
741 MSG_CLIENT_2_SERVER_LOGIN, mbuf[2]);
742 return -1;
743 }
744 usr=mbuf+5;
745 pwd=usr+strlen((char *)usr)+1;
746 }
747 else
748 {
749 cs_debug_mask(D_CLIENT, "bad client login request");
750 return -1;
751 }
752
753 cl->ncd_client_id = (mbuf[0] << 8) | mbuf[1];
754 const char *client_name = newcamd_get_client_name(cl->ncd_client_id);
755#if defined(TCP_KEEPIDLE)
756 if(cl->ncd_client_id == 0x4453){ // DiabloWifi has problems with TCPKeepAlive
757 int32_t flag = 600;
758 if(setsockopt(cl->udp_fd, SOL_TCP, TCP_KEEPIDLE, &flag, sizeof(flag)) && errno != EBADF){ //send first keepalive packet after 600 seconds of last package received (keepalive packets included)
759 cs_log("Setting TCP_KEEPIDLE failed, errno=%d, %s", errno, strerror(errno));
760 } else cs_log("WARNING: Setting TCP_KEEPIDLE to 10 minutes for bugged DiabloWifi. Note that this might lead to not detected broken connections or multiple connections.");
761 }
762#endif
763
764 if(cl->ncd_proto==NCD_525 && 0x6D == mbuf[0]
765 && 0x67 == mbuf[1] && 0x11 == cl->ncd_header[11])
766 {
767 sid_list = 1;
768 }
769
770 for (ok=0, account=cfg.account; (usr) && (account) && (!ok); account=account->next)
771 {
772 cs_debug_mask(D_CLIENT, "account->usr=%s", account->usr);
773 if (strcmp((char *)usr, account->usr) == 0)
774 {
775 __md5_crypt(ESTR(account->pwd), "$1$abcdefgh$", (char *)passwdcrypt);
776 cs_debug_mask(D_CLIENT, "account->pwd=%s", passwdcrypt);
777 if (strcmp((char *)pwd, (const char *)passwdcrypt) == 0)
778 {
779 cl->crypted=1;
780 char e_txt[20];
781 snprintf(e_txt, 20, "%s:%d", "newcamd", cfg.ncd_ptab.ports[cl->port_idx].s_port);
782 if((rc = cs_auth_client(cl, account, e_txt)) == 2) {
783 cs_log("hostname or ip mismatch for user %s (%s)", usr, client_name);
784 break;
785 }
786 else if (rc != 0)
787 {
788 cs_log("account is invalid for user %s (%s)", usr, client_name);
789 break;
790 }
791 else
792 {
793 cs_log("user %s authenticated successfully (%s)", usr, client_name);
794 ok = 1;
795 break;
796 }
797 }
798 else
799 cs_log("user %s is providing a wrong password (%s)", usr, client_name);
800 }
801 }
802
803 if (!ok && !account)
804 {
805 cs_log("user %s is trying to connect but doesnt exist ! (%s)", usr, client_name);
806 usr = 0;
807 }
808
809 // check for non ready reader and reject client
810 for (rdr=first_active_reader; rdr ; rdr=rdr->next) {
811 if(rdr->caid==cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts[0].caid) {
812 if(rdr->card_status == CARD_NEED_INIT) {
813 cs_log("init for reader %s not finished -> reject client", rdr->label);
814 ok = 0;
815 }
816 break;
817 }
818 }
819
820 if (ok) {
821 LL_ITER itr = ll_iter_create(cl->aureader_list);
822 while ((rdr = ll_iter_next(&itr))) {
823 int32_t n;
824 for (n=0;n<cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts[0].nprids;n++) {
825 if (emm_reader_match(rdr, cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts[0].caid, cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts[0].prids[n])) {
826 aureader=rdr;
827 break;
828 }
829 }
830 if (aureader)
831 break;
832 }
833
834 if (aureader) {
835 cs_log("AU enabled for user %s on reader %s", usr, aureader->label);
836 } else {
837 cs_log("AU disabled for user %s", usr);
838 }
839 }
840
841 network_cmd_no_data_send(cl->udp_fd, &cl->ncd_msgid,
842 (ok)?MSG_CLIENT_2_SERVER_LOGIN_ACK:MSG_CLIENT_2_SERVER_LOGIN_NAK,
843 cl->ncd_skey, COMMTYPE_SERVER);
844
845 if (ok)
846 {
847 FILTER *pufilt = 0;
848
849 des_login_key_get(deskey, passwdcrypt, strlen((char *)passwdcrypt), key);
850 memcpy(cl->ncd_skey, key, 16);
851
852 i=process_input(mbuf, sizeof(mbuf), cfg.cmaxidle);
853 if( i>0 )
854 {
855 int32_t j,len=15;
856 if( mbuf[2] != MSG_CARD_DATA_REQ)
857 {
858 cs_debug_mask(D_CLIENT, "expected MSG_CARD_DATA_REQ (%02X), received %02X",
859 MSG_CARD_DATA_REQ, mbuf[2]);
860 return -1;
861 }
862
863 // set userfilter
864 cl->ftab.filts[0] = mk_user_ftab();
865
866 // set userfilter for au enabled clients
867 if (aureader)
868 cl->ftab.filts[0] = mk_user_au_ftab(aureader);
869
870 pufilt = &cl->ftab.filts[0];
871 if (cfg.ncd_mgclient)
872 cl->ftab.nfilts = 0; //We cannot filter all cards!
873 else
874 cl->ftab.nfilts = 1;
875
876 mbuf[0] = MSG_CARD_DATA;
877 mbuf[1] = 0x00;
878 mbuf[2] = 0x00;
879
880 if(aureader)
881 mbuf[3] = 1;
882 else
883 mbuf[3] = get_threadnum(cl)+10; // Unique user number
884
885 mbuf[4] = (uchar)(pufilt->caid>>8);
886 mbuf[5] = (uchar)(pufilt->caid);
887 mbuf[6] = 0x00;
888 mbuf[7] = 0x00;
889
890 if (aureader)
891 hexserial_to_newcamd(aureader->hexserial, mbuf+8, pufilt->caid);
892 else
893 memset(&mbuf[8], 0, 6); //mbuf[8] - mbuf[13]
894
895 mbuf[14] = pufilt->nprids;
896 for( j=0; j<pufilt->nprids; j++)
897 {
898 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
899 {
900 mbuf[15+11*j] = 0;
901 mbuf[16+11*j] = 0;
902 mbuf[17+11*j] = j;
903 }
904 else
905 {
906 mbuf[15+11*j] = (uchar)(pufilt->prids[j]>>16);
907 mbuf[16+11*j] = (uchar)(pufilt->prids[j]>>8);
908 mbuf[17+11*j] = (uchar)(pufilt->prids[j]);
909 }
910 mbuf[18+11*j] = 0x00;
911 mbuf[19+11*j] = 0x00;
912 mbuf[20+11*j] = 0x00;
913 mbuf[21+11*j] = 0x00;
914 if (aureader)
915 {
916 // check if user provid from IDENT exists on card
917 int32_t k, found;
918 uint32_t rprid;
919 found=0;
920 if( pufilt->caid==aureader->caid )
921 {
922 for( k=0; (k<aureader->nprov); k++ )
923 {
924 rprid=b2i(3, &aureader->prid[k][1]);
925 if( rprid==pufilt->prids[j] )
926 {
927 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
928 {
929 mbuf[22+11*j] = aureader->prid[k][0];
930 mbuf[23+11*j] = aureader->prid[k][1];
931 mbuf[24+11*j] = aureader->prid[k][2];
932 mbuf[25+11*j] = aureader->prid[k][3];
933 }
934 else
935 {
936 mbuf[22+11*j] = aureader->sa[k][0];
937 mbuf[23+11*j] = aureader->sa[k][1];
938 mbuf[24+11*j] = aureader->sa[k][2];
939 mbuf[25+11*j] = aureader->sa[k][3];
940 }
941 found=1;
942 break;
943 }
944 }
945 }
946 if( !found )
947 {
948 mbuf[22+11*j] = 0x00;
949 mbuf[23+11*j] = 0x00;
950 mbuf[24+11*j] = 0x00;
951 mbuf[25+11*j] = 0x00;
952 }
953 }
954 else
955 {
956 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
957 {
958 mbuf[22+11*j] = 0x00;
959 mbuf[23+11*j] = (uchar)(pufilt->prids[j]>>16);
960 mbuf[24+11*j] = (uchar)(pufilt->prids[j]>>8);
961 mbuf[25+11*j] = (uchar)(pufilt->prids[j]);
962 }
963 else
964 {
965 mbuf[22+11*j] = 0x00;
966 mbuf[23+11*j] = 0x00;
967 mbuf[24+11*j] = 0x00;
968 mbuf[25+11*j] = 0x00;
969 }
970 }
971 len+=11;
972 }
973
974 custom_data_t cd;
975 memset(&cd, 0, sizeof(cd));
976
977 if (aureader)
978 {
979 if (aureader->blockemm & EMM_GLOBAL)
980 cd.sid |= 4;
981 if (aureader->blockemm & EMM_SHARED)
982 cd.sid |= 2;
983 if (aureader->blockemm & EMM_UNIQUE)
984 cd.sid |= 1;
985 }
986
987 if( network_message_send(cl->udp_fd, &cl->ncd_msgid,
988 mbuf, len, key, COMMTYPE_SERVER, 0, &cd) <0 )
989 {
990 return -1;
991 }
992 }
993
994 // send SID list
995 if (sid_list)
996 send_sid_list();
997 }
998 else
999 {
1000 cs_auth_client(cl, 0, usr ? "login failure" : "no such user");
1001 return -1;
1002 }
1003 return 0;
1004}
1005
1006static void newcamd_send_dcw(struct s_client *client, ECM_REQUEST *er)
1007{
1008 int32_t len;
1009 uint16_t cl_msgid;
1010 uchar mbuf[19];
1011
1012 if (!client->udp_fd) {
1013 cs_debug_mask(D_CLIENT, "ncd_send_dcw: error: client->udp_fd=%d", client->udp_fd);
1014 return;
1015 }
1016
1017 cl_msgid = er->msgid;
1018 mbuf[0] = er->ecm[0];
1019 if( client->ftab.filts[0].nprids==0 || er->rc >= E_NOTFOUND /*not found*/)
1020 {
1021 len=3;
1022 mbuf[1] = mbuf[2] = 0x00;
1023 }
1024 else
1025 {
1026 len = 19;
1027 mbuf[1] = mbuf[2] = 0x10;
1028 memcpy(mbuf+3, er->cw, 16);
1029 }
1030
1031 cs_debug_mask(D_CLIENT, "ncd_send_dcw: er->msgid=%d, cl_msgid=%d, %02X", er->msgid, cl_msgid, mbuf[0]);
1032
1033 network_message_send(client->udp_fd, &cl_msgid, mbuf, len,
1034 client->ncd_skey, COMMTYPE_SERVER, 0, NULL);
1035}
1036
1037static void newcamd_process_ecm(struct s_client *cl, uchar *buf, int32_t len)
1038{
1039 int32_t pi;
1040 ECM_REQUEST *er;
1041
1042 if (!(er=get_ecmtask())) {
1043 return;
1044 }
1045 // save client ncd_msgid
1046 er->msgid = cl->ncd_msgid;
1047 er->ecmlen = buf[4]+3;
1048 cs_debug_mask(D_CLIENT, "ncd_process_ecm: er->msgid=%d len=%d ecmlen=%d", er->msgid, len, er->ecmlen);
1049 er->srvid = cl->ncd_header[4]<<8 | cl->ncd_header[5];
1050 er->caid = cl->ncd_header[6]<<8 | cl->ncd_header[7];
1051 er->prid = cl->ncd_header[8]<<16 | cl->ncd_header[9]<<8 | cl->ncd_header[10];
1052 if (!er->caid) {
1053 pi = cl->port_idx;
1054 if( cfg.ncd_ptab.nports && cfg.ncd_ptab.nports >= pi)
1055 er->caid=cfg.ncd_ptab.ports[pi].ncd->ncd_ftab.filts[0].caid;
1056 }
1057 memcpy(er->ecm, buf+2, er->ecmlen);
1058 get_cw(cl, er);
1059}
1060
1061static void newcamd_process_emm(uchar *buf)
1062{
1063 int32_t ok=1;
1064 uint16_t caid;
1065 struct s_client *cl = cur_client();
1066 EMM_PACKET epg;
1067
1068 memset(&epg, 0, sizeof(epg));
1069
1070 epg.emmlen = buf[2]+3;
1071 caid = cl->ftab.filts[0].caid;
1072 epg.caid[0] = (uchar)(caid>>8);
1073 epg.caid[1] = (uchar)(caid);
1074
1075/*
1076 epg.provid[0] = (uchar)(aureader->auprovid>>24);
1077 epg.provid[1] = (uchar)(aureader->auprovid>>16);
1078 epg.provid[2] = (uchar)(aureader->auprovid>>8);
1079 epg.provid[3] = (uchar)(aureader->auprovid);
1080*/
1081/* if (caid == 0x0500)
1082 {
1083 uint16_t emm_head;
1084
1085 emm_head = (buf[0]<<8) | buf[1];
1086 switch( emm_head )
1087 {
1088 case 0x8e70: // EMM-S
1089 memcpy(epg.hexserial+1, buf+3, 4);
1090 epg.hexserial[4]=aureader->hexserial[4];
1091 break;
1092 case 0x8870: // EMM-U
1093 case 0x8c70: // confidential ?
1094 default:
1095 cs_log("unsupported emm type: %04X", emm_head);
1096 ok=0;
1097 }
1098 if( !ok ) cs_log("only EMM-S supported");
1099 }
1100 else*/
1101
1102 memcpy(epg.emm, buf, epg.emmlen);
1103 if( ok )
1104 do_emm(cl, &epg);
1105
1106 // Should always send an answer to client (also if au is disabled),
1107 // some clients will disconnect if they get no answer
1108 buf[1] = 0x10;
1109 buf[2] = 0x00;
1110 network_message_send(cl->udp_fd, &cl->ncd_msgid, buf, 3,
1111 cl->ncd_skey, COMMTYPE_SERVER, 0, NULL);
1112}
1113
1114static void newcamd_report_cards(struct s_client *client) {
1115 int32_t j, k, l;
1116 uint8_t buf[512];
1117 custom_data_t *cd;
1118 if (!cs_malloc(&cd, sizeof(struct custom_data)))
1119 return;
1120 memset(buf, 0, sizeof(buf));
1121
1122 cd->sid = cfg.ncd_ptab.ports[client->port_idx].s_port;
1123
1124 buf[0] = MSG_SERVER_2_CLIENT_ADDCARD;
1125 struct s_reader *rdr;
1126 for (rdr=first_active_reader; rdr ; rdr=rdr->next) {
1127 int32_t flt = 0;
1128 if (!(rdr->grp & client->grp)) continue; //test - skip unaccesible readers
1129 if (rdr->ftab.filts) {
1130 for (j=0; j<CS_MAXFILTERS; j++) {
1131 if (rdr->ftab.filts[j].caid) {
1132 cd->caid = rdr->ftab.filts[j].caid;
1133 if (!rdr->ftab.filts[j].nprids) {
1134 cd->provid = 0;
1135 cs_debug_mask(D_CLIENT, "newcamd: extended: report card %04X:%06X svc",cd->caid, cd->provid);
1136 network_message_send(client->udp_fd, &client->ncd_msgid, buf, 3, client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1137 }
1138 for (k=0; k<rdr->ftab.filts[j].nprids; k++) {
1139 cd->provid = rdr->ftab.filts[j].prids[k];
1140 cs_debug_mask(D_CLIENT, "newcamd: extended: report card %04X:%06X svc",cd->caid, cd->provid);
1141 network_message_send(client->udp_fd, &client->ncd_msgid, buf, 3, client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1142 flt = 1;
1143 }
1144 }
1145 }
1146 }
1147
1148 if (rdr->caid && !flt) {
1149 if ((rdr->tcp_connected || rdr->card_status == CARD_INSERTED)) {
1150 cd->caid = rdr->caid;
1151 if (!rdr->nprov) {
1152 cd->provid = 0;
1153 cs_debug_mask(D_CLIENT, "newcamd: extended: report card %04X:%06X caid",cd->caid, cd->provid);
1154 network_message_send(client->udp_fd, &client->ncd_msgid, buf, 3, client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1155 }
1156 for (j=0; j<rdr->nprov; j++) {
1157 cd->provid = (rdr->prid[j][1]) << 16 | (rdr->prid[j][2] << 8) | rdr->prid[j][3];
1158 cs_debug_mask(D_CLIENT, "newcamd: extended: report card %04X:%06X caid",cd->caid, cd->provid);
1159 network_message_send(client->udp_fd, &client->ncd_msgid, buf, 3, client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1160 }
1161 }
1162 }
1163 }
1164 if (cfg.sidtab && client->account) {
1165 struct s_sidtab *ptr;
1166 for (j=0,ptr=cfg.sidtab; ptr; ptr=ptr->next,j++) {
1167 if (client->account->sidtabs.ok&((SIDTABBITS)1<<j))
1168 for (k=0;k<ptr->num_caid;k++) {
1169 cd->caid = ptr->caid[k];
1170 if (!ptr->num_provid) {
1171 cd->provid = 0;
1172 cs_debug_mask(D_CLIENT, "newcamd: extended: report card %04X:%06X acs",cd->caid, cd->provid);
1173 network_message_send(client->udp_fd, &client->ncd_msgid, buf, 3, client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1174 }
1175 for (l=0;l<ptr->num_provid;l++) {
1176 cd->provid = ptr->provid[l];
1177 cs_debug_mask(D_CLIENT, "newcamd: extended: report card %04X:%06X acs",cd->caid, cd->provid);
1178 network_message_send(client->udp_fd, &client->ncd_msgid, buf, 3, client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1179 }
1180 }
1181 }
1182 }
1183 free(cd);
1184
1185}
1186
1187static void newcamd_server_init(struct s_client *client) {
1188 int8_t res = 0;
1189
1190 client->ncd_server = 1;
1191 cs_log("client connected to %d port", cfg.ncd_ptab.ports[client->port_idx].s_port);
1192
1193 if (cfg.ncd_ptab.ports[client->port_idx].ncd->ncd_key_is_set) {
1194 //port has a des key specified
1195 res = newcamd_auth_client(client->ip, cfg.ncd_ptab.ports[client->port_idx].ncd->ncd_key);
1196 } else {
1197 //default global des key
1198 res = newcamd_auth_client(client->ip, cfg.ncd_key);
1199 }
1200
1201 if (res == -1) {
1202 cs_disconnect_client(client);
1203 return;
1204 }
1205
1206 // report all cards if using extended mg proto
1207 if (cfg.ncd_mgclient) {
1208 cs_debug_mask(D_CLIENT, "newcamd: extended: report all available cards");
1209 newcamd_report_cards(client);
1210 }
1211
1212}
1213
1214#define EXT_VERSION_STR "1.67"
1215#define EXT_VERSION_LEN 4
1216
1217static void newcamd_send_version(struct s_client *client)
1218{
1219 uchar buf[30];
1220 memset(buf, 0, sizeof(buf));
1221 buf[0] = MSG_SERVER_2_CLIENT_GET_VERSION;
1222 buf[1] = EXT_VERSION_LEN>>8;
1223 buf[2] = EXT_VERSION_LEN & 0xFF;
1224 memcpy(buf+3, EXT_VERSION_STR, EXT_VERSION_LEN);
1225 network_message_send(client->udp_fd, &client->ncd_msgid, buf, EXT_VERSION_LEN+3, client->ncd_skey, COMMTYPE_SERVER, 0, NULL);
1226}
1227
1228static void * newcamd_server(struct s_client *client, uchar *mbuf, int32_t len)
1229{
1230 // check for clienttimeout, if timeout occurs try to send keepalive / wait for answer
1231 // befor client was disconnected. If keepalive was disabled, exit after clienttimeout
1232
1233 if (len<3)
1234 return NULL;
1235
1236 cs_debug_mask(D_CLIENT, "newcamd: got cmd %d", mbuf[2]);
1237
1238 switch(mbuf[2]) {
1239 case 0x80:
1240 case 0x81:
1241 newcamd_process_ecm(client, mbuf, len);
1242 break;
1243
1244 case MSG_SERVER_2_CLIENT_GET_VERSION:
1245 cs_debug_mask(D_CLIENT, "newcamd: extended: send Version 1.67");
1246 newcamd_send_version(client);
1247 break;
1248
1249 case MSG_KEEPALIVE:
1250 newcamd_reply_ka();
1251 break;
1252
1253 default:
1254 if(mbuf[2]>0x81 && mbuf[2]<0x90)
1255 newcamd_process_emm(mbuf+2);
1256 else {
1257 cs_debug_mask(D_CLIENT, "unknown newcamd command! (%d)", mbuf[2]);
1258 }
1259 }
1260
1261 return NULL;
1262}
1263
1264void newcamd_idle(void) {
1265 struct s_client *client = cur_client();
1266 struct s_reader *rdr = client->reader;
1267
1268 if (!rdr) return;
1269
1270 if (rdr->tcp_ito > 0) {
1271 // inactivitytimeout > 0 enables protocol keepalive packages
1272 time_t now;
1273 int32_t time_diff;
1274 time(&now);
1275 time_diff = abs(now - rdr->last_s);
1276 if (time_diff>(rdr->tcp_ito)) {
1277 if (client->ncd_keepalive)
1278 newcamd_reply_ka();
1279 else
1280 network_tcp_connection_close(client->reader, "inactivity");
1281 }
1282 }
1283 else if (rdr->tcp_ito == -1) {
1284 // idle reconnect
1285 newcamd_connect();
1286 }
1287}
1288
1289/*
1290* client functions
1291*/
1292
1293int32_t newcamd_client_init(struct s_client *client)
1294{
1295
1296 char ptxt[1] = { "\0" };
1297
1298 client->ncd_proto=client->reader->ncd_proto;
1299
1300 cs_log("proxy %s:%d newcamd52%d (fd=%d%s)",
1301 client->reader->device, client->reader->r_port,
1302 (client->reader->ncd_proto==NCD_525)?5:4, client->udp_fd, ptxt);
1303
1304 // try to connect. ignore possible failures
1305 // idle reconnect (tcp_ito = -1) will trigger an additional connect anyway
1306 if (client->reader->ncd_connect_on_init && client->reader->tcp_ito != -1)
1307 newcamd_connect();
1308
1309 return(0);
1310}
1311
1312static int32_t newcamd_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
1313{
1314 struct s_reader *rdr = client->reader;
1315
1316 if(!newcamd_connect())
1317 return (-1);
1318
1319 // check server filters
1320 if(!chk_rsfilter(rdr, er))
1321 return(-1);
1322
1323 memcpy(buf, er->ecm, er->ecmlen);
1324
1325 client->ncd_header[4] = er->srvid >> 8;
1326 client->ncd_header[5] = er->srvid & 0xFF;
1327 client->ncd_header[6] = er->caid >> 8;
1328 client->ncd_header[7] = er->caid & 0xFF;
1329 client->ncd_header[8] = er->prid >> 16;
1330 client->ncd_header[9] = er->prid >> 8;
1331 client->ncd_header[10] = er->prid & 0xFF;
1332
1333 return((newcamd_send(buf, er->ecmlen, er->srvid)<1) ? (-1) : 0);
1334}
1335
1336
1337static int32_t newcamd_send_emm(EMM_PACKET *ep)
1338{
1339 uchar buf[ep->emmlen];
1340
1341 if(!newcamd_connect())
1342 return (-1);
1343
1344 memcpy(buf, ep->emm, ep->emmlen);
1345 return((newcamd_send(buf, ep->emmlen, 0)<1) ? 0 : 1);
1346}
1347
1348static int32_t newcamd_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t n)
1349{
1350 uint16_t idx = -1;
1351
1352 if (n<5)
1353 return -1;
1354
1355 switch(buf[2]) {
1356 case 0x80:
1357 case 0x81:
1358 idx = (buf[0] << 8) | buf[1];
1359 if (n==5) { //not found on server
1360 *rc = 0;
1361 memset(dcw, 0, 16);
1362 break;
1363 }
1364
1365 if (n<21) {
1366 cs_debug_mask(D_CLIENT, "invalid newcamd answer");
1367 return(-1);
1368 }
1369
1370 *rc = 1;
1371 memcpy(dcw, buf+5, 16);
1372 break;
1373
1374 case MSG_KEEPALIVE:
1375 return -1;
1376
1377 case MSG_SERVER_2_CLIENT_ADDCARD:
1378 if (client->reader) {
1379 client->reader->ncd_disable_server_filt=1;
1380 }
1381 return -1;
1382
1383 default:
1384 if (buf[2]>0x81 && buf[2]<0x90) { //answer to emm
1385 return -1;
1386 }
1387 cs_debug_mask(D_CLIENT, "unknown newcamd command from server");
1388 return -1;
1389 }
1390 return(idx);
1391}
1392
1393/*
1394 * resolve client type for newcamd protocol
1395 */
1396const char *newcamd_get_client_name(uint16_t client_id)
1397{
1398 // When adding new entries keep the list sorted!
1399 static const struct {
1400 uint16_t id;
1401 const char *client;
1402 } ncd_service_ids[] = {
1403 { 0x0000, "generic" },
1404 { 0x02C2, "Opticum" },
1405 { 0x0665, "rq-sssp-client/CS" },
1406 { 0x0666, "rqcamd" },
1407 { 0x0667, "rq-echo-client" },
1408 { 0x0669, "rq-sssp-client/CW" },
1409 { 0x0769, "JlsRq" },
1410 { 0x414C, "AlexCS" },
1411 { 0x4333, "camd3" },
1412 { 0x4343, "CCcam" },
1413 { 0x434C, "Cardlink" },
1414 { 0x4453, "DiabloCam/UW" },
1415 { 0x4543, "eyetvCamd" },
1416 { 0x4765, "Octagon" },
1417 { 0x4C43, "LCE" },
1418 { 0x4E58, "NextYE2k" },
1419 { 0x5342, "SBCL" },
1420 { 0x5456, "Tecview" },
1421 { 0x5644, "vdr-sc" },
1422 { 0x5743, "WiCard" },
1423 { 0x6378, "cx" },
1424 { 0x6502, "Tvheadend" },
1425 { 0x6576, "evocamd" },
1426 { 0x6762, "gbox2CS" },
1427 { 0x6B61, "Kaffeine" },
1428 { 0x6B63, "kpcs" },
1429 { 0x6D63, "mpcs" },
1430 { 0x6D67, "mgcamd" },
1431 { 0x6E65, "NextYE2k" },
1432 { 0x6E73, "NewCS" },
1433 { 0x7264, "radegast" },
1434 { 0x7363, "Scam" },
1435 { 0x7763, "WinCSC" },
1436 { 0x7878, "tsdecrypt" },
1437 { 0x8888, "OSCam" },
1438 { 0x9911, "ACamd" },
1439 { 0xFFFF, NULL } };
1440 int i = 0;
1441 while (1) {
1442 if (!ncd_service_ids[i].client)
1443 break;
1444 if (ncd_service_ids[i].id == client_id)
1445 return ncd_service_ids[i].client;
1446 i++;
1447 }
1448 return "unknown - please report";
1449}
1450
1451void module_newcamd(struct s_module *ph)
1452{
1453 ph->desc="newcamd";
1454 ph->type=MOD_CONN_TCP;
1455 ph->listenertype = LIS_NEWCAMD;
1456 IP_ASSIGN(ph->s_ip, cfg.ncd_srvip);
1457 ph->s_handler=newcamd_server;
1458 ph->s_init=newcamd_server_init;
1459 ph->recv=newcamd_recv;
1460 ph->send_dcw=newcamd_send_dcw;
1461 ph->ptab=cfg.ncd_ptab;
1462 ph->c_init=newcamd_client_init;
1463 ph->c_recv_chk=newcamd_recv_chk;
1464 ph->c_send_ecm=newcamd_send_ecm;
1465 ph->c_send_emm=newcamd_send_emm;
1466 ph->c_idle = newcamd_idle;
1467 ph->num=R_NEWCAMD;
1468}
1469#endif
Note: See TracBrowser for help on using the repository browser.