source: trunk/module-newcamd.c@ 3652

Last change on this file since 3652 was 3652, checked in by dingo35, 13 years ago

replace au index by aureader pointer

File size: 37.0 KB
Line 
1#include "globals.h"
2extern struct s_reader reader[CS_MAXREADER];
3
4#define CWS_NETMSGSIZE 272
5#define NCD_CLIENT_ID 0x8888
6
7#define CWS_FIRSTCMDNO 0xe0
8typedef enum
9{
10 MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
11 MSG_CLIENT_2_SERVER_LOGIN_ACK,
12 MSG_CLIENT_2_SERVER_LOGIN_NAK,
13 MSG_CARD_DATA_REQ,
14 MSG_CARD_DATA,
15 MSG_SERVER_2_CLIENT_NAME,
16 MSG_SERVER_2_CLIENT_NAME_ACK,
17 MSG_SERVER_2_CLIENT_NAME_NAK,
18 MSG_SERVER_2_CLIENT_LOGIN,
19 MSG_SERVER_2_CLIENT_LOGIN_ACK,
20 MSG_SERVER_2_CLIENT_LOGIN_NAK,
21 MSG_ADMIN,
22 MSG_ADMIN_ACK,
23 MSG_ADMIN_LOGIN,
24 MSG_ADMIN_LOGIN_ACK,
25 MSG_ADMIN_LOGIN_NAK,
26 MSG_ADMIN_COMMAND,
27 MSG_ADMIN_COMMAND_ACK,
28 MSG_ADMIN_COMMAND_NAK,
29 MSG_KEEPALIVE = CWS_FIRSTCMDNO + 0x1d,
30 MSG_SERVER_2_CLIENT_OSD = 0xd1,
31 MSG_SERVER_2_CLIENT_ALLCARDS = 0xd2,
32 MSG_SERVER_2_CLIENT_ADDCARD = 0xd3,
33 MSG_SERVER_2_CLIENT_REMOVECARD = 0xd4,
34 MSG_SERVER_2_CLIENT_CHANGE_KEY = 0xd5,
35 MSG_SERVER_2_CLIENT_GET_VERSION = 0xd6,
36 MSG_SERVER_2_CLIENT_ADDSID = 0xd7,
37 MSG_CLIENT_2_SERVER_CARDDISCOVER = 0xd8
38} net_msg_type_t;
39
40typedef enum
41{
42 COMMTYPE_CLIENT,
43 COMMTYPE_SERVER
44} comm_type_t;
45
46
47typedef struct custom_data
48{
49 unsigned short sid;
50 unsigned short caid;
51 int provid;
52 uchar x;
53} custom_data_t;
54
55static char *get_ncd_client_name(char *client_id)
56{
57 static const int max_id_idx = 29;
58 static const char *ncd_service_ids[] = { "0000", "5644", "4C43", "4333", "7264", "6762", "6D67", "7763", "6E73", "6378", "6B61",
59 "6576", "4343", "5456", "414C", "0666", "0667", "9911", "434C", "4765", "5342",
60 "6E65", "4E58", "4453", "8888", "7363", "0669", "0665", "0769", "4543" };
61
62 static char *ncd_service_names[] = { "generic", "vdr-sc", "LCE", "camd3", "radegast", "gbox2CS", "mgcamd", //actually a const so threadsafe
63 "WinCSC", "NewCS", "cx", "Kaffeine", "evocamd", "CCcam", "Tecview",
64 "AlexCS", "rqcamd", "rq-echo-client", "ACamd", "Cardlink", "Octagon", "SBCL",
65 "NextYE2k", "NextYE2k", "DiabloCam/UW", "OScam", "Scam", "rq-sssp-client/CW",
66 "rq-sssp-client/CS", "JlsRq", "eyetvCamd", "unknown - please report" };
67
68 int idx = 0;
69 for (idx = 0; idx <= max_id_idx; idx++) {
70 if(!memcmp(ncd_service_ids[idx], client_id, 4))
71 return ncd_service_names[idx];
72
73 }
74
75 return ncd_service_names[max_id_idx+1];
76}
77
78#define REQ_SIZE 2
79
80static int network_message_send(int handle, uint16 *netMsgId, uint8 *buffer,
81 int len, uint8 *deskey, comm_type_t commType,
82 ushort sid, custom_data_t *cd)
83{
84 uint8 netbuf[CWS_NETMSGSIZE];
85 int head_size;
86 struct s_client *cl = cur_client();
87
88 head_size = (cl->ncd_proto==NCD_524)?8:12;
89
90 if (len < 3 || len + head_size > CWS_NETMSGSIZE || handle < 0)
91 return -1;
92 buffer[1] = (buffer[1] & 0xf0) | (((len - 3) >> 8) & 0x0f);
93 buffer[2] = (len - 3) & 0xff;
94 memcpy(netbuf+head_size, buffer, len);
95 len += head_size;
96 if (netMsgId) {
97 switch(commType)
98 {
99 case COMMTYPE_CLIENT:
100 (*netMsgId)++;
101 break;
102 case COMMTYPE_SERVER:
103 if( *netMsgId == 0xFFFE ) *netMsgId = 0; // ??? 0xFFFF ?
104 break;
105 }
106 netbuf[2] = (*netMsgId) >> 8;
107 netbuf[3] = (*netMsgId) & 0xff;
108 }
109 else
110 netbuf[2] = netbuf[3] = 0;
111 memset(netbuf+4, 0, (cl->ncd_proto==NCD_524)?4:8);
112 if( sid ) {
113 netbuf[(cl->ncd_proto==NCD_524)?6:4] = (uchar)(sid>>8); //sid
114 netbuf[(cl->ncd_proto==NCD_524)?7:5] = (uchar)(sid);
115 }
116 //if ((!ncd_proto==NCD_524) && (buffer[0] >= 0xd1) && (buffer[0]<= 0xd8)) { // extended proto for mg
117 //cs_debug("newcamd: extended: msg");
118 if (cd) {
119 cs_debug("newcamd: has cd");
120 netbuf[4] = cd->sid >> 8;
121 netbuf[5] = cd->sid & 0xff;
122 netbuf[6] = cd->caid >> 8;
123 netbuf[7] = cd->caid & 0xff;
124 netbuf[8] = (cd->provid >> 16) & 0xFF;
125 netbuf[9] = (cd->provid >> 8) & 0xff;
126 netbuf[10] = cd->provid & 0xff;
127 }
128 //}
129 netbuf[0] = (len - 2) >> 8;
130 netbuf[1] = (len - 2) & 0xff;
131 cs_ddump(netbuf, len, "send %d bytes to %s", len, remote_txt());
132 if ((len = des_encrypt(netbuf, len, deskey)) < 0)
133 return -1;
134 netbuf[0] = (len - 2) >> 8;
135 netbuf[1] = (len - 2) & 0xff;
136 return send(handle, netbuf, len, 0);
137}
138
139static int network_message_receive(int handle, uint16 *netMsgId, uint8 *buffer,
140 uint8 *deskey, comm_type_t commType)
141{
142 int len, ncd_off, msgid;
143 uint8 netbuf[CWS_NETMSGSIZE];
144 int returnLen;
145 struct s_client *cl = cur_client();
146
147 if (!buffer || handle < 0)
148 return -1;
149 len = recv(handle, netbuf, 2, 0);
150 cs_debug("nmr(): len=%d, errno=%d", len, (len==-1)?errno:0);
151 if (!len) {
152 cs_debug("nmr: 1 return 0");
153 network_tcp_connection_close(cl->reader, handle);
154 return 0;
155 }
156 if (len != 2) {
157 cs_debug("nmr: len!=2");
158 network_tcp_connection_close(cl->reader, handle);
159 return -1;
160 }
161 if (((netbuf[0] << 8) | netbuf[1]) > CWS_NETMSGSIZE - 2) {
162 cs_debug("nmr: 1 return -1");
163 return -1;
164 }
165
166 len = recv(handle, netbuf+2, (netbuf[0] << 8) | netbuf[1], 0);
167 if (!len) {
168 cs_debug("nmr: 2 return 0");
169 return 0;
170 }
171 if (len != ((netbuf[0] << 8) | netbuf[1])) {
172 cs_debug("nmr: 2 return -1");
173 return -1;
174 }
175 len += 2;
176 if ((len = des_decrypt(netbuf, len, deskey)) < 11 ) { // 15(newcamd525) or 11 ???
177 cs_debug("nmr: can't decrypt, invalid des key?");
178 cs_sleepms(2000);
179 return -1;
180 }
181 //cs_ddump(netbuf, len, "nmr: decrypted data, len=%d", len);
182 msgid = (netbuf[2] << 8) | netbuf[3];
183
184 if( cl->ncd_proto==NCD_AUTO ) {
185 // auto detect
186 int l5 = (((netbuf[13] & 0x0f) << 8) | netbuf[14]) + 3;
187 int l4 = (((netbuf[9] & 0x0f) << 8) | netbuf[10]) + 3;
188
189 if( (l5<=len-12) && ((netbuf[12]&0xF0)==0xE0 || (netbuf[12]&0xF0)==0x80) )
190 cl->ncd_proto = NCD_525;
191 else if( (l4<=len-8) && ((netbuf[8]&0xF0)==0xE0 || (netbuf[9]&0xF0)==0x80) )
192 cl->ncd_proto = NCD_524;
193 else {
194 cs_debug("nmr: 4 return -1");
195 return -1;
196 }
197
198 cs_debug("nmr: autodetect: newcamd52%d used", (cl->ncd_proto==NCD_525)?5:4);
199 }
200
201 ncd_off=(cl->ncd_proto==NCD_525)?4:0;
202
203 returnLen = (((netbuf[9+ncd_off] & 0x0f) << 8) | netbuf[10+ncd_off]) + 3;
204 if ( returnLen > (len-(8+ncd_off)) ) {
205 cs_debug("nmr: 4 return -1");
206 return -1;
207 }
208
209 //cs_ddump(netbuf, len, "nmr: decrypted data");
210 if (netMsgId)
211 {
212 switch (commType)
213 {
214 case COMMTYPE_SERVER:
215 *netMsgId = msgid;
216 break;
217
218 case COMMTYPE_CLIENT:
219 //if (*netMsgId != ((netbuf[2] << 8) | netbuf[3])) {
220 cs_debug("nmr: netMsgId=%d, from server=%d, ", *netMsgId, msgid );
221 //return -2;
222 //}
223 break;
224
225 default:
226 cs_debug("nmr: 5 return -1");
227 return -1;
228 break;
229 }
230 }
231 switch(commType)
232 {
233 case COMMTYPE_SERVER:
234 buffer[0]=(cl->ncd_proto==NCD_525)?netbuf[4]:netbuf[6]; // sid
235 buffer[1]=(cl->ncd_proto==NCD_525)?netbuf[5]:netbuf[7];
236 break;
237 case COMMTYPE_CLIENT:
238 buffer[0]=netbuf[2]; // msgid
239 buffer[1]=netbuf[3];
240 break;
241 }
242
243 memcpy(buffer+2, netbuf+(8+ncd_off), returnLen);
244 return returnLen+2;
245}
246
247static void network_cmd_no_data_send(int handle, uint16 *netMsgId,
248 net_msg_type_t cmd, uint8 *deskey,
249 comm_type_t commType)
250{
251 uint8 buffer[CWS_NETMSGSIZE];
252
253 buffer[0] = cmd; buffer[1] = 0;
254 network_message_send(handle, netMsgId, buffer, 3, deskey, commType, 0, NULL);
255}
256
257static int network_cmd_no_data_receive(int handle, uint16 *netMsgId,
258 uint8 *deskey, comm_type_t commType)
259{
260 uint8 buffer[CWS_NETMSGSIZE];
261
262 if (network_message_receive(handle, netMsgId, buffer, deskey, commType) != 3+2)
263 return -1;
264 return buffer[2];
265}
266
267void newcamd_reply_ka()
268{
269 struct s_client *cl = cur_client();
270
271 if(!cl->udp_fd)
272 {
273 cs_debug("invalid client fd=%d", cl->udp_fd);
274 return;
275 }
276
277 cs_debug("send keepalive to client fd=%d", cl->udp_fd);
278
279 network_cmd_no_data_send(cl->udp_fd, &cl->ncd_msgid,
280 MSG_KEEPALIVE, cl->ncd_skey,COMMTYPE_SERVER);
281}
282
283static int connect_newcamd_server()
284{
285 int i;
286 uint8 buf[CWS_NETMSGSIZE];
287 uint8 keymod[14];
288 uint8 *key;
289 int handle=0;
290
291 uint32 index;
292 uchar passwdcrypt[120];
293 uint8 login_answer;
294 int bytes_received;
295 struct s_client *cl = cur_client();
296
297 if(cl->reader->device[0] == 0 || cl->reader->r_pwd[0] == 0 ||
298 cl->reader->r_usr[0] == 0 || cl->reader->r_port == 0)
299 return -5;
300
301 // 1. Connect
302 handle = network_tcp_connection_open();
303 if(handle < 0) return -1;
304
305 // 2. Get init sequence
306 cl->reader->ncd_msgid = 0;
307 if( read(handle, keymod, sizeof(keymod)) != sizeof(keymod)) {
308 cs_log("server does not return 14 bytes");
309 network_tcp_connection_close(cl->reader, handle);
310 return -2;
311 }
312 cs_ddump(keymod, 14, "server init sequence:");
313 key = des_login_key_get(keymod, cl->reader->ncd_key, 14);
314
315 // 3. Send login info
316 index = 3;
317 buf[0] = MSG_CLIENT_2_SERVER_LOGIN;
318 buf[1] = 0;
319 strcpy((char *)buf+index, cl->reader->r_usr);
320 __md5_crypt(cl->reader->r_pwd, "$1$abcdefgh$", (char *)passwdcrypt);
321 index += strlen(cl->reader->r_usr)+1;
322 strcpy((char *)buf+index, (const char *)passwdcrypt);
323
324 network_message_send(handle, 0, buf, index+strlen((char *)passwdcrypt)+1, key,
325 COMMTYPE_CLIENT, NCD_CLIENT_ID, NULL);
326
327 // 3.1 Get login answer
328 login_answer=network_cmd_no_data_receive(handle, &cl->reader->ncd_msgid,
329 key, COMMTYPE_CLIENT);
330 if( login_answer == MSG_CLIENT_2_SERVER_LOGIN_NAK )
331 {
332 cs_log("login failed for user '%s'", cl->reader->r_usr);
333 network_tcp_connection_close(cl->reader, handle);
334 return -3;
335 }
336 if( login_answer != MSG_CLIENT_2_SERVER_LOGIN_ACK )
337 {
338 cs_log("expected MSG_CLIENT_2_SERVER_LOGIN_ACK (%02X), received %02X",
339 MSG_CLIENT_2_SERVER_LOGIN_ACK, login_answer);
340 network_tcp_connection_close(cl->reader, handle);
341 return -3;
342 }
343
344 // 3.2 Set connection info
345 cl->reader->tcp_connected = 1;
346
347 // 4. Send MSG_CARD_DATE_REQ
348 key = des_login_key_get(cl->reader->ncd_key, passwdcrypt, strlen((char *)passwdcrypt));
349
350 network_cmd_no_data_send(handle, &cl->reader->ncd_msgid, MSG_CARD_DATA_REQ,
351 key, COMMTYPE_CLIENT);
352 bytes_received = network_message_receive(handle, &cl->reader->ncd_msgid, buf,
353 key, COMMTYPE_CLIENT);
354 if( bytes_received < 16 || buf[2] != MSG_CARD_DATA ) {
355 cs_log("expected MSG_CARD_DATA (%02X), received %02X",
356 MSG_CARD_DATA, buf[2]);
357 network_tcp_connection_close(cl->reader, handle);
358 return -4;
359 }
360
361 // 5. Parse CAID and PROVID(s)
362 cl->reader->caid[0] = (ushort)((buf[4+2]<<8) | buf[5+2]);
363
364 /* handle special serial format in newcamd. See newcamd_auth_client */
365 if (((cl->reader->caid[0] >> 8) == 0x17) || ((cl->reader->caid[0] >> 8) == 0x06)) {
366 memcpy(&cl->reader->hexserial, buf+10+2, 4);
367 int hexbase = cl->reader->hexserial[0];
368 cl->reader->hexserial[0] = cl->reader->hexserial[1];
369 cl->reader->hexserial[1] = cl->reader->hexserial[2];
370 cl->reader->hexserial[2] = cl->reader->hexserial[3];
371 cl->reader->hexserial[3] = hexbase;
372 }
373 else if (((cl->reader->caid[0] >> 8) == 0x05) || ((cl->reader->caid[0] >> 8) == 0x0D))
374 memcpy(&cl->reader->hexserial, buf+9+2, 5);
375 else
376 memcpy(&cl->reader->hexserial, buf+8+2, 6);
377
378 cs_log("Newcamd Server: %s:%d - UserID: %i", cl->reader->device, cl->reader->r_port, buf[3+2]);
379 cs_log("CAID: %04X - UA: %02X%02X%02X%02X%02X%02X%02X%02X - Provider # %i", cl->reader->caid[0], 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]);
380 cl->reader->nprov = buf[14+2];
381 memset(cl->reader->prid, 0x00, sizeof(cl->reader->prid));
382 for (i=0; i < cl->reader->nprov; i++) {
383 cl->reader->availkeys[i][0] = 1;
384 cl->reader->prid[i][0] = buf[15+2+11*i];
385 cl->reader->prid[i][1] = buf[16+2+11*i];
386 cl->reader->prid[i][2] = buf[17+2+11*i];
387 memcpy(&cl->reader->sa[i], buf+22+2+11*i, 4); // the 4 first bytes are not read
388 cs_log("Provider ID: %02X%02X%02X - SA: %02X%02X%02X%02X", cl->reader->prid[i][0], cl->reader->prid[i][1], cl->reader->prid[i][2], cl->reader->sa[i][0], cl->reader->sa[i][1], cl->reader->sa[i][2], cl->reader->sa[i][3]);
389 }
390 memcpy(cl->reader->ncd_skey, key, 16);
391
392 // 6. Set card inserted
393 cl->reader->tcp_connected = 2;
394 cl->reader->card_status = CARD_INSERTED;
395 cl->reader->last_g = cl->reader->last_s = time((time_t *)0);
396
397 // Only after connect() on cl->udp_fd (Linux)
398 cl->pfd=cl->udp_fd;
399
400 return 0;
401}
402
403static int newcamd_connect()
404{
405 struct s_client *cl = cur_client();
406
407 if (cl->reader->tcp_connected < 2 && connect_newcamd_server() < 0)
408 return 0;
409
410 if (!cl->udp_fd)
411 return 0;
412
413 return 1;
414}
415
416
417static int newcamd_send(uchar *buf, int ml, ushort sid)
418{
419 struct s_client *cl = cur_client();
420
421 if(!newcamd_connect())
422 return(-1);
423
424 return(network_message_send(cl->udp_fd, &cl->reader->ncd_msgid,
425 buf, ml, cl->reader->ncd_skey, COMMTYPE_CLIENT, sid, NULL));
426}
427
428static int newcamd_recv(struct s_client *client, uchar *buf, int UNUSED(l))
429{
430 int rc, rs;
431
432 if (client->typ == 'c')
433 {
434 rs=network_message_receive(client->udp_fd,
435 &client->ncd_msgid, buf,
436 client->ncd_skey, COMMTYPE_SERVER);
437 }
438 else
439 {
440 if (!client->udp_fd) return(-1);
441 rs=network_message_receive(client->udp_fd,
442 &client->reader->ncd_msgid,buf,
443 client->reader->ncd_skey, COMMTYPE_CLIENT);
444 }
445
446 if (rs<5) rc=(-1);
447 else rc=rs;
448
449 cs_ddump(buf, rs, "received %d bytes from %s", rs, remote_txt());
450 client->last = time((time_t *) 0);
451
452 if( rc==-1 )
453 {
454 if (rs > 0)
455 cs_log("packet to small (%d bytes)", rs);
456 else
457 cs_log("Connection closed to %s", remote_txt());
458 }
459 return(rc);
460}
461
462static FILTER mk_user_au_ftab(int au)
463{
464 int i,j,found;
465 struct s_client *cl = cur_client();
466 FILTER filt;
467 FILTER *pufilt;
468
469 filt.caid = reader[au].caid[0];
470 if (filt.caid == 0) filt.caid = cl->ftab.filts[0].caid;
471 filt.nprids = 0;
472 memset(&filt.prids, 0, sizeof(filt.prids));
473 pufilt = &cl->ftab.filts[0];
474
475 for( i=0; i<reader[au].nprov; i++ )
476 filt.prids[filt.nprids++] = b2i(3, &reader[au].prid[i][1]);
477
478 for( i=0; i<pufilt->nprids; i++ )
479 {
480 for( j=found=0; (!found)&&(j<filt.nprids); j++ )
481 if (pufilt->prids[i] == filt.prids[j]) found=1;
482 if( !found )
483 filt.prids[filt.nprids++] = pufilt->prids[i];
484 }
485
486 return filt;
487}
488
489static FILTER mk_user_ftab()
490{
491 FILTER *psfilt = 0;
492 FILTER filt;
493 int port_idx,i,j,k,c;
494 struct s_client *cl = cur_client();
495
496 filt.caid = 0;
497 filt.nprids = 0;
498 memset(&filt.prids, 0, sizeof(filt.prids));
499
500 port_idx = cl->port_idx;
501 psfilt = &cfg->ncd_ptab.ports[port_idx].ftab.filts[0];
502
503 // 1. CAID
504 // search server CAID in client CAID
505 for( c=i=0; i<CS_MAXCAIDTAB; i++ )
506 {
507 int ctab_caid;
508 ctab_caid = cl->ctab.caid[i]&cl->ctab.mask[i];
509 if( ctab_caid ) c++;
510
511 if( psfilt->caid==ctab_caid )
512 {
513 filt.caid=ctab_caid;
514 break;
515 }
516 }
517 if( c && !filt.caid )
518 {
519 cs_log("no valid CAID found in CAID for user '%s'", cl->usr);
520 return filt;
521 }
522
523 // search CAID in client IDENT
524 cs_debug("client[%8X].%s nfilts=%d, filt.caid=%04X", pthread_self(),
525 cl->usr, cl->ftab.nfilts, filt.caid);
526
527 if( !filt.caid && cl->ftab.nfilts )
528 {
529 int fcaids;
530 for( i=fcaids=0; i<cl->ftab.nfilts; i++ )
531 {
532 ushort ucaid=cl->ftab.filts[i].caid;
533 if( ucaid ) fcaids++;
534 if( ucaid && psfilt->caid==ucaid )
535 {
536 filt.caid = ucaid;
537 break;
538 }
539 }
540 if( fcaids==cl->ftab.nfilts && !filt.caid )
541 {
542 cs_log("no valid CAID found in IDENT for user '%s'", cl->usr);
543 //cs_disconnect_client();
544 return filt;
545 }
546 }
547 // empty client CAID - use server CAID
548 if( !filt.caid ) filt.caid=psfilt->caid;
549
550 // 2. PROVID
551 if( !cl->ftab.nfilts )
552 {
553 int add;
554 for (i=0; i<psfilt->nprids; i++) {
555 // use server PROVID(s) (and only those which are in user's groups)
556 add = 0;
557 struct s_reader *rdr;
558 for (rdr=first_reader; rdr ; rdr=rdr->next)
559 if (rdr->grp & cl->grp) {
560 if (!rdr->ftab.nfilts) {
561 if (rdr->typ & R_IS_NETWORK) add = 1;
562 for (j=0; !add && j<rdr->nprov; j++)
563 if (b2i(3, &rdr->prid[j][1]) == psfilt->prids[i]) add = 1;
564 } else {
565 for (j=0; !add && j<rdr->ftab.nfilts; j++) {
566 ulong rcaid = rdr->ftab.filts[j].caid;
567 if (!rcaid || rcaid == filt.caid) {
568 for (k=0; !add && k<rdr->ftab.filts[j].nprids; k++)
569 if (rdr->ftab.filts[j].prids[k] == psfilt->prids[i]) add = 1;
570 }
571 }
572 }
573 }
574 if (add) filt.prids[filt.nprids++] = psfilt->prids[i];
575 }
576 return filt;
577 }
578
579 // search in client IDENT
580 for( j=0; j<cl->ftab.nfilts; j++ )
581 {
582 ulong ucaid = cl->ftab.filts[j].caid;
583 cs_debug("client caid #%d: %04X", j, ucaid);
584 if( !ucaid || ucaid==filt.caid )
585 {
586 for (i=0; i<psfilt->nprids; i++)
587 {
588 cs_debug("search server provid #%d: %06X", i, psfilt->prids[i]);
589 if( cl->ftab.filts[j].nprids )
590 {
591 for( k=0; k<cl->ftab.filts[j].nprids; k++ )
592 if (cl->ftab.filts[j].prids[k] == psfilt->prids[i])
593 filt.prids[filt.nprids++]=cl->ftab.filts[j].prids[k];
594 } else {
595 filt.prids[filt.nprids++] = psfilt->prids[i];
596 // allow server PROVID(s) if no PROVID(s) specified in IDENT
597 }
598 }
599 }
600 }
601
602 if( !filt.nprids )
603 {
604 cs_log("no valid PROVID(s) found in CAID for user '%s'", cl->usr);
605 //cs_disconnect_client();
606 }
607
608 return filt;
609}
610
611static void newcamd_auth_client(in_addr_t ip, uint8 *deskey)
612{
613 int i, ok;
614 uchar *usr = NULL, *pwd = NULL;
615 char client_id[5], *client_name = NULL;
616 struct s_auth *account;
617 uchar buf[14];
618 uchar *key=0;
619 uchar passwdcrypt[120];
620 struct s_reader *aureader=first_reader; //FIXME strange enough au was initialized to 0 = first reader, and not to -1 = no reader
621 struct s_ip *p_ip;
622 struct s_client *cl = cur_client();
623 uchar mbuf[1024];
624
625 ok = cfg->ncd_allowed ? 0 : 1;
626 for (p_ip=cfg->ncd_allowed; (p_ip) && (!ok); p_ip=p_ip->next)
627 ok=((ip>=p_ip->ip[0]) && (ip<=p_ip->ip[1]));
628
629 if (!ok)
630 {
631 cs_auth_client(cl, (struct s_auth *)0, NULL);
632 cs_exit(0);
633 }
634
635 // make random 14 bytes
636 for( i=0; i<14; i++ ) buf[i]=fast_rnd();
637
638 // send init sequence
639 send(cl->udp_fd, buf, 14, 0);
640 key = des_login_key_get(buf, deskey, 14);
641 memcpy(cl->ncd_skey, key, 16);
642 cl->ncd_msgid = 0;
643
644 i=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle);
645 if ( i>0 )
646 {
647 if( mbuf[2] != MSG_CLIENT_2_SERVER_LOGIN )
648 {
649 cs_debug("expected MSG_CLIENT_2_SERVER_LOGIN (%02X), received %02X",
650 MSG_CLIENT_2_SERVER_LOGIN, mbuf[2]);
651 NULLFREE(cl->req);
652 cs_exit(0);
653 }
654 usr=mbuf+5;
655 pwd=usr+strlen((char *)usr)+1;
656 }
657 else
658 {
659 cs_debug("bad client login request");
660 NULLFREE(cl->req);
661 cs_exit(0);
662 }
663
664 sprintf(client_id, "%02X%02X", mbuf[0], mbuf[1]);
665 client_name = get_ncd_client_name(client_id);
666
667 for (ok=0, account=cfg->account; (usr) && (account) && (!ok); account=account->next)
668 {
669 cs_debug("account->usr=%s", account->usr);
670 if (strcmp((char *)usr, account->usr) == 0)
671 {
672 __md5_crypt(account->pwd, "$1$abcdefgh$", (char *)passwdcrypt);
673 cs_debug("account->pwd=%s", passwdcrypt);
674 if (strcmp((char *)pwd, (const char *)passwdcrypt) == 0)
675 {
676 cl->crypted=1;
677
678 if(cs_auth_client(cl, account, NULL) == 2) {
679 cs_log("hostname or ip mismatch for user %s (%s)", usr, client_name);
680 break;
681 }
682 else
683 {
684 cs_log("user %s authenticated successfully (%s)", usr, client_name);
685 ok = 1;
686 break;
687 }
688 }
689 else
690 cs_log("user %s is providing a wrong password (%s)", usr, client_name);
691 }
692 }
693
694 if (!ok && !account)
695 {
696 cs_log("user %s is trying to connect but doesnt exist ! (%s)", usr, client_name);
697 usr = 0;
698 }
699
700 // check for non ready reader and reject client
701 struct s_reader *rdr;
702 for (rdr=first_reader; rdr ; rdr=rdr->next) {
703 if(rdr->caid[0]==cfg->ncd_ptab.ports[cl->port_idx].ftab.filts[0].caid) {
704 if(rdr->card_status == CARD_NEED_INIT) {
705 cs_log("init for reader %s not finished -> reject client", rdr->label);
706 ok = 0;
707 }
708 break;
709 }
710 }
711
712 if (ok)
713 {
714 aureader = cl->aureader;
715 if (aureader)
716 {
717 if (cfg->ncd_ptab.ports[cl->port_idx].ftab.filts[0].caid != aureader->caid[0]
718 && cfg->ncd_ptab.ports[cl->port_idx].ftab.filts[0].caid != aureader->ftab.filts[0].caid
719 && aureader->typ != R_CCCAM) // disabling AU breaks cccam-au when cascading over newcamd, but with enabled au client was receiving wrong card data on faulty configured newcamd filters and when using betatunnel
720 {
721 cs_log("AU wont be used on this port -> disable AU");
722 aureader = NULL;
723 }
724 else
725 {
726 cs_log("AU enabled for user %s on reader %s", usr, aureader->label);
727 }
728 }
729 else
730 {
731 cs_log("AU disabled for user %s", usr);
732 }
733 }
734
735 network_cmd_no_data_send(cl->udp_fd, &cl->ncd_msgid,
736 (ok)?MSG_CLIENT_2_SERVER_LOGIN_ACK:MSG_CLIENT_2_SERVER_LOGIN_NAK,
737 cl->ncd_skey, COMMTYPE_SERVER);
738
739 if (ok)
740 {
741 FILTER *pufilt = 0;
742
743 key = des_login_key_get(deskey, passwdcrypt, strlen((char *)passwdcrypt));
744 memcpy(cl->ncd_skey, key, 16);
745
746 i=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle);
747 if( i>0 )
748 {
749 int j,len=15;
750 if( mbuf[2] != MSG_CARD_DATA_REQ)
751 {
752 cs_debug("expected MSG_CARD_DATA_REQ (%02X), received %02X",
753 MSG_CARD_DATA_REQ, mbuf[2]);
754 NULLFREE(cl->req);
755 cs_exit(0);
756 }
757
758 // set userfilter
759 cl->ftab.filts[0] = mk_user_ftab();
760
761 // set userfilter for au enabled clients
762 if (aureader)
763 cl->ftab.filts[0] = mk_user_au_ftab(get_ridx(aureader));
764
765 pufilt = &cl->ftab.filts[0];
766 cl->ftab.nfilts = 1;
767
768 mbuf[0] = MSG_CARD_DATA;
769 mbuf[1] = 0x00;
770 mbuf[2] = 0x00;
771
772 if(aureader)
773 mbuf[3] = 1;
774 else
775 mbuf[3] = get_threadnum(cl)+10; // Unique user number
776
777 mbuf[4] = (uchar)(pufilt->caid>>8);
778 mbuf[5] = (uchar)(pufilt->caid);
779 mbuf[6] = 0x00;
780 mbuf[7] = 0x00;
781
782 if (aureader)
783 {
784 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
785 {
786 // only 4 Bytes Hexserial for newcamd clients (Hex Base + Hex Serial)
787 // first 2 Byte always 00
788 mbuf[8]=0x00; //serial only 4 bytes
789 mbuf[9]=0x00; //serial only 4 bytes
790 // 1 Byte Hex Base (see reader-irdeto.c how this is stored in "aureader->hexserial")
791 mbuf[10]=aureader->hexserial[3];
792 // 3 Bytes Hex Serial (see reader-irdeto.c how this is stored in "aureader->hexserial")
793 mbuf[11]=aureader->hexserial[0];
794 mbuf[12]=aureader->hexserial[1];
795 mbuf[13]=aureader->hexserial[2];
796 }
797 else if (((pufilt->caid >> 8) == 0x05) || ((pufilt->caid >> 8) == 0x0D))
798 {
799 mbuf[8] = 0x00;
800 mbuf[9] = aureader->hexserial[0];
801 mbuf[10] = aureader->hexserial[1];
802 mbuf[11] = aureader->hexserial[2];
803 mbuf[12] = aureader->hexserial[3];
804 mbuf[13] = aureader->hexserial[4];
805 }
806 else
807 {
808 mbuf[8] = aureader->hexserial[0];
809 mbuf[9] = aureader->hexserial[1];
810 mbuf[10] = aureader->hexserial[2];
811 mbuf[11] = aureader->hexserial[3];
812 mbuf[12] = aureader->hexserial[4];
813 mbuf[13] = aureader->hexserial[5];
814 }
815 }
816 else
817 {
818 cl->aureader = NULL;
819 mbuf[8] = 0x00;
820 mbuf[9] = 0x00;
821 mbuf[10] = 0x00;
822 mbuf[11] = 0x00;
823 mbuf[12] = 0x00;
824 mbuf[13] = 0x00;
825 }
826 mbuf[14] = pufilt->nprids;
827 for( j=0; j<pufilt->nprids; j++)
828 {
829 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
830 {
831 mbuf[15+11*j] = 0;
832 mbuf[16+11*j] = 0;
833 mbuf[17+11*j] = j;
834 }
835 else
836 {
837 mbuf[15+11*j] = (uchar)(pufilt->prids[j]>>16);
838 mbuf[16+11*j] = (uchar)(pufilt->prids[j]>>8);
839 mbuf[17+11*j] = (uchar)(pufilt->prids[j]);
840 }
841 mbuf[18+11*j] = 0x00;
842 mbuf[19+11*j] = 0x00;
843 mbuf[20+11*j] = 0x00;
844 mbuf[21+11*j] = 0x00;
845 if (aureader)
846 {
847 // check if user provid from IDENT exists on card
848 int k, found;
849 ulong rprid;
850 found=0;
851 if( pufilt->caid==aureader->caid[0] )
852 {
853 for( k=0; (k<aureader->nprov); k++ )
854 {
855 rprid=b2i(3, &aureader->prid[k][1]);
856 if( rprid==pufilt->prids[j] )
857 {
858 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
859 {
860 mbuf[22+11*j] = aureader->prid[k][0];
861 mbuf[23+11*j] = aureader->prid[k][1];
862 mbuf[24+11*j] = aureader->prid[k][2];
863 mbuf[25+11*j] = aureader->prid[k][3];
864 }
865 else
866 {
867 mbuf[22+11*j] = aureader->sa[k][0];
868 mbuf[23+11*j] = aureader->sa[k][1];
869 mbuf[24+11*j] = aureader->sa[k][2];
870 mbuf[25+11*j] = aureader->sa[k][3];
871 }
872 found=1;
873 break;
874 }
875 }
876 }
877 if( !found )
878 {
879 mbuf[22+11*j] = 0x00;
880 mbuf[23+11*j] = 0x00;
881 mbuf[24+11*j] = 0x00;
882 mbuf[25+11*j] = 0x00;
883 }
884 }
885 else
886 {
887 if (((pufilt->caid >> 8) == 0x17) || ((pufilt->caid >> 8) == 0x06)) // Betacrypt or Irdeto
888 {
889 mbuf[22+11*j] = 0x00;
890 mbuf[23+11*j] = (uchar)(pufilt->prids[j]>>16);
891 mbuf[24+11*j] = (uchar)(pufilt->prids[j]>>8);
892 mbuf[25+11*j] = (uchar)(pufilt->prids[j]);
893 }
894 else
895 {
896 mbuf[22+11*j] = 0x00;
897 mbuf[23+11*j] = 0x00;
898 mbuf[24+11*j] = 0x00;
899 mbuf[25+11*j] = 0x00;
900 }
901 }
902 len+=11;
903 }
904
905 custom_data_t cd;
906 memset(&cd, 0, sizeof(cd));
907
908 if (aureader)
909 {
910 if (aureader->blockemm_g)
911 cd.sid |= 4;
912 if (aureader->blockemm_s)
913 cd.sid |= 2;
914 if (aureader->blockemm_u)
915 cd.sid |= 1;
916 }
917
918 if( network_message_send(cl->udp_fd, &cl->ncd_msgid,
919 mbuf, len, key, COMMTYPE_SERVER, 0, &cd) <0 )
920 {
921 NULLFREE(cl->req);
922 cs_exit(0);
923 }
924 }
925 }
926 else
927 {
928 cs_auth_client(cl, 0, usr ? "login failure" : "no such user");
929 NULLFREE(cl->req);
930 cs_exit(0);
931 }
932}
933
934static void newcamd_send_dcw(struct s_client *client, ECM_REQUEST *er)
935{
936 int len;
937 ushort cl_msgid;
938 uchar mbuf[1024];
939
940 if (!client->udp_fd) {
941 cs_debug("ncd_send_dcw: error: client->udp_fd=%d", client->udp_fd);
942 return;
943 }
944 memcpy(&cl_msgid, client->req+(er->cpti*REQ_SIZE), 2); // get client ncd_msgid + 0x8x
945 mbuf[0] = er->ecm[0];
946 if( client->ftab.filts[0].nprids==0 || er->rc>3 /*not found*/)
947 {
948 len=3;
949 mbuf[1] = mbuf[2] = 0x00;
950 }
951 else
952 {
953 len = 19;
954 mbuf[1] = mbuf[2] = 0x10;
955 memcpy(mbuf+3, er->cw, 16);
956 }
957
958 cs_debug("ncd_send_dcw: er->cpti=%d, cl_msgid=%d, %02X", er->cpti, cl_msgid, mbuf[0]);
959
960 network_message_send(client->udp_fd, &cl_msgid, mbuf, len,
961 client->ncd_skey, COMMTYPE_SERVER, 0, NULL);
962}
963
964static void newcamd_process_ecm(uchar *buf)
965{
966 int pi;
967 struct s_client *cl = cur_client();
968 ECM_REQUEST *er;
969
970 if (!(er=get_ecmtask())) {
971 return;
972 }
973 // save client ncd_msgid
974 memcpy(cl->req+(er->cpti*REQ_SIZE), &cl->ncd_msgid, 2);
975 cs_debug("ncd_process_ecm: er->cpti=%d, cl_msgid=%d, %02X", er->cpti,
976 cl->ncd_msgid, buf[2]);
977 er->l=buf[4]+3;
978 er->srvid = (buf[0]<<8)|buf[1];
979 er->caid = 0;
980 pi = cl->port_idx;
981 if( cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
982 er->caid=cfg->ncd_ptab.ports[pi].ftab.filts[0].caid;
983 memcpy(er->ecm, buf+2, er->l);
984 get_cw(cl, er);
985}
986
987static void newcamd_process_emm(uchar *buf)
988{
989 int ok=1;
990 ushort caid;
991 struct s_client *cl = cur_client();
992 EMM_PACKET epg;
993
994 memset(&epg, 0, sizeof(epg));
995 struct s_reader *aureader=cl->aureader;
996
997 // if client is not allowed to do AU just send back the OK-answer to
998 // the client and do nothing else with the received data
999 if (aureader)
1000 {
1001 epg.l=buf[2]+3;
1002 caid = cl->ftab.filts[0].caid;
1003 epg.caid[0] = (uchar)(caid>>8);
1004 epg.caid[1] = (uchar)(caid);
1005
1006 epg.provid[0] = (uchar)(aureader->auprovid>>24);
1007 epg.provid[1] = (uchar)(aureader->auprovid>>16);
1008 epg.provid[2] = (uchar)(aureader->auprovid>>8);
1009 epg.provid[3] = (uchar)(aureader->auprovid);
1010
1011/* if (caid == 0x0500)
1012 {
1013 ushort emm_head;
1014
1015 emm_head = (buf[0]<<8) | buf[1];
1016 switch( emm_head )
1017 {
1018 case 0x8e70: // EMM-S
1019 memcpy(epg.hexserial+1, buf+3, 4);
1020 epg.hexserial[4]=aureader->hexserial[4];
1021 break;
1022 case 0x8870: // EMM-U
1023 case 0x8c70: // confidential ?
1024 default:
1025 cs_log("unsupported emm type: %04X", emm_head);
1026 ok=0;
1027 }
1028 if( !ok ) cs_log("only EMM-S supported");
1029 }
1030 else*/
1031
1032 memcpy(epg.emm, buf, epg.l);
1033 if( ok )
1034 do_emm(cl, &epg);
1035 }
1036
1037 // Should always send an answer to client (also if au is disabled),
1038 // some clients will disconnect if they get no answer
1039 buf[1] = 0x10;
1040 buf[2] = 0x00;
1041 network_message_send(cl->udp_fd, &cl->ncd_msgid, buf, 3,
1042 cl->ncd_skey, COMMTYPE_SERVER, 0, NULL);
1043}
1044
1045static void * newcamd_server(void *cli)
1046{
1047 int rc;
1048 struct s_client * client = (struct s_client *) cli;
1049 client->thread=pthread_self();
1050 pthread_setspecific(getclient, cli);
1051 uchar mbuf[1024];
1052
1053 client->req=(uchar *)malloc(CS_MAXPENDING*REQ_SIZE);
1054 if (!client->req)
1055 {
1056 cs_log("Cannot allocate memory (errno=%d)", errno);
1057 cs_exit(1);
1058 }
1059
1060 memset(client->req, 0, CS_MAXPENDING*REQ_SIZE);
1061 client->ncd_server = 1;
1062 cs_log("client connected to %d port", cfg->ncd_ptab.ports[client->port_idx].s_port);
1063
1064 if (cfg->ncd_ptab.ports[client->port_idx].ncd_key_is_set) {
1065 //port has a des key specified
1066 newcamd_auth_client(client->ip, cfg->ncd_ptab.ports[client->port_idx].ncd_key);
1067 } else {
1068 //default global des key
1069 newcamd_auth_client(client->ip, cfg->ncd_key);
1070 }
1071
1072 // report all cards if using extended mg proto
1073 if (cfg->ncd_mgclient) {
1074 cs_debug("newcamd: extended: report all available cards");
1075 int j, k;
1076 uint8 buf[512];
1077 custom_data_t *cd = malloc(sizeof(struct custom_data));
1078 memset(cd, 0, sizeof(struct custom_data));
1079 memset(buf, 0, sizeof(buf));
1080
1081 buf[0] = MSG_SERVER_2_CLIENT_ADDCARD;
1082
1083 struct s_reader *rdr;
1084 for (rdr=first_reader; rdr ; rdr=rdr->next) {
1085 int flt = 0;
1086 if (!(rdr->grp & client->grp)) continue; //test - skip unaccesible readers
1087 if (rdr->ftab.filts) {
1088 for (j=0; j<CS_MAXFILTERS; j++) {
1089 if (rdr->ftab.filts[j].caid) {
1090 cd->caid = rdr->ftab.filts[j].caid;
1091 for (k=0; k<rdr->ftab.filts[j].nprids; k++) {
1092 cd->provid = rdr->ftab.filts[j].prids[k];
1093 cs_debug("newcamd: extended: report card");
1094
1095 network_message_send(client->udp_fd,
1096 &client->ncd_msgid, buf, 3,
1097 client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1098
1099 flt = 1;
1100 }
1101 }
1102 }
1103 }
1104
1105 if (rdr->caid[0] && !flt) {
1106 if ((rdr->tcp_connected || rdr->card_status == CARD_INSERTED)) {
1107 cd->caid = rdr->caid[0];
1108 for (j=0; j<rdr->nprov; j++) {
1109 if (rdr->card_status == CARD_INSERTED)
1110 cd->provid = (rdr->prid[j][1]) << 16
1111 | (rdr->prid[j][2] << 8) | rdr->prid[j][3];
1112 else
1113 cd->provid = (rdr->prid[j][0]) << 16
1114 | (rdr->prid[j][1] << 8) | rdr->prid[j][2];
1115
1116 cs_debug("newcamd: extended: report card");
1117 network_message_send(client->udp_fd,
1118 &client->ncd_msgid, buf, 3,
1119 client->ncd_skey, COMMTYPE_SERVER, 0, cd);
1120 }
1121 }
1122 }
1123 }
1124 free(cd);
1125 }
1126
1127 // check for clienttimeout, if timeout occurs try to send keepalive / wait for answer
1128 // befor client was disconnected. If keepalive was disabled, exit after clienttimeout
1129 rc=-9;
1130 while(rc==-9)
1131 {
1132 // process_input returns -9 on clienttimeout
1133 while ((rc=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>0)
1134 {
1135 switch(mbuf[2])
1136 {
1137 case 0x80:
1138 case 0x81:
1139 newcamd_process_ecm(mbuf);
1140 break;
1141
1142 case MSG_KEEPALIVE:
1143 newcamd_reply_ka();
1144 break;
1145
1146 default:
1147 if(mbuf[2]>0x81 && mbuf[2]<0x90)
1148 newcamd_process_emm(mbuf+2);
1149 else
1150 {
1151 cs_debug("unknown newcamd command! (%d)", mbuf[2]);
1152 }
1153 }
1154 }
1155
1156 if(rc==-9)
1157 {
1158 if (client->ncd_keepalive)
1159 newcamd_reply_ka();
1160 else
1161 rc=0;
1162 }
1163 }
1164
1165 NULLFREE(client->req);
1166 cs_disconnect_client(client);
1167 return NULL;
1168}
1169
1170/*
1171* client functions
1172*/
1173
1174int newcamd_client_init(struct s_client *client)
1175{
1176 struct sockaddr_in loc_sa;
1177 struct protoent *ptrp;
1178 int p_proto;
1179 char ptxt[16];
1180
1181 client->pfd=0;
1182 if (client->reader->r_port<=0)
1183 {
1184 cs_log("invalid port %d for server %s", client->reader->r_port, client->reader->device);
1185 return(1);
1186 }
1187 if( (ptrp=getprotobyname("tcp")) )
1188 p_proto=ptrp->p_proto;
1189 else
1190 p_proto=6;
1191
1192 client->ip=0;
1193 memset((char *)&loc_sa,0,sizeof(loc_sa));
1194 loc_sa.sin_family = AF_INET;
1195#ifdef LALL
1196 if (cfg->serverip[0])
1197 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
1198 else
1199#endif
1200 loc_sa.sin_addr.s_addr = INADDR_ANY;
1201 loc_sa.sin_port = htons(client->reader->l_port);
1202
1203 if ((client->udp_fd=socket(PF_INET, SOCK_STREAM, p_proto))<0)
1204 {
1205 cs_log("Socket creation failed (errno=%d)", errno);
1206 cs_exit(1);
1207 }
1208
1209#ifdef SO_PRIORITY
1210 if (cfg->netprio)
1211 setsockopt(client->udp_fd, SOL_SOCKET, SO_PRIORITY,
1212 (void *)&cfg->netprio, sizeof(ulong));
1213#endif
1214 if (!client->reader->tcp_ito) {
1215 ulong keep_alive = client->reader->tcp_ito?1:0;
1216 setsockopt(client->udp_fd, SOL_SOCKET, SO_KEEPALIVE,
1217 (void *)&keep_alive, sizeof(ulong));
1218 }
1219
1220 if (client->reader->l_port>0)
1221 {
1222 if (bind(client->udp_fd, (struct sockaddr *)&loc_sa, sizeof (loc_sa))<0)
1223 {
1224 cs_log("bind failed (errno=%d)", errno);
1225 close(client->udp_fd);
1226 return(1);
1227 }
1228 sprintf(ptxt, ", port=%d", client->reader->l_port);
1229 }
1230 else
1231 ptxt[0]='\0';
1232
1233 memset((char *)&client->udp_sa,0,sizeof(client->udp_sa));
1234 client->udp_sa.sin_family = AF_INET;
1235 client->udp_sa.sin_port = htons((u_short)client->reader->r_port);
1236
1237 client->ncd_proto=client->reader->ncd_proto;
1238
1239 cs_log("proxy %s:%d newcamd52%d (fd=%d%s)",
1240 client->reader->device, client->reader->r_port,
1241 (client->reader->ncd_proto==NCD_525)?5:4, client->udp_fd, ptxt);
1242
1243 return(0);
1244}
1245
1246static int newcamd_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
1247{
1248 struct s_reader *rdr = client->reader;
1249
1250 if(!newcamd_connect())
1251 return (-1);
1252
1253 // check server filters
1254 if(!chk_rsfilter(rdr, er))
1255 return(-1);
1256
1257 memcpy(buf, er->ecm, er->l);
1258 return((newcamd_send(buf, er->l, er->srvid)<1) ? (-1) : 0);
1259}
1260
1261
1262static int newcamd_send_emm(EMM_PACKET *ep)
1263{
1264 uchar buf[200];
1265
1266 if(!newcamd_connect())
1267 return (-1);
1268
1269 memcpy(buf, ep->emm, ep->l);
1270 return((newcamd_send(buf, ep->l, 0)<1) ? 0 : 1);
1271}
1272
1273static int newcamd_recv_chk(struct s_client *client, uchar *dcw, int *rc, uchar *buf, int n)
1274{
1275 ushort idx;
1276 *client = *client; //suppress compiler error, but recv_chk should comply to other recv_chk routines...
1277 if( n<21 ) // no cw, ignore others
1278 return(-1);
1279 *rc = 1;
1280 idx = (buf[0] << 8) | buf[1];
1281 memcpy(dcw, buf+5, 16);
1282 return(idx);
1283}
1284
1285void module_newcamd(struct s_module *ph)
1286{
1287 strcpy(ph->desc, "newcamd");
1288 ph->type=MOD_CONN_TCP;
1289 ph->logtxt = ", crypted";
1290 ph->multi=1;
1291 ph->watchdog=1;
1292 ph->s_ip=cfg->ncd_srvip;
1293 ph->s_handler=newcamd_server;
1294 ph->recv=newcamd_recv;
1295 ph->send_dcw=newcamd_send_dcw;
1296 ph->ptab=&cfg->ncd_ptab;
1297 if( ph->ptab->nports==0 )
1298 ph->ptab->nports=1; // show disabled in log
1299 ph->c_multi=1;
1300 ph->c_init=newcamd_client_init;
1301 ph->c_recv_chk=newcamd_recv_chk;
1302 ph->c_send_ecm=newcamd_send_ecm;
1303 ph->c_send_emm=newcamd_send_emm;
1304 ph->num=R_NEWCAMD;
1305}
Note: See TracBrowser for help on using the repository browser.