source: trunk/module-newcamd.c@ 8

Last change on this file since 8 was 8, checked in by smurzch2, 12 years ago

Start repository for OSCam (Open Source Cam)

The start is from the MpCS source code. Thanks a lot to the authors for this
great sources.

File size: 31.8 KB
Line 
1#include "globals.h"
2
3#define CWS_NETMSGSIZE 240
4
5typedef unsigned char uint8;
6typedef unsigned short uint16;
7typedef unsigned int uint32;
8typedef unsigned long long uint64;
9
10#define CWS_FIRSTCMDNO 0xe0
11typedef enum
12{
13 MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
14 MSG_CLIENT_2_SERVER_LOGIN_ACK,
15 MSG_CLIENT_2_SERVER_LOGIN_NAK,
16 MSG_CARD_DATA_REQ,
17 MSG_CARD_DATA,
18 MSG_SERVER_2_CLIENT_NAME,
19 MSG_SERVER_2_CLIENT_NAME_ACK,
20 MSG_SERVER_2_CLIENT_NAME_NAK,
21 MSG_SERVER_2_CLIENT_LOGIN,
22 MSG_SERVER_2_CLIENT_LOGIN_ACK,
23 MSG_SERVER_2_CLIENT_LOGIN_NAK,
24 MSG_ADMIN,
25 MSG_ADMIN_ACK,
26 MSG_ADMIN_LOGIN,
27 MSG_ADMIN_LOGIN_ACK,
28 MSG_ADMIN_LOGIN_NAK,
29 MSG_ADMIN_COMMAND,
30 MSG_ADMIN_COMMAND_ACK,
31 MSG_ADMIN_COMMAND_NAK,
32 MSG_KEEPALIVE = CWS_FIRSTCMDNO + 0x1d
33} net_msg_type_t;
34
35typedef enum
36{
37 COMMTYPE_CLIENT,
38 COMMTYPE_SERVER
39} comm_type_t;
40
41#define REQ_SIZE 2
42static uchar *req=0;
43static int ncd_proto=NCD_AUTO;
44
45static int network_message_send(int handle, uint16 *netMsgId, uint8 *buffer,
46 int len, uint8 *deskey, comm_type_t commType,
47 ushort sid)
48{
49 uint8 netbuf[CWS_NETMSGSIZE];
50 int head_size;
51 head_size = (ncd_proto==NCD_524)?8:12;
52
53 if (len < 3 || len + head_size > CWS_NETMSGSIZE || handle < 0)
54 return -1;
55 buffer[1] = (buffer[1] & 0xf0) | (((len - 3) >> 8) & 0x0f);
56 buffer[2] = (len - 3) & 0xff;
57 memcpy(netbuf+head_size, buffer, len);
58 len += head_size;
59 if (netMsgId) {
60 switch(commType)
61 {
62 case COMMTYPE_CLIENT:
63 (*netMsgId)++;
64 break;
65 case COMMTYPE_SERVER:
66 if( *netMsgId == 0xFFFE ) *netMsgId = 0; // èëè 0xFFFF ?
67 break;
68 }
69 netbuf[2] = (*netMsgId) >> 8;
70 netbuf[3] = (*netMsgId) & 0xff;
71 }
72 else
73 netbuf[2] = netbuf[3] = 0;
74 memset(netbuf+4, 0, (ncd_proto==NCD_524)?4:8);
75 if( sid ) {
76 netbuf[(ncd_proto==NCD_524)?6:4] = (uchar)(sid>>8); //sid
77 netbuf[(ncd_proto==NCD_524)?7:5] = (uchar)(sid);
78 }
79 netbuf[0] = (len - 2) >> 8;
80 netbuf[1] = (len - 2) & 0xff;
81 cs_ddump(netbuf, len, "send %d bytes to %s", len, remote_txt());
82 if ((len = des_encrypt(netbuf, len, deskey)) < 0)
83 return -1;
84 netbuf[0] = (len - 2) >> 8;
85 netbuf[1] = (len - 2) & 0xff;
86 return send(handle, netbuf, len, 0);
87}
88
89static int network_message_receive(int handle, uint16 *netMsgId, uint8 *buffer,
90 uint8 *deskey, comm_type_t commType)
91{
92 int len, ncd_off, msgid;
93 uint8 netbuf[CWS_NETMSGSIZE];
94 int returnLen;
95
96 if (!buffer || handle < 0)
97 return -1;
98 len = recv(handle, netbuf, 2, 0);
99 cs_debug("nmr(): len=%d, errno=%d", len, (len==-1)?errno:0);
100 if (!len) {
101 cs_debug("nmr: 1 return 0");
102 network_tcp_connection_close(handle);
103 return 0;
104 }
105 if (len != 2) {
106 cs_debug("nmr: len!=2");
107 network_tcp_connection_close(handle);
108 return -1;
109 }
110 if (((netbuf[0] << 8) | netbuf[1]) > CWS_NETMSGSIZE - 2) {
111 cs_debug("nmr: 1 return -1");
112 return -1;
113 }
114
115 len = recv(handle, netbuf+2, (netbuf[0] << 8) | netbuf[1], 0);
116 if (!len) {
117 cs_debug("nmr: 2 return 0");
118 return 0;
119 }
120 if (len != ((netbuf[0] << 8) | netbuf[1])) {
121 cs_debug("nmr: 2 return -1");
122 return -1;
123 }
124 len += 2;
125 if ((len = des_decrypt(netbuf, len, deskey)) < 11 ) { // 15(newcamd525) or 11 ???
126 cs_debug("nmr: can't decrypt, invalid des key?");
127 sleep(2);
128 return -1;
129 }
130 //cs_ddump(netbuf, len, "nmr: decrypted data, len=%d", len);
131 msgid = (netbuf[2] << 8) | netbuf[3];
132
133 if( ncd_proto==NCD_AUTO ) {
134 // auto detect
135 int l5 = (((netbuf[13] & 0x0f) << 8) | netbuf[14]) + 3;
136 int l4 = (((netbuf[9] & 0x0f) << 8) | netbuf[10]) + 3;
137
138 if( (l5<=len-12) && ((netbuf[12]&0xF0)==0xE0 || (netbuf[12]&0xF0)==0x80) )
139 ncd_proto = NCD_525;
140 else if( (l4<=len-8) && ((netbuf[8]&0xF0)==0xE0 || (netbuf[9]&0xF0)==0x80) )
141 ncd_proto = NCD_524;
142 else {
143 cs_debug("nmr: 4 return -1");
144 return -1;
145 }
146
147 cs_debug("nmr: autodetect: newcamd52%d used", (ncd_proto==NCD_525)?5:4);
148 }
149
150 ncd_off=(ncd_proto==NCD_525)?4:0;
151
152 returnLen = (((netbuf[9+ncd_off] & 0x0f) << 8) | netbuf[10+ncd_off]) + 3;
153 if ( returnLen > (len-(8+ncd_off)) ) {
154 cs_debug("nmr: 4 return -1");
155 return -1;
156 }
157
158// cs_ddump(netbuf, len, "nmr: decrypted data");
159 if (netMsgId)
160 {
161 switch (commType)
162 {
163 case COMMTYPE_SERVER:
164 *netMsgId = msgid;
165 break;
166
167 case COMMTYPE_CLIENT:
168 //if (*netMsgId != ((netbuf[2] << 8) | netbuf[3])) {
169 cs_debug("nmr: netMsgId=%d, from server=%d, ", *netMsgId, msgid );
170 //return -2;
171 //}
172 break;
173
174 default:
175 cs_debug("nmr: 5 return -1");
176 return -1;
177 break;
178 }
179 }
180 switch(commType)
181 {
182 case COMMTYPE_SERVER:
183 buffer[0]=(ncd_proto==NCD_525)?netbuf[4]:netbuf[6]; // sid
184 buffer[1]=(ncd_proto==NCD_525)?netbuf[5]:netbuf[7];
185 break;
186 case COMMTYPE_CLIENT:
187 buffer[0]=netbuf[2]; // msgid
188 buffer[1]=netbuf[3];
189 break;
190 }
191
192 memcpy(buffer+2, netbuf+(8+ncd_off), returnLen);
193 return returnLen+2;
194}
195
196static void network_cmd_no_data_send(int handle, uint16 *netMsgId,
197 net_msg_type_t cmd, uint8 *deskey,
198 comm_type_t commType)
199{
200 uint8 buffer[CWS_NETMSGSIZE];
201
202 buffer[0] = cmd; buffer[1] = 0;
203 network_message_send(handle, netMsgId, buffer, 3, deskey, commType, 0);
204}
205
206static int network_cmd_no_data_receive(int handle, uint16 *netMsgId,
207 uint8 *deskey, comm_type_t commType)
208{
209 uint8 buffer[CWS_NETMSGSIZE];
210
211 if (network_message_receive(handle, netMsgId, buffer, deskey, commType) != 3+2)
212 return -1;
213 return buffer[2];
214}
215
216int
217connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec)
218{
219 int flags, n, error;
220 socklen_t len;
221 fd_set rset, wset;
222 struct timeval tval;
223
224 flags = fcntl(sockfd, F_GETFL, 0);
225 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
226
227 error = 0;
228 cs_debug("conn_nb 1 (fd=%d)", sockfd);
229
230 if ( (n = connect(sockfd, saptr, salen)) < 0) {
231 if( errno==EALREADY ) {
232 cs_debug("conn_nb in progress, errno=%d", errno);
233 return(-1);
234 }
235 else if( errno==EISCONN ) {
236 cs_debug("conn_nb already connected, errno=%d", errno);
237 goto done;
238 }
239 cs_debug("conn_nb 2 (fd=%d)", sockfd);
240 if (errno != EINPROGRESS) {
241 cs_debug("conn_nb 3 (fd=%d)", sockfd);
242 return(-1);
243 }
244 }
245
246 /* Do whatever we want while the connect is taking place. */
247 if (n == 0)
248 goto done; /* connect completed immediately */
249
250 FD_ZERO(&rset);
251 FD_SET(sockfd, &rset);
252 wset = rset;
253 tval.tv_sec = nsec;
254 tval.tv_usec = 0;
255
256 if ( (n = select(sockfd+1, &rset, &wset, 0, nsec ? &tval : 0)) == 0) {
257 //close(sockfd); // timeout
258 cs_debug("conn_nb 4 (fd=%d)", sockfd);
259 errno = ETIMEDOUT;
260 return(-1);
261 }
262
263 cs_debug("conn_nb 5 (fd=%d)", sockfd);
264
265 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
266 cs_debug("conn_nb 6 (fd=%d)", sockfd);
267 len = sizeof(error);
268 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
269 cs_debug("conn_nb 7 (fd=%d)", sockfd);
270 return(-1); // Solaris pending error
271 }
272 } else {
273 cs_debug("conn_nb 8 (fd=%d)", sockfd);
274 return -2;
275 }
276
277done:
278 cs_debug("conn_nb 9 (fd=%d)", sockfd);
279 fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
280
281 if (error) {
282 cs_debug("conn_nb 10 (fd=%d)", sockfd);
283 //close(sockfd); /* just in case */
284 errno = error;
285 return(-1);
286 }
287 return(0);
288}
289
290int network_tcp_connection_open(uint8 *hostname, uint16 port)
291{
292 int flags;
293 if( connect_nonb(client[cs_idx].udp_fd,
294 (struct sockaddr *)&client[cs_idx].udp_sa,
295 sizeof(client[cs_idx].udp_sa), 5) < 0)
296 {
297 cs_log("connect(fd=%d) failed: (errno=%d)", client[cs_idx].udp_fd, errno);
298 return -1;
299 }
300 flags = fcntl(client[cs_idx].udp_fd, F_GETFL, 0);
301 flags &=~ O_NONBLOCK;
302 fcntl(client[cs_idx].udp_fd, F_SETFL, flags );
303
304 return client[cs_idx].udp_fd;
305}
306
307void newcamd_reply_ka()
308{
309 if( !client[cs_idx].udp_fd )
310 {
311 cs_debug("invalid client fd=%d", client[cs_idx].udp_fd);
312 return;
313 }
314 cs_debug("send keep_alive");
315 network_cmd_no_data_send(client[cs_idx].udp_fd, &client[cs_idx].ncd_msgid,
316 MSG_KEEPALIVE, client[cs_idx].ncd_skey,
317 COMMTYPE_SERVER);
318}
319
320static int connect_newcamd_server()
321{
322 uint32 i;
323 uint8 buf[CWS_NETMSGSIZE];
324 uint8 keymod[14];
325 uint8 *key;
326 int handle=0;
327
328 uint32 index;
329 uint8 *passwdcrypt;
330 uint8 login_answer;
331 int bytes_received;
332
333 if(reader[ridx].device[0] == 0 || reader[ridx].r_pwd[0] == 0 ||
334 reader[ridx].r_usr[0] == 0 || reader[ridx].r_port == 0)
335 return -5;
336
337 // 1. Connect
338 //
339 handle = network_tcp_connection_open(reader[ridx].device, reader[ridx].r_port);
340 if(handle < 0) return -1;
341
342 // 2. Get init sequence
343 //
344 reader[ridx].ncd_msgid = 0;
345 if( read(handle, keymod, sizeof(keymod)) != sizeof(keymod)) {
346 cs_log("server does not return 14 bytes");
347 network_tcp_connection_close(handle);
348 return -2;
349 }
350 cs_ddump(keymod, 14, "server init sequence:");
351 key = des_login_key_get(keymod, reader[ridx].ncd_key, 14);
352
353 // 3. Send login info
354 //
355 index = 3;
356 buf[0] = MSG_CLIENT_2_SERVER_LOGIN;
357 buf[1] = 0;
358 strcpy(buf+index, reader[ridx].r_usr);
359 passwdcrypt = (uint8*)__md5_crypt(reader[ridx].r_pwd, "$1$abcdefgh$");
360 index += strlen(reader[ridx].r_usr)+1;
361 strcpy(buf+index, passwdcrypt);
362
363 //cs_debug("login to server %s:%d user=%s, pwd=%s, len=%d", reader[ridx].device,
364 // reader[ridx].r_port, reader[ridx].r_usr, reader[ridx].r_pwd,
365 // index+strlen(passwdcrypt)+1);
366 network_message_send(handle, 0, buf, index+strlen(passwdcrypt)+1, key,
367 COMMTYPE_CLIENT, 0);
368
369 // 3.1 Get login answer
370 //
371 login_answer=network_cmd_no_data_receive(handle, &reader[ridx].ncd_msgid,
372 key, COMMTYPE_CLIENT);
373 if( login_answer == MSG_CLIENT_2_SERVER_LOGIN_NAK )
374 {
375 cs_log("login failed for user '%s'", reader[ridx].r_usr);
376 network_tcp_connection_close(handle);
377 return -3;
378 }
379 if( login_answer != MSG_CLIENT_2_SERVER_LOGIN_ACK )
380 {
381 cs_log("expected MSG_CLIENT_2_SERVER_LOGIN_ACK (%02X), received %02X",
382 MSG_CLIENT_2_SERVER_LOGIN_ACK, login_answer);
383 network_tcp_connection_close(handle);
384 return -3;
385 }
386
387 // 4. Send MSG_CARD_DATE_REQ
388 //
389 key = des_login_key_get(reader[ridx].ncd_key, passwdcrypt, strlen(passwdcrypt));
390
391 network_cmd_no_data_send(handle, &reader[ridx].ncd_msgid, MSG_CARD_DATA_REQ,
392 key, COMMTYPE_CLIENT);
393 bytes_received = network_message_receive(handle, &reader[ridx].ncd_msgid, buf,
394 key, COMMTYPE_CLIENT);
395 if( bytes_received < 16 || buf[2] != MSG_CARD_DATA ) {
396 cs_log("expected MSG_CARD_DATA (%02X), received %02X",
397 MSG_CARD_DATA, buf[2]);
398 network_tcp_connection_close(handle);
399 return -4;
400 }
401
402 // 5. Parse CAID and PROVID(s)
403 //
404 reader[ridx].caid[0] = (ushort)((buf[4+2]<<8) | buf[5+2]);
405 cs_log("server %s:%d caid: %04X",
406 reader[ridx].device, reader[ridx].r_port, reader[ridx].caid[0]);
407 reader[ridx].nprov = buf[14+2];
408
409 for( i=0; i<reader[ridx].nprov; i++ )
410 {
411 reader[ridx].prid[i][0] = buf[15+2+11*i];
412 reader[ridx].prid[i][1] = buf[16+2+11*i];
413 reader[ridx].prid[i][2] = buf[17+2+11*i];
414 cs_log("provider #%d: %02X%02X%02X",
415 i,
416 reader[ridx].prid[i][0],
417 reader[ridx].prid[i][1],
418 reader[ridx].prid[i][2]);
419 }
420 memcpy(reader[ridx].ncd_skey, key, 16);
421
422 // 6. Set connected info
423 //
424 reader[ridx].tcp_connected=1;
425 reader[ridx].last_g = reader[ridx].last_s = time((time_t *)0);
426
427// cs_log("last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
428
429 // !!! Only after connect() on client[cs_idx].udp_fd (Linux)
430 pfd=client[cs_idx].udp_fd;
431
432 return 0;
433}
434
435static int newcamd_connect()
436{
437 if (!reader[ridx].tcp_connected && connect_newcamd_server() < 0 ) return 0;
438 if (!client[cs_idx].udp_fd) return 0;
439
440 return 1;
441}
442
443
444static int newcamd_send(uchar *buf, int ml, ushort sid)
445{
446 if( !newcamd_connect() ) return(-1);
447
448 //cs_ddump(buf, ml, "send %d bytes to %s", ml, remote_txt());
449 return(network_message_send(client[cs_idx].udp_fd, &reader[ridx].ncd_msgid,
450 buf, ml, reader[ridx].ncd_skey, COMMTYPE_CLIENT, sid));
451}
452
453static int newcamd_recv(uchar *buf, int l)
454{
455 int rc, rs;
456 if (is_server)
457 rs=network_message_receive(client[cs_idx].udp_fd,
458 &client[cs_idx].ncd_msgid, buf,
459 client[cs_idx].ncd_skey, COMMTYPE_SERVER);
460 else
461 {
462 if (!client[cs_idx].udp_fd) return(-1);
463 rs=network_message_receive(client[cs_idx].udp_fd,
464 &reader[ridx].ncd_msgid,buf,
465 reader[ridx].ncd_skey, COMMTYPE_CLIENT);
466 }
467 if (rs<5) rc=(-1);
468 else rc=rs;
469 cs_ddump(buf, rs, "received %d bytes from %s", rs, remote_txt());
470 client[cs_idx].last = time((time_t *) 0);
471 if( rc==-1 )
472 if (rs > 0)
473 cs_log("packet to small (%d bytes)", rs);
474 else
475 cs_log("Connection closed to %s", remote_txt());
476 return(rc);
477}
478
479static unsigned int seed;
480static uchar fast_rnd()
481{
482 unsigned int offset = 12923;
483 unsigned int multiplier = 4079;
484
485 seed = seed * multiplier + offset;
486 return (uchar)(seed % 0xFF);
487}
488
489static FILTER mk_user_au_ftab(int au)
490{
491 int i,j,found;
492 FILTER filt;
493 FILTER *pufilt;
494
495 filt.caid = reader[au].caid[0];
496 filt.nprids = 0;
497 memset(&filt.prids, 0, sizeof(filt.prids));
498 pufilt = &client[cs_idx].ftab.filts[0];
499
500 for( i=0; i<reader[au].nprov; i++ )
501 filt.prids[filt.nprids++] = b2i(3, &reader[au].prid[i][1]);
502
503 for( i=0; i<pufilt->nprids; i++ )
504 {
505 for( j=found=0; (!found)&&(j<filt.nprids); j++ )
506 if( pufilt->prids[i]==filt.prids[j] )
507 found=1;
508 if( !found )
509 filt.prids[filt.nprids++] = pufilt->prids[i];
510 }
511
512 return filt;
513}
514
515static FILTER mk_user_ftab()
516{
517 FILTER *psfilt = 0;
518 FILTER filt;
519 int port_idx,i,j,k,c;
520
521 filt.caid = 0;
522 filt.nprids = 0;
523 memset(&filt.prids, 0, sizeof(filt.prids));
524
525 port_idx = client[cs_idx].port_idx;
526 psfilt = &cfg->ncd_ptab.ports[port_idx].ftab.filts[0];
527
528 // 1. CAID
529 // search server CAID in client CAID
530 for( c=i=0; i<CS_MAXCAIDTAB; i++ )
531 {
532 int ctab_caid;
533 ctab_caid = client[cs_idx].ctab.caid[i]&client[cs_idx].ctab.mask[i];
534 if( ctab_caid ) c++;
535 if( psfilt->caid==ctab_caid )
536 {
537 filt.caid=ctab_caid;
538 break;
539 }
540 }
541 if( c && !filt.caid )
542 {
543 cs_log("no valid CAID found in CAID for user '%s'", client[cs_idx].usr);
544 return filt;
545 }
546
547 // search CAID in client IDENT
548 cs_debug("client[%d].%s nfilts=%d, filt.caid=%04X", cs_idx,
549 client[cs_idx].usr, client[cs_idx].ftab.nfilts, filt.caid);
550
551 if( !filt.caid && client[cs_idx].ftab.nfilts )
552 {
553 int fcaids;
554 for( i=fcaids=0; i<client[cs_idx].ftab.nfilts; i++ )
555 {
556 ushort ucaid=client[cs_idx].ftab.filts[i].caid;
557 if( ucaid ) fcaids++;
558 if( ucaid && psfilt->caid==ucaid )
559 {
560 filt.caid = ucaid;
561 break;
562 }
563 }
564 if( fcaids==client[cs_idx].ftab.nfilts && !filt.caid )
565 {
566 cs_log("no valid CAID found in IDENT for user '%s'", client[cs_idx].usr);
567 //cs_disconnect_client();
568 return filt;
569 }
570 }
571 // empty client CAID - use server CAID
572 if( !filt.caid ) filt.caid=psfilt->caid;
573
574 // 2. PROVID
575 if( !client[cs_idx].ftab.nfilts )
576 {
577 filt.nprids = psfilt->nprids;
578 for( i=0; i<filt.nprids; i++ )
579 filt.prids[i] = psfilt->prids[i]; // use server PROVID(s)
580 return filt;
581 }
582
583 // search in client IDENT
584 for( i=0; i<psfilt->nprids; i++ )
585 {
586 cs_debug("search server provid #%d: %06X", i, psfilt->prids[i]);
587 for( j=0; j<client[cs_idx].ftab.nfilts; j++ )
588 {
589 ulong ucaid = client[cs_idx].ftab.filts[j].caid;
590 cs_debug("client caid #%d: %04X", j, ucaid);
591 if( !ucaid || ucaid==filt.caid )
592 {
593 if( client[cs_idx].ftab.filts[j].nprids )
594 {
595 for( k=0; k<client[cs_idx].ftab.filts[j].nprids; k++ )
596 if( psfilt->prids[i]==client[cs_idx].ftab.filts[j].prids[k] )
597 filt.prids[filt.nprids++]=client[cs_idx].ftab.filts[j].prids[k];
598 }
599 else {
600 filt.nprids = psfilt->nprids;
601 for( k=0; k<filt.nprids; k++ )
602 filt.prids[k] = psfilt->prids[k]; // use server PROVID(s)
603 }
604 goto end;
605 }
606 }
607 }
608
609 if( !filt.nprids )
610 {
611 cs_log("no valid PROVID(s) found in CAID for user '%s'", client[cs_idx].usr);
612 //cs_disconnect_client();
613 }
614end:
615 return filt;
616}
617
618static int newcamd_auth_client(in_addr_t ip)
619{
620 int i, ok = 0;
621 uchar *usr=NULL, *pwd=NULL;
622 struct s_auth *account;
623 uchar buf[14];
624 uchar *key=0;
625 uint8 *passwdcrypt = NULL;
626 int au;
627
628 // make random 14 bytes
629 seed = (unsigned int) time((time_t*)0);
630 for( i=0; i<14; i++ ) buf[i]=fast_rnd();
631
632 // send init sequence
633 send(client[cs_idx].udp_fd, buf, 14, 0);
634 key = des_login_key_get(buf, cfg->ncd_key, 14);
635 memcpy(client[cs_idx].ncd_skey, key, 16);
636 client[cs_idx].ncd_msgid = 0;
637
638 i=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle);
639 if ( i>0 )
640 {
641 if( mbuf[2] != MSG_CLIENT_2_SERVER_LOGIN ) {
642 cs_debug("expected MSG_CLIENT_2_SERVER_LOGIN (%02X), received %02X",
643 MSG_CLIENT_2_SERVER_LOGIN, mbuf[2]);
644 if(req) { free(req); req=0;}
645 cs_exit(0);
646 }
647 usr=mbuf+5;
648 pwd=usr+strlen(usr)+1;
649 //cs_debug("usr=%s,pwd=%s", usr, pwd);
650 }
651 else {
652 cs_debug("bad client login request");
653 if(req) { free(req); req=0;}
654 cs_exit(0);
655 }
656
657 for (ok=0, account=cfg->account; (usr) && (account) && (!ok); account=account->next)
658 {
659 cs_debug("account->usr=%s", account->usr);
660 if( (ok=(!strcmp(usr, account->usr))) )
661 {
662 passwdcrypt = (uint8*)__md5_crypt(account->pwd, "$1$abcdefgh$");
663 cs_debug("account->pwd=%s", passwdcrypt);
664 if( !strcmp(pwd, passwdcrypt) )
665 {
666 client[cs_idx].crypted=1;
667 if (cs_auth_client(account, NULL))
668 {
669 if(req) { free(req); req=0;}
670 cs_exit(0);
671 }
672 break;
673 }
674 else
675 ok=0;
676 }
677 }
678
679 if (ok)
680 {
681 au = client[cs_idx].au;
682
683 if( au!=-1)
684 {
685 if (reader[au].card_system <= 0)
686 {
687 // Init for AU enabled card not finished, reject Client
688 ok = 0;
689 au = -2; // Flag zur Logausgabe
690 }
691 }
692 }
693
694 network_cmd_no_data_send(client[cs_idx].udp_fd, &client[cs_idx].ncd_msgid,
695 (ok)?MSG_CLIENT_2_SERVER_LOGIN_ACK:MSG_CLIENT_2_SERVER_LOGIN_NAK,
696 client[cs_idx].ncd_skey, COMMTYPE_SERVER);
697
698 if (ok)
699 {
700 FILTER pufilt_noau = { 0 };
701 FILTER *pufilt = 0;
702
703 key = des_login_key_get(cfg->ncd_key, passwdcrypt, strlen(passwdcrypt));
704 memcpy(client[cs_idx].ncd_skey, key, 16);
705
706 i=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle);
707 if( i>0 )
708 {
709 int j,len=15;
710 if( mbuf[2] != MSG_CARD_DATA_REQ) {
711 cs_debug("expected MSG_CARD_DATA_REQ (%02X), received %02X",
712 MSG_CARD_DATA_REQ, mbuf[2]);
713 if(req) { free(req); req=0;}
714 cs_exit(0);
715 }
716
717 client[cs_idx].ftab.filts[0] = mk_user_ftab();
718
719 pufilt = &client[cs_idx].ftab.filts[0];
720
721 // remember user filter
722 memcpy(&pufilt_noau, pufilt, sizeof(FILTER));
723
724 if( au!=-1)
725 {
726 unsigned char equal = 1;
727
728 client[cs_idx].ftab.filts[0] = mk_user_au_ftab(au);
729 pufilt = &client[cs_idx].ftab.filts[0];
730
731 // check if user filter CAID and PROVID is the same as CAID and PROVID of the AU reader
732
733 if ((pufilt->caid != pufilt_noau.caid))
734 {
735 cs_log("CAID server: %04X, CAID card: %04X, not equal, AU disabled",pufilt_noau.caid,pufilt->caid);
736 equal = 0;
737 }
738
739 for( j=0; equal && j<pufilt_noau.nprids && j<pufilt->nprids; j++)
740 {
741 if (pufilt->prids[j] != pufilt_noau.prids[j])
742 {
743 cs_log("PROVID%d server: %04X, PROVID%d card: %04X, not equal, AU disabled",j,pufilt_noau.prids[j],j,pufilt->prids[j]);
744 equal = 0;
745 }
746 }
747
748 if (!equal)
749 {
750 // Not equal -> AU must set to disabled -> set back to user filter
751 memcpy(pufilt, &pufilt_noau, sizeof(FILTER));
752 au = -1;
753 }
754 }
755 client[cs_idx].ftab.nfilts = 1;
756
757 mbuf[0] = MSG_CARD_DATA;
758 mbuf[1] = 0x00;
759 mbuf[2] = 0x00;
760
761 // AU always set to true because some clients cannot handle "non-AU"
762 // For security reason don't send the real hexserial (see below)
763 // if a non-AU-client sends an EMM-request it will be thrown away
764 // (see function "newcamd_process_emm")
765 /*
766 if( au!=-1 )
767 mbuf[3] = 1;
768 else
769 mbuf[3] = cs_idx+10; // Unique user number
770 */
771 mbuf[3] = 1;
772
773 mbuf[4] = (uchar)(pufilt->caid>>8);
774 mbuf[5] = (uchar)(pufilt->caid);
775 mbuf[6] = 0x00;
776 mbuf[7] = 0x00;
777 if( au!=-1 )
778 {
779 if (((pufilt->caid >= 0x1700) && (pufilt->caid <= 0x1799)) || // Betacrypt
780 ((pufilt->caid >= 0x0600) && (pufilt->caid <= 0x0699))) // Irdeto
781 {
782 // only 4 Bytes Hexserial for newcamd clients (Hex Base + Hex Serial)
783 // first 2 Byte always 00
784 mbuf[8]=0x00; //serial only 4 bytes
785 mbuf[9]=0x00; //serial only 4 bytes
786 // 1 Byte Hex Base (see reader-irdeto.c how this is stored in "reader[au].hexserial")
787 mbuf[10]=reader[au].hexserial[3];
788 // 3 Bytes Hex Serial (see reader-irdeto.c how this is stored in "reader[au].hexserial")
789 mbuf[11]=reader[au].hexserial[0];
790 mbuf[12]=reader[au].hexserial[1];
791 mbuf[13]=reader[au].hexserial[2];
792 }
793 else
794 {
795 mbuf[8] = reader[au].hexserial[0];//So this is right!
796 mbuf[9] = reader[au].hexserial[1];
797 mbuf[10] = reader[au].hexserial[2];
798 mbuf[11] = reader[au].hexserial[3];
799 mbuf[12] = reader[au].hexserial[4];
800 mbuf[13] = reader[au].hexserial[5];
801 }
802
803 }
804 else
805 {
806 client[cs_idx].au = -1;
807 // send "faked" Hexserial to client
808 if (((pufilt->caid >= 0x1700) && (pufilt->caid <= 0x1799)) || // Betacrypt
809 ((pufilt->caid >= 0x0600) && (pufilt->caid <= 0x0699))) // Irdeto
810 {
811 mbuf[8] = 0x00;
812 mbuf[9] = 0x00;
813 mbuf[10] = fast_rnd();
814 mbuf[11] = fast_rnd();
815 mbuf[12] = fast_rnd();
816 mbuf[13] = fast_rnd();
817 }
818 else
819 {
820 mbuf[8] = fast_rnd();
821 mbuf[9] = fast_rnd();
822 mbuf[10] = fast_rnd();
823 mbuf[11] = fast_rnd();
824 mbuf[12] = fast_rnd();
825 mbuf[13] = fast_rnd();
826 }
827 }
828 mbuf[14] = pufilt->nprids;
829 for( j=0; j<pufilt->nprids; j++)
830 {
831 if ((pufilt->caid >= 0x0600) && (pufilt->caid <= 0x0699)) // Irdeto
832 {
833 mbuf[15+11*j] = 0;
834 mbuf[16+11*j] = 0;
835 mbuf[17+11*j] = j;
836 }
837 else
838 {
839 mbuf[15+11*j] = (uchar)(pufilt->prids[j]>>16);
840 mbuf[16+11*j] = (uchar)(pufilt->prids[j]>>8);
841 mbuf[17+11*j] = (uchar)(pufilt->prids[j]);
842 }
843 mbuf[18+11*j] = 0x00;
844 mbuf[19+11*j] = 0x00;
845 mbuf[20+11*j] = 0x00;
846 mbuf[21+11*j] = 0x00;
847 if( au!=-1 )
848 { // check if user provid from IDENT exists on card
849 int k, found;
850 ulong rprid;
851 found=0;
852 if( pufilt->caid==reader[au].caid[0] )
853 {
854 for( k=0; (k<reader[au].nprov); k++ )
855 {
856 rprid=b2i(3, &reader[au].prid[k][1]);
857 if( rprid==pufilt->prids[j] )
858 {
859 if ((pufilt->caid >= 0x0600) && (pufilt->caid <= 0x0699)) // Irdeto
860 {
861 mbuf[22+11*j] = reader[au].prid[k][0];
862 mbuf[23+11*j] = reader[au].prid[k][1];
863 mbuf[24+11*j] = reader[au].prid[k][2];
864 mbuf[25+11*j] = reader[au].prid[k][3];
865 }
866 else
867 {
868 mbuf[22+11*j] = reader[au].sa[k][0];
869 mbuf[23+11*j] = reader[au].sa[k][1];
870 mbuf[24+11*j] = reader[au].sa[k][2];
871 mbuf[25+11*j] = reader[au].sa[k][3];
872 }
873 found=1;
874 break;
875 }
876 }
877 }
878 if( !found )
879 {
880 mbuf[22+11*j] = 0x00;
881 mbuf[23+11*j] = 0x00;
882 mbuf[24+11*j] = 0x00;
883 mbuf[25+11*j] = 0x00;
884 }
885 }
886 else
887 {
888 if ((pufilt->caid >= 0x0600) && (pufilt->caid <= 0x0699)) // Irdeto
889 {
890 mbuf[22+11*j] = 0x00;
891 mbuf[23+11*j] = (uchar)(pufilt->prids[j]>>16);
892 mbuf[24+11*j] = (uchar)(pufilt->prids[j]>>8);
893 mbuf[25+11*j] = (uchar)(pufilt->prids[j]);
894 }
895 else
896 {
897 mbuf[22+11*j] = 0x00;
898 mbuf[23+11*j] = 0x00;
899 mbuf[24+11*j] = 0x00;
900 mbuf[25+11*j] = 0x00;
901 }
902 }
903 len+=11;
904 }
905
906 if( network_message_send(client[cs_idx].udp_fd, &client[cs_idx].ncd_msgid,
907 mbuf, len, key, COMMTYPE_SERVER, 0 ) <0 ) {
908 if(req) { free(req); req=0;}
909 cs_exit(0);
910 }
911 }
912 }
913 else
914 {
915 if (au < -1)
916 cs_auth_client(0, "Init for AU enabled card not finished");
917 else
918 cs_auth_client(0, usr ? "login failure" : "no user");
919 if(req) { free(req); req=0;}
920 cs_exit(0);
921 }
922}
923
924static void newcamd_send_dcw(ECM_REQUEST *er)
925{
926 int len;
927 ushort cl_msgid;
928
929 if (!client[cs_idx].udp_fd) {
930 cs_debug("ncd_send_dcw: error: client[cs_idx].udp_fd=%d", client[cs_idx].udp_fd);
931 return;
932 }
933 memcpy(&cl_msgid, req+(er->cpti*REQ_SIZE), 2); // get client ncd_msgid + 0x8x
934 mbuf[0] = er->ecm[0];
935 if( client[cs_idx].ftab.filts[0].nprids==0 || er->rc>3 /*not found*/)
936 {
937 len=3;
938 mbuf[1] = mbuf[2] = 0x00;
939 }
940 else
941 {
942 len = 19;
943 mbuf[1] = mbuf[2] = 0x10;
944 memcpy(mbuf+3, er->cw, 16);
945 }
946
947 cs_debug("ncd_send_dcw: er->cpti=%d, cl_msgid=%d, %02X", er->cpti, cl_msgid, mbuf[0]);
948
949 network_message_send(client[cs_idx].udp_fd, &cl_msgid, mbuf, len,
950 client[cs_idx].ncd_skey, COMMTYPE_SERVER, 0);
951}
952
953static void newcamd_process_ecm(uchar *buf, int l)
954{
955 int pi;
956 ECM_REQUEST *er;
957 if (!(er=get_ecmtask())) {
958 return;
959 }
960 // save client ncd_msgid
961 memcpy(req+(er->cpti*REQ_SIZE), &client[cs_idx].ncd_msgid, 2);
962 cs_debug("ncd_process_ecm: er->cpti=%d, cl_msgid=%d, %02X", er->cpti,
963 client[cs_idx].ncd_msgid, buf[2]);
964 er->l=buf[4]+3;
965 er->srvid = (buf[0]<<8)|buf[1];
966 er->caid = 0;
967 pi = client[cs_idx].port_idx;
968 if( cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
969 er->caid=cfg->ncd_ptab.ports[pi].ftab.filts[0].caid;
970 memcpy(er->ecm, buf+2, er->l);
971 get_cw(er);
972}
973
974static void newcamd_process_emm(uchar *buf, int l)
975{
976 int au, ok=1;
977 ushort caid;
978
979 memset(&epg, 0, sizeof(epg));
980 au=client[cs_idx].au;
981
982 // if client is not allowed to do AU just send back the OK-answer to
983 // the client and do nothing else with the received data
984 if ((au>=0) && (au<=CS_MAXREADER))
985 {
986 epg.l=buf[2]+3;
987 caid = client[cs_idx].ftab.filts[0].caid;
988 epg.caid[0] = (uchar)(caid>>8);
989 epg.caid[1] = (uchar)(caid);
990 if( caid == 0x0500 )
991 {
992 ushort emm_head;
993
994 emm_head = (buf[0]<<8) | buf[1];
995 switch( emm_head )
996 {
997 case 0x8e70: // EMM-S
998 memcpy(epg.hexserial+1, buf+3, 4);
999 epg.hexserial[4]=reader[au].hexserial[4];
1000 break;
1001 case 0x8870: // EMM-U
1002 case 0x8c70: // confidential ?
1003 default:
1004 cs_log("unsupported emm type: %04X", emm_head);
1005 ok=0;
1006 }
1007 if( !ok ) cs_log("only EMM-S supported");
1008 }
1009 else
1010 memcpy(epg.hexserial, reader[au].hexserial, 8); // dummy
1011
1012 memcpy(epg.emm, buf, epg.l);
1013 if( ok )
1014 do_emm(&epg);
1015 }
1016 // Should always send an answer to client (also if au is disabled),
1017 // some clients will disconnect if they get no answer
1018 buf[1] = 0x10;
1019 buf[2] = 0x00;
1020 network_message_send(client[cs_idx].udp_fd, &client[cs_idx].ncd_msgid, buf, 3,
1021 client[cs_idx].ncd_skey, COMMTYPE_SERVER, 0);
1022}
1023
1024static void newcamd_server()
1025{
1026 int n;
1027
1028 req=(uchar *)malloc(CS_MAXPENDING*REQ_SIZE);
1029 if (!req)
1030 {
1031 cs_log("Cannot allocate memory (errno=%d)", errno);
1032 cs_exit(1);
1033 }
1034 memset(req, 0, CS_MAXPENDING*REQ_SIZE);
1035
1036 client[cs_idx].ncd_server = 1;
1037 cs_debug("client connected to %d port",
1038 cfg->ncd_ptab.ports[client[cs_idx].port_idx].s_port);
1039 newcamd_auth_client(client[cs_idx].ip);
1040
1041 n=-9;
1042 while(n==-9)
1043 while ((n=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>0)
1044 {
1045 switch(mbuf[2])
1046 {
1047 case 0x80:
1048 case 0x81:
1049 newcamd_process_ecm(mbuf, n);
1050 break;
1051 case MSG_KEEPALIVE:
1052 newcamd_reply_ka();
1053 break;
1054 default:
1055 if( mbuf[2]>0x81 && mbuf[2]<0x90 )
1056 newcamd_process_emm(mbuf+2, n-2);
1057 else
1058 cs_debug("unknown command !");
1059 }
1060 }
1061 free(req);
1062 cs_disconnect_client();
1063}
1064
1065/*
1066* client functions
1067*/
1068
1069int newcamd_client_init()
1070{
1071 static struct sockaddr_in loc_sa;
1072 struct protoent *ptrp;
1073 int p_proto;
1074 char ptxt[16];
1075
1076 pfd=0;
1077 if (reader[ridx].r_port<=0)
1078 {
1079 cs_log("invalid port %d for server %s", reader[ridx].r_port, reader[ridx].device);
1080 return(1);
1081 }
1082 if( (ptrp=getprotobyname("tcp")) )
1083 p_proto=ptrp->p_proto;
1084 else
1085 p_proto=6;
1086
1087 client[cs_idx].ip=0;
1088 memset((char *)&loc_sa,0,sizeof(loc_sa));
1089 loc_sa.sin_family = AF_INET;
1090#ifdef LALL
1091 if (cfg->serverip[0])
1092 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
1093 else
1094#endif
1095 loc_sa.sin_addr.s_addr = INADDR_ANY;
1096 loc_sa.sin_port = htons(reader[ridx].l_port);
1097
1098 if ((client[cs_idx].udp_fd=socket(PF_INET, SOCK_STREAM, p_proto))<0)
1099 {
1100 cs_log("Socket creation failed (errno=%d)", errno);
1101 cs_exit(1);
1102 }
1103
1104#ifdef SO_PRIORITY
1105 if (cfg->netprio)
1106 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_PRIORITY,
1107 (void *)&cfg->netprio, sizeof(ulong));
1108#endif
1109 if (!reader[ridx].tcp_ito) {
1110 ulong keep_alive = reader[ridx].tcp_ito?1:0;
1111 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_KEEPALIVE,
1112 (void *)&keep_alive, sizeof(ulong));
1113 }
1114
1115 if (reader[ridx].l_port>0)
1116 {
1117 if (bind(client[cs_idx].udp_fd, (struct sockaddr *)&loc_sa, sizeof (loc_sa))<0)
1118 {
1119 cs_log("bind failed (errno=%d)", errno);
1120 close(client[cs_idx].udp_fd);
1121 return(1);
1122 }
1123 sprintf(ptxt, ", port=%d", reader[ridx].l_port);
1124 }
1125 else
1126 ptxt[0]='\0';
1127
1128 memset((char *)&client[cs_idx].udp_sa,0,sizeof(client[cs_idx].udp_sa));
1129 client[cs_idx].udp_sa.sin_family = AF_INET;
1130 client[cs_idx].udp_sa.sin_port = htons((u_short)reader[ridx].r_port);
1131
1132 ncd_proto = reader[ridx].ncd_proto;
1133
1134 cs_log("proxy %s:%d newcamd52%d (fd=%d%s)",
1135 reader[ridx].device, reader[ridx].r_port,
1136 (ncd_proto==NCD_525)?5:4, client[cs_idx].udp_fd, ptxt);
1137 //pfd=client[cs_idx].udp_fd; // !!! we set it after connect() (linux)
1138 return(0);
1139}
1140
1141static int newcamd_send_ecm(ECM_REQUEST *er, uchar *buf)
1142{
1143 //int rc=(-1);
1144 if (!client[cs_idx].udp_sa.sin_addr.s_addr) // once resolved at least
1145 return(-1);
1146
1147 // check server filters
1148 if( !newcamd_connect() ) return (-1);
1149
1150 if( !chk_rsfilter(er, reader[ridx].ncd_disable_server_filt) ) return(-1);
1151
1152 memcpy(buf, er->ecm, er->l);
1153
1154 return((newcamd_send(buf, er->l, er->srvid)<1) ? (-1) : 0);
1155}
1156
1157static int newcamd_recv_chk(uchar *dcw, int *rc, uchar *buf, int n)
1158{
1159 ushort idx;
1160
1161 if( n<21 ) // no cw, ignore others
1162 return(-1);
1163 *rc = 1;
1164 idx = (buf[0] << 8) | buf[1];
1165 memcpy(dcw, buf+5, 16);
1166 return(idx);
1167}
1168
1169void module_newcamd(struct s_module *ph)
1170{
1171 strcpy(ph->desc, "newcamd");
1172 ph->type=MOD_CONN_TCP;
1173 ph->logtxt = ", crypted";
1174 ph->multi=1;
1175 ph->watchdog=1;
1176 ph->s_ip=cfg->ncd_srvip;
1177 ph->s_handler=newcamd_server;
1178 ph->recv=newcamd_recv;
1179 ph->send_dcw=newcamd_send_dcw;
1180 ph->ptab=&cfg->ncd_ptab;
1181 if( ph->ptab->nports==0 )
1182 ph->ptab->nports=1; // show disabled in log
1183 ph->c_multi=1;
1184 ph->c_init=newcamd_client_init;
1185 ph->c_recv_chk=newcamd_recv_chk;
1186 ph->c_send_ecm=newcamd_send_ecm;
1187
1188}
Note: See TracBrowser for help on using the repository browser.