source: trunk/module-newcamd.c@ 3653

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

get rid of extern reader declararions

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