source: trunk/module-newcamd.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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