1 | #include "globals.h"
|
---|
2 | #if defined MODULE_CAMD35 || defined MODULE_CAMD35_TCP
|
---|
3 |
|
---|
4 | #include "cscrypt/md5.h"
|
---|
5 | #include "module-cacheex.h"
|
---|
6 | #include "oscam-aes.h"
|
---|
7 | #include "oscam-chk.h"
|
---|
8 | #include "oscam-cache.h"
|
---|
9 | #include "oscam-client.h"
|
---|
10 | #include "oscam-ecm.h"
|
---|
11 | #include "oscam-emm.h"
|
---|
12 | #include "oscam-net.h"
|
---|
13 | #include "oscam-string.h"
|
---|
14 | #include "oscam-reader.h"
|
---|
15 |
|
---|
16 | //CMD00 - ECM (request)
|
---|
17 | //CMD01 - ECM (response)
|
---|
18 | //CMD02 - EMM (in clientmode - set EMM, in server mode - EMM data) - obsolete
|
---|
19 | //CMD03 - ECM (cascading request)
|
---|
20 | //CMD04 - ECM (cascading response)
|
---|
21 | //CMD05 - EMM (emm request) send cardata/cardinfo to client
|
---|
22 | //CMD06 - EMM (incomming EMM in server mode)
|
---|
23 | //CMD19 - EMM (incomming EMM in server mode) only seen with caid 0x1830
|
---|
24 | //CMD08 - Stop sending requests to the server for current srvid,prvid,caid
|
---|
25 | //CMD44 - MPCS/OScam internal error notification
|
---|
26 | //CMD55 - connect_on_init/keepalive
|
---|
27 |
|
---|
28 | //CMD0x3d - CACHEEX Cache-push id request
|
---|
29 | //CMD0x3e - CACHEEX Cache-push id answer
|
---|
30 | //CMD0x3f - CACHEEX cache-push
|
---|
31 |
|
---|
32 | //used variable ncd_skey for storing remote node id: ncd_skey[0..7] : 8
|
---|
33 | //bytes node id ncd_skey[8] : 1=valid node id received
|
---|
34 |
|
---|
35 | #define REQ_SIZE 584 // 512 + 20 + 0x34
|
---|
36 |
|
---|
37 | static int32_t __camd35_send(struct s_client *cl, uchar *buf, int32_t buflen, int answer_awaited)
|
---|
38 | {
|
---|
39 | int32_t l;
|
---|
40 | unsigned char rbuf[REQ_SIZE + 15 + 4], *sbuf = rbuf + 4;
|
---|
41 |
|
---|
42 | if(!cl->udp_fd || !cl->crypted) { return (-1); } //exit if no fd or aes key not set!
|
---|
43 |
|
---|
44 | //Fix ECM len > 255
|
---|
45 | if(buflen <= 0)
|
---|
46 | { buflen = ((buf[0] == 0) ? (((buf[21] & 0x0f) << 8) | buf[22]) + 3 : buf[1]); }
|
---|
47 | l = 20 + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0) + buflen;
|
---|
48 | memcpy(rbuf, cl->ucrc, 4);
|
---|
49 | memcpy(sbuf, buf, l);
|
---|
50 | memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's
|
---|
51 | i2b_buf(4, crc32(0L, sbuf + 20, buflen), sbuf + 4);
|
---|
52 | l = boundary(4, l);
|
---|
53 | cs_ddump_mask(cl->typ == 'c' ? D_CLIENT : D_READER, sbuf, l, "send %d bytes to %s", l, username(cl));
|
---|
54 | aes_encrypt_idx(&cl->aes_keys, sbuf, l);
|
---|
55 |
|
---|
56 | int32_t status;
|
---|
57 | if(cl->is_udp)
|
---|
58 | {
|
---|
59 | status = sendto(cl->udp_fd, rbuf, l + 4, 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len);
|
---|
60 | if(status == -1) { set_null_ip(&SIN_GET_ADDR(cl->udp_sa)); }
|
---|
61 | }
|
---|
62 | else
|
---|
63 | {
|
---|
64 | status = send(cl->udp_fd, rbuf, l + 4, 0);
|
---|
65 |
|
---|
66 | if(cl->typ == 'p' && cl->reader)
|
---|
67 | {
|
---|
68 | if(status == -1) { network_tcp_connection_close(cl->reader, "can't send"); }
|
---|
69 | }
|
---|
70 | else if(cl->typ == 'c')
|
---|
71 | {
|
---|
72 | if(status == -1) { cs_disconnect_client(cl); }
|
---|
73 | }
|
---|
74 | }
|
---|
75 | if(status != -1)
|
---|
76 | {
|
---|
77 | if(cl->reader && answer_awaited)
|
---|
78 | {
|
---|
79 | cl->reader->last_s = time(NULL);
|
---|
80 | }
|
---|
81 | if(cl->reader && !answer_awaited)
|
---|
82 | {
|
---|
83 | cl->reader->last_s = cl->reader->last_g = time(NULL);
|
---|
84 | }
|
---|
85 | cl->last = time(NULL);
|
---|
86 |
|
---|
87 | }
|
---|
88 | return status;
|
---|
89 | }
|
---|
90 |
|
---|
91 | static int32_t camd35_send(struct s_client *cl, uchar *buf, int32_t buflen)
|
---|
92 | {
|
---|
93 | // send command and set sending time because we await response
|
---|
94 | return __camd35_send(cl, buf, buflen, 1);
|
---|
95 | }
|
---|
96 |
|
---|
97 | static int32_t camd35_send_without_timeout(struct s_client *cl, uchar *buf, int32_t buflen)
|
---|
98 | {
|
---|
99 | // send command and do NOT set sending time because we DON'T await response
|
---|
100 | return __camd35_send(cl, buf, buflen, 0);
|
---|
101 | }
|
---|
102 |
|
---|
103 | static int32_t camd35_auth_client(struct s_client *cl, uchar *ucrc)
|
---|
104 | {
|
---|
105 | int32_t rc = 1;
|
---|
106 | uint32_t crc;
|
---|
107 | struct s_auth *account;
|
---|
108 | unsigned char md5tmp[MD5_DIGEST_LENGTH];
|
---|
109 |
|
---|
110 | if(cl->upwd[0])
|
---|
111 | { return (memcmp(cl->ucrc, ucrc, 4) ? 1 : 0); }
|
---|
112 | cl->crypted = 1;
|
---|
113 | crc = (((ucrc[0] << 24) | (ucrc[1] << 16) | (ucrc[2] << 8) | ucrc[3]) & 0xffffffffL);
|
---|
114 | for(account = cfg.account; (account) && (!cl->upwd[0]); account = account->next)
|
---|
115 | if(crc == crc32(0L, MD5((unsigned char *)account->usr, strlen(account->usr), md5tmp), MD5_DIGEST_LENGTH))
|
---|
116 | {
|
---|
117 | rc = cs_auth_client(cl, account, NULL);
|
---|
118 | if(!rc)
|
---|
119 | {
|
---|
120 | memcpy(cl->ucrc, ucrc, 4);
|
---|
121 | cs_strncpy((char *)cl->upwd, account->pwd, sizeof(cl->upwd));
|
---|
122 | aes_set_key(&cl->aes_keys, (char *) MD5(cl->upwd, strlen((char *)cl->upwd), md5tmp));
|
---|
123 | return 0;
|
---|
124 | }
|
---|
125 | }
|
---|
126 | return (rc);
|
---|
127 | }
|
---|
128 |
|
---|
129 | static int32_t camd35_recv(struct s_client *client, uchar *buf, int32_t l)
|
---|
130 | {
|
---|
131 | int32_t rc, s, rs, n = 0, buflen = 0, len = 0;
|
---|
132 | for(rc = rs = s = 0; !rc; s++)
|
---|
133 | {
|
---|
134 | switch(s)
|
---|
135 | {
|
---|
136 | case 0:
|
---|
137 | if(!client->udp_fd) { return (-9); }
|
---|
138 | if(client->is_udp && client->typ == 'c')
|
---|
139 | {
|
---|
140 | rs = recv_from_udpipe(buf);
|
---|
141 | }
|
---|
142 | else
|
---|
143 | {
|
---|
144 | //read minimum packet size (4 byte ucrc + 32 byte data) to detect packet size (tcp only)
|
---|
145 |
|
---|
146 | //rs = recv(client->udp_fd, buf, client->is_udp ? l : 36, 0);
|
---|
147 | if(client->is_udp){
|
---|
148 | while (1){
|
---|
149 | rs = recv(client->udp_fd, buf, l, 0);
|
---|
150 | if (rs < 0){
|
---|
151 | if(errno == EINTR) { continue; } // try again in case of interrupt
|
---|
152 | if(errno == EAGAIN) { continue; } //EAGAIN needs select procedure again
|
---|
153 | cs_debug_mask(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
|
---|
154 | break;
|
---|
155 | }else {break;}
|
---|
156 | }
|
---|
157 | }else{
|
---|
158 | int32_t tot=36, readed=0;
|
---|
159 | rs = 0;
|
---|
160 | do
|
---|
161 | {
|
---|
162 | readed = recv(client->udp_fd, buf+rs, tot, 0);
|
---|
163 | if (readed < 0){
|
---|
164 | if(errno == EINTR) { continue; } // try again in case of interrupt
|
---|
165 | if(errno == EAGAIN) { continue; } //EAGAIN needs select procedure again
|
---|
166 | cs_debug_mask(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
|
---|
167 | break;
|
---|
168 | }
|
---|
169 | if (readed == 0){ // nothing to read left!
|
---|
170 | break;
|
---|
171 | }
|
---|
172 | if (readed > 0){ // received something, add it!
|
---|
173 | tot-=readed;
|
---|
174 | rs+=readed;
|
---|
175 | }
|
---|
176 | }
|
---|
177 | while(tot!=0);
|
---|
178 | }
|
---|
179 |
|
---|
180 | }
|
---|
181 | if(rs < 36)
|
---|
182 | {
|
---|
183 | rc = -1;
|
---|
184 | goto out;
|
---|
185 | }
|
---|
186 | break;
|
---|
187 | case 1:
|
---|
188 | switch(camd35_auth_client(client, buf))
|
---|
189 | {
|
---|
190 | case 0:
|
---|
191 | break; // ok
|
---|
192 | case 1:
|
---|
193 | rc = -2;
|
---|
194 | break; // unknown user
|
---|
195 | default:
|
---|
196 | rc = -9;
|
---|
197 | break; // error's from cs_auth()
|
---|
198 | }
|
---|
199 | memmove(buf, buf + 4, rs -= 4);
|
---|
200 | break;
|
---|
201 | case 2:
|
---|
202 | aes_decrypt(&client->aes_keys, buf, rs);
|
---|
203 | if(rs != boundary(4, rs))
|
---|
204 | cs_debug_mask(client->typ == 'c' ? D_CLIENT : D_READER,
|
---|
205 | "WARNING: packet size has wrong decryption boundary");
|
---|
206 |
|
---|
207 | n = (buf[0] == 3) ? 0x34 : 0;
|
---|
208 |
|
---|
209 | //Fix for ECM request size > 255 (use ecm length field)
|
---|
210 | if(buf[0] == 0)
|
---|
211 | { buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; }
|
---|
212 | else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f) //cacheex-push
|
---|
213 | { buflen = buf[1] | (buf[2] << 8); }
|
---|
214 | else
|
---|
215 | { buflen = buf[1]; }
|
---|
216 |
|
---|
217 | n = boundary(4, n + 20 + buflen);
|
---|
218 | if(!(client->is_udp && client->typ == 'c') && (rs < n) && ((n - 32) > 0))
|
---|
219 | {
|
---|
220 |
|
---|
221 | //len = recv(client->udp_fd, buf+32, n-32, 0); // read the rest of the packet
|
---|
222 | int32_t tot=n-32, readed=0;
|
---|
223 | len = 0;
|
---|
224 | do{
|
---|
225 | readed = recv(client->udp_fd, buf+32+len, tot, 0); // read the rest of the packet
|
---|
226 | if (readed < 0){
|
---|
227 | if(errno == EINTR) { continue; } // try again in case of interrupt
|
---|
228 | if(errno == EAGAIN) { continue; } //EAGAIN needs select procedure again
|
---|
229 | cs_debug_mask(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
|
---|
230 | break;
|
---|
231 | }
|
---|
232 | if (readed == 0){ // nothing to read left!
|
---|
233 | break;
|
---|
234 | }
|
---|
235 | if (readed > 0){ // received something, add it!
|
---|
236 | tot-=readed;
|
---|
237 | len+=readed;
|
---|
238 | }
|
---|
239 | }
|
---|
240 | while(tot!=0);
|
---|
241 |
|
---|
242 |
|
---|
243 | if(len > 0)
|
---|
244 | {
|
---|
245 | rs += len;
|
---|
246 | aes_decrypt(&client->aes_keys, buf + 32, len);
|
---|
247 | }
|
---|
248 | if(len < 0)
|
---|
249 | {
|
---|
250 | rc = -1;
|
---|
251 | goto out;
|
---|
252 | }
|
---|
253 | }
|
---|
254 |
|
---|
255 | cs_ddump_mask(client->typ == 'c' ? D_CLIENT : D_READER,
|
---|
256 | buf, rs, "received %d bytes from %s", rs, remote_txt());
|
---|
257 |
|
---|
258 | if(n < rs)
|
---|
259 | cs_debug_mask(client->typ == 'c' ? D_CLIENT : D_READER,
|
---|
260 | "ignoring %d bytes of garbage", rs - n);
|
---|
261 | else if(n > rs) { rc = -3; }
|
---|
262 | break;
|
---|
263 | case 3:
|
---|
264 | if(crc32(0L, buf + 20, buflen) != b2i(4, buf + 4)) { rc = -4; }
|
---|
265 | if(!rc) { rc = n; }
|
---|
266 | break;
|
---|
267 | }
|
---|
268 | }
|
---|
269 |
|
---|
270 | out:
|
---|
271 | if((rs > 0) && ((rc == -1) || (rc == -2)))
|
---|
272 | {
|
---|
273 | cs_ddump_mask(client->typ == 'c' ? D_CLIENT : D_READER, buf, rs,
|
---|
274 | "received %d bytes from %s (native)", rs, remote_txt());
|
---|
275 | }
|
---|
276 | if(rc >= 0) { client->last = time(NULL); } // last client action is now
|
---|
277 | switch(rc)
|
---|
278 | {
|
---|
279 | //case 0: break;
|
---|
280 | case -1:
|
---|
281 | cs_log("packet is too small (received %d bytes, expected %d bytes)", rs, l);
|
---|
282 | break;
|
---|
283 | case -2:
|
---|
284 | if(cs_auth_client(client, 0, "unknown user"))
|
---|
285 | { cs_disconnect_client(client); }
|
---|
286 | break;
|
---|
287 | case -3:
|
---|
288 | cs_log("incomplete request !");
|
---|
289 | break;
|
---|
290 | case -4:
|
---|
291 | cs_log("checksum error (wrong password ?)");
|
---|
292 | break;
|
---|
293 | //default: cs_debug_mask(D_TRACE, "camd35_recv returns rc=%d", rc); break;
|
---|
294 | }
|
---|
295 |
|
---|
296 | return (rc);
|
---|
297 | }
|
---|
298 |
|
---|
299 | /*
|
---|
300 | * server functions
|
---|
301 | */
|
---|
302 |
|
---|
303 | static void camd35_request_emm(ECM_REQUEST *er)
|
---|
304 | {
|
---|
305 | int32_t i;
|
---|
306 | time_t now;
|
---|
307 | uchar mbuf[1024];
|
---|
308 | struct s_client *cl = cur_client();
|
---|
309 | struct s_reader *aureader = NULL, *rdr = NULL;
|
---|
310 |
|
---|
311 | if(er->selected_reader && !er->selected_reader->audisabled && ll_contains(cl->aureader_list, er->selected_reader))
|
---|
312 | { aureader = er->selected_reader; }
|
---|
313 |
|
---|
314 | if(!aureader && cl->aureader_list)
|
---|
315 | {
|
---|
316 | LL_ITER itr = ll_iter_create(cl->aureader_list);
|
---|
317 | while((rdr = ll_iter_next(&itr)))
|
---|
318 | {
|
---|
319 | if(emm_reader_match(rdr, er->caid, er->prid))
|
---|
320 | {
|
---|
321 | aureader = rdr;
|
---|
322 | break;
|
---|
323 | }
|
---|
324 | }
|
---|
325 | }
|
---|
326 |
|
---|
327 | if(!aureader)
|
---|
328 | { return; } // TODO
|
---|
329 |
|
---|
330 | uint16_t au_caid = aureader->caid;
|
---|
331 |
|
---|
332 | // Bulcrypt has 2 caids and aureader->caid can't be used.
|
---|
333 | // Use 5581 for AU.
|
---|
334 | if(!au_caid && (er->caid == 0x5581 || er->caid == 0x4aee))
|
---|
335 | { au_caid = 0x5581; }
|
---|
336 |
|
---|
337 | time(&now);
|
---|
338 | if(!memcmp(cl->lastserial, aureader->hexserial, 8))
|
---|
339 | if(abs(now - cl->last) < 180) { return; }
|
---|
340 |
|
---|
341 | memcpy(cl->lastserial, aureader->hexserial, 8);
|
---|
342 | cl->last = now;
|
---|
343 |
|
---|
344 | if(au_caid)
|
---|
345 | {
|
---|
346 | cl->disable_counter = 0;
|
---|
347 | cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)",
|
---|
348 | username(cur_client()), aureader->label, aureader->caid,
|
---|
349 | aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0]));
|
---|
350 | }
|
---|
351 | else if(cl->disable_counter > 2)
|
---|
352 | { return; }
|
---|
353 | else
|
---|
354 | { cl->disable_counter++; }
|
---|
355 |
|
---|
356 | memset(mbuf, 0, sizeof(mbuf));
|
---|
357 | mbuf[2] = mbuf[3] = 0xff; // must not be zero
|
---|
358 | i2b_buf(2, er->srvid, mbuf + 8);
|
---|
359 |
|
---|
360 | //override request provid with auprovid if set in CMD05
|
---|
361 | if(aureader->auprovid)
|
---|
362 | {
|
---|
363 | if(aureader->auprovid != er->prid)
|
---|
364 | { i2b_buf(4, aureader->auprovid, mbuf + 12); }
|
---|
365 | else
|
---|
366 | { i2b_buf(4, er->prid, mbuf + 12); }
|
---|
367 | }
|
---|
368 | else
|
---|
369 | {
|
---|
370 | i2b_buf(4, er->prid, mbuf + 12);
|
---|
371 | }
|
---|
372 |
|
---|
373 | i2b_buf(2, er->pid, mbuf + 16);
|
---|
374 | mbuf[0] = 5;
|
---|
375 | mbuf[1] = 111;
|
---|
376 | if(au_caid)
|
---|
377 | {
|
---|
378 | mbuf[39] = 1; // no. caids
|
---|
379 | mbuf[20] = au_caid >> 8; // caid's (max 8)
|
---|
380 | mbuf[21] = au_caid & 0xff;
|
---|
381 | if(au_caid == 0x5581)
|
---|
382 | {
|
---|
383 | // Bulcrypt have two CAIDs, add the second one
|
---|
384 | mbuf[39]++;
|
---|
385 | mbuf[22] = 0x4aee >> 8;
|
---|
386 | mbuf[23] = 0x4aee & 0xff;
|
---|
387 | }
|
---|
388 | memcpy(mbuf + 40, aureader->hexserial, 6); // serial now 6 bytes
|
---|
389 | mbuf[47] = aureader->nprov;
|
---|
390 | for(i = 0; i < aureader->nprov; i++)
|
---|
391 | {
|
---|
392 | if((au_caid >= 0x1700 && au_caid <= 0x1799) || // Betacrypt
|
---|
393 | (au_caid >= 0x0600 && au_caid <= 0x0699)) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
|
---|
394 | {
|
---|
395 | mbuf[48 + (i * 5)] = aureader->prid[i][0];
|
---|
396 | memcpy(&mbuf[50 + (i * 5)], &aureader->prid[i][1], 3);
|
---|
397 | }
|
---|
398 | else
|
---|
399 | {
|
---|
400 | mbuf[48 + (i * 5)] = aureader->prid[i][2];
|
---|
401 | mbuf[49 + (i * 5)] = aureader->prid[i][3];
|
---|
402 | memcpy(&mbuf[50 + (i * 5)], &aureader->sa[i][0], 4); // for conax we need at least 4 Bytes
|
---|
403 | }
|
---|
404 | }
|
---|
405 | //we think client/server protocols should deliver all information, and only readers should discard EMM
|
---|
406 | mbuf[128] = (aureader->blockemm & EMM_GLOBAL && !(aureader->saveemm & EMM_GLOBAL)) ? 0 : 1;
|
---|
407 | mbuf[129] = (aureader->blockemm & EMM_SHARED && !(aureader->saveemm & EMM_SHARED)) ? 0 : 1;
|
---|
408 | mbuf[130] = (aureader->blockemm & EMM_UNIQUE && !(aureader->saveemm & EMM_UNIQUE)) ? 0 : 1;
|
---|
409 | //mbuf[131] = aureader->card_system; //Cardsystem for Oscam client
|
---|
410 | }
|
---|
411 | else // disable emm
|
---|
412 | { mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1; }
|
---|
413 |
|
---|
414 | memcpy(mbuf + 10, mbuf + 20, 2);
|
---|
415 | camd35_send(cl, mbuf, 0); // send with data-len 111 for camd3 > 3.890
|
---|
416 | mbuf[1]++;
|
---|
417 | camd35_send(cl, mbuf, 0); // send with data-len 112 for camd3 < 3.890
|
---|
418 | }
|
---|
419 |
|
---|
420 | static void camd35_send_dcw(struct s_client *client, ECM_REQUEST *er)
|
---|
421 | {
|
---|
422 | uchar *buf;
|
---|
423 | buf = er->src_data; // get orig request
|
---|
424 |
|
---|
425 | if(!buf)
|
---|
426 | {
|
---|
427 | cs_log("%s: src_data missing.",client->reader->ph.desc);
|
---|
428 | return;
|
---|
429 | }
|
---|
430 |
|
---|
431 | if(((er->rcEx > 0) || (er->rc == E_INVALID)) && !client->c35_suppresscmd08)
|
---|
432 | {
|
---|
433 | buf[0] = 0x08;
|
---|
434 | buf[1] = 2;
|
---|
435 | memset(buf + 20, 0, buf[1]);
|
---|
436 | buf[22] = er->rc; //put rc in byte 22 - hopefully don't break legacy camd3
|
---|
437 | }
|
---|
438 | else if(er->rc == E_STOPPED)
|
---|
439 | {
|
---|
440 | buf[0] = 0x08;
|
---|
441 | buf[1] = 2;
|
---|
442 | buf[20] = 0;
|
---|
443 | /*
|
---|
444 | * the second Databyte should be forseen for a sleeptime in minutes
|
---|
445 | * whoever knows the camd3 protocol related to CMD08 - please help!
|
---|
446 | * on tests this don't work with native camd3
|
---|
447 | */
|
---|
448 | buf[21] = client->c35_sleepsend;
|
---|
449 | cs_log("%s stop request send", client->account->usr);
|
---|
450 | }
|
---|
451 | else
|
---|
452 | {
|
---|
453 | // Send CW
|
---|
454 | if((er->rc < E_NOTFOUND) || (er->rc == E_FAKE))
|
---|
455 | {
|
---|
456 | if(buf[0] == 3)
|
---|
457 | { memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); }
|
---|
458 | buf[0]++;
|
---|
459 | buf[1] = 16;
|
---|
460 | #ifdef CS_CACHEEX
|
---|
461 | if(((client->typ == 'c' && client->account && client->account->cacheex.mode)
|
---|
462 | || ((client->typ == 'p' || client->typ == 'r') && (client->reader && client->reader->cacheex.mode)))
|
---|
463 | && er->cwc_cycletime && er->cwc_next_cw_cycle < 2) // ce1
|
---|
464 | {
|
---|
465 | buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime
|
---|
466 | if(er->cwc_next_cw_cycle == 1)
|
---|
467 | { buf[18] = (buf[18] | 0x80); } // set bit 8 to high
|
---|
468 |
|
---|
469 | if(client->typ == 'c' && client->account && client->account->cacheex.mode)
|
---|
470 | { client->account->cwc_info++; }
|
---|
471 | else if((client->typ == 'p' || client->typ == 'r') && (client->reader && client->reader->cacheex.mode))
|
---|
472 | { client->cwc_info++; }
|
---|
473 | cs_debug_mask(D_CWC, "CWC (CE1) push to %s (camd3) cycletime: %isek - nextcwcycle: CW%i for %04X:%06X:%04X", username(client), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
|
---|
474 | buf[19] = er->ecm[0];
|
---|
475 | }
|
---|
476 | #endif
|
---|
477 | memcpy(buf + 20, er->cw, buf[1]);
|
---|
478 | }
|
---|
479 | else
|
---|
480 | {
|
---|
481 | // Send old CMD44 to prevent cascading problems with older mpcs/oscam versions
|
---|
482 | buf[0] = 0x44;
|
---|
483 | buf[1] = 0;
|
---|
484 | }
|
---|
485 | }
|
---|
486 | camd35_send(client, buf, 0);
|
---|
487 | camd35_request_emm(er);
|
---|
488 | }
|
---|
489 |
|
---|
490 | static void camd35_process_ecm(uchar *buf, int buflen)
|
---|
491 | {
|
---|
492 | ECM_REQUEST *er;
|
---|
493 | if(!buf || buflen < 23)
|
---|
494 | { return; }
|
---|
495 | uint16_t ecmlen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3;
|
---|
496 | if(ecmlen + 20 > buflen)
|
---|
497 | { return; }
|
---|
498 | if(!(er = get_ecmtask()))
|
---|
499 | { return; }
|
---|
500 | // er->l = buf[1];
|
---|
501 | //fix ECM LEN issue
|
---|
502 | er->ecmlen = ecmlen;
|
---|
503 | if(!cs_malloc(&er->src_data, 0x34 + 20 + er->ecmlen))
|
---|
504 | { return; }
|
---|
505 | memcpy(er->src_data, buf, 0x34 + 20 + er->ecmlen); // save request
|
---|
506 | er->srvid = b2i(2, buf + 8);
|
---|
507 | er->caid = b2i(2, buf + 10);
|
---|
508 | er->prid = b2i(4, buf + 12);
|
---|
509 | //er->pid = b2i(2, buf+16); value is ecmtask idx see camd35_recv_chk 941
|
---|
510 | memcpy(er->ecm, buf + 20, er->ecmlen);
|
---|
511 | get_cw(cur_client(), er);
|
---|
512 | }
|
---|
513 |
|
---|
514 | static void camd35_process_emm(uchar *buf, int buflen, int emmlen)
|
---|
515 | {
|
---|
516 | EMM_PACKET epg;
|
---|
517 | if(!buf || buflen < 20 || emmlen + 20 > buflen)
|
---|
518 | { return; }
|
---|
519 | memset(&epg, 0, sizeof(epg));
|
---|
520 | epg.emmlen = emmlen;
|
---|
521 | memcpy(epg.caid, buf + 10, 2);
|
---|
522 | memcpy(epg.provid, buf + 12 , 4);
|
---|
523 | memcpy(epg.emm, buf + 20, epg.emmlen);
|
---|
524 | do_emm(cur_client(), &epg);
|
---|
525 | }
|
---|
526 |
|
---|
527 | static int32_t tcp_connect(struct s_client *cl)
|
---|
528 | {
|
---|
529 | if(cl->is_udp) // check for udp client
|
---|
530 | {
|
---|
531 | if(!IP_ISSET(SIN_GET_ADDR(cl->udp_sa))) // check ip is set
|
---|
532 | {
|
---|
533 | if(!(hostResolve(cl->reader))) // no ip -> try to resolve ip of client
|
---|
534 | {
|
---|
535 | network_tcp_connection_close(cl->reader, "no ip");
|
---|
536 | return 0;
|
---|
537 | }
|
---|
538 | }
|
---|
539 | }
|
---|
540 |
|
---|
541 | if(!cl->reader->tcp_connected) // client not connected
|
---|
542 | {
|
---|
543 | int32_t handle = 0;
|
---|
544 | handle = network_tcp_connection_open(cl->reader); // try to connect
|
---|
545 | if(handle < 0) // got no handle -> error!
|
---|
546 | {
|
---|
547 | cl->reader->last_s = 0; // set last send to zero
|
---|
548 | cl->reader->last_g = 0; // set last receive to zero
|
---|
549 | cl->last = 0; // set last client action to zero
|
---|
550 | return (0);
|
---|
551 | }
|
---|
552 |
|
---|
553 | cl->reader->tcp_connected = 1;
|
---|
554 | cl->reader->card_status = CARD_INSERTED;
|
---|
555 | cl->reader->last_s = time(NULL); // reset last send
|
---|
556 | cl->reader->last_g = time(NULL); // reset last receive
|
---|
557 | cl->last = time(NULL); // reset last client action
|
---|
558 | cl->pfd = cl->udp_fd = handle;
|
---|
559 | }
|
---|
560 | if(!cl->udp_fd) { return (0); } // Check if client has no handle -> error
|
---|
561 | if(cl->reader->tcp_rto && (cl->reader->last_s - cl->reader->last_g > cl->reader->tcp_rto)) // check if client reached timeout, if so disconnect client
|
---|
562 | {
|
---|
563 | network_tcp_connection_close(cl->reader, "rto");
|
---|
564 | return 0;
|
---|
565 | }
|
---|
566 |
|
---|
567 | return (1); // all ok
|
---|
568 | }
|
---|
569 |
|
---|
570 |
|
---|
571 | #ifdef CS_CACHEEX
|
---|
572 | uint8_t camd35_node_id[8];
|
---|
573 |
|
---|
574 | /**
|
---|
575 | * send own id
|
---|
576 | */
|
---|
577 | void camd35_cache_push_send_own_id(struct s_client *cl, uint8_t *mbuf)
|
---|
578 | {
|
---|
579 | uint8_t rbuf[32]; //minimal size
|
---|
580 |
|
---|
581 | if(!cl->crypted) { return; }
|
---|
582 |
|
---|
583 | cs_debug_mask(D_CACHEEX, "cacheex: received id request from node %" PRIu64 "X %s", cacheex_node_id(mbuf + 20), username(cl));
|
---|
584 |
|
---|
585 | memset(rbuf, 0, sizeof(rbuf));
|
---|
586 | rbuf[0] = 0x3e;
|
---|
587 | rbuf[1] = 12;
|
---|
588 | rbuf[2] = 0;
|
---|
589 | memcpy(rbuf + 20, camd35_node_id, 8);
|
---|
590 | cs_debug_mask(D_CACHEEX, "cacheex: sending own id %" PRIu64 "X request %s", cacheex_node_id(camd35_node_id), username(cl));
|
---|
591 | camd35_send(cl, rbuf, 12); //send adds +20
|
---|
592 | }
|
---|
593 |
|
---|
594 | /**
|
---|
595 | * request remote id
|
---|
596 | */
|
---|
597 | void camd35_cache_push_request_remote_id(struct s_client *cl)
|
---|
598 | {
|
---|
599 | uint8_t rbuf[32];//minimal size
|
---|
600 |
|
---|
601 | memset(rbuf, 0, sizeof(rbuf));
|
---|
602 | rbuf[0] = 0x3d;
|
---|
603 | rbuf[1] = 12;
|
---|
604 | rbuf[2] = 0;
|
---|
605 | memcpy(rbuf + 20, camd35_node_id, 8);
|
---|
606 | cs_debug_mask(D_CACHEEX, "cacheex: sending id request to %s", username(cl));
|
---|
607 | camd35_send(cl, rbuf, 12); //send adds +20
|
---|
608 | }
|
---|
609 |
|
---|
610 | /**
|
---|
611 | * store received remote id
|
---|
612 | */
|
---|
613 | void camd35_cache_push_receive_remote_id(struct s_client *cl, uint8_t *buf)
|
---|
614 | {
|
---|
615 |
|
---|
616 | memcpy(cl->ncd_skey, buf + 20, 8);
|
---|
617 | cl->ncd_skey[8] = 1;
|
---|
618 | cs_debug_mask(D_CACHEEX, "cacheex: received id answer from %s: %" PRIu64 "X", username(cl), cacheex_node_id(cl->ncd_skey));
|
---|
619 | }
|
---|
620 |
|
---|
621 |
|
---|
622 | int32_t camd35_cache_push_chk(struct s_client *cl, ECM_REQUEST *er)
|
---|
623 | {
|
---|
624 | if(ll_count(er->csp_lastnodes) >= cacheex_maxhop(cl)) //check max 10 nodes to push:
|
---|
625 | {
|
---|
626 | cs_debug_mask(D_CACHEEX, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl));
|
---|
627 | return 0;
|
---|
628 | }
|
---|
629 |
|
---|
630 | if(cl->reader)
|
---|
631 | {
|
---|
632 | if(!cl->reader->tcp_connected)
|
---|
633 | {
|
---|
634 | cs_debug_mask(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
|
---|
635 | return 0;
|
---|
636 | }
|
---|
637 | }
|
---|
638 |
|
---|
639 | //if(chk_is_null_nodeid(remote_node,8)){
|
---|
640 | if(!cl->ncd_skey[8])
|
---|
641 | {
|
---|
642 | cs_debug_mask(D_CACHEEX, "cacheex: NO peer_node_id got yet, skip!");
|
---|
643 | return 0;
|
---|
644 | }
|
---|
645 |
|
---|
646 | uint8_t *remote_node = cl->ncd_skey; //it is sended by reader(mode 2) or client (mode 3) each 30s using keepalive msgs
|
---|
647 |
|
---|
648 | //search existing peer nodes:
|
---|
649 | LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
|
---|
650 | uint8_t *node;
|
---|
651 | while((node = ll_li_next(li)))
|
---|
652 | {
|
---|
653 | cs_debug_mask(D_CACHEEX, "cacheex: check node %" PRIu64 "X == %" PRIu64 "X ?", cacheex_node_id(node), cacheex_node_id(remote_node));
|
---|
654 | if(memcmp(node, remote_node, 8) == 0)
|
---|
655 | {
|
---|
656 | break;
|
---|
657 | }
|
---|
658 | }
|
---|
659 | ll_li_destroy(li);
|
---|
660 |
|
---|
661 | //node found, so we got it from there, do not push:
|
---|
662 | if(node)
|
---|
663 | {
|
---|
664 | cs_debug_mask(D_CACHEEX,
|
---|
665 | "cacheex: node %" PRIu64 "X found in list => skip push!", cacheex_node_id(node));
|
---|
666 | return 0;
|
---|
667 | }
|
---|
668 |
|
---|
669 | //check if cw is already pushed
|
---|
670 | if(check_is_pushed(er->cw_cache, cl))
|
---|
671 | { return 0; }
|
---|
672 |
|
---|
673 | cs_debug_mask(D_CACHEEX, "cacheex: push ok %" PRIu64 "X to %" PRIu64 "X %s", cacheex_node_id(camd35_node_id), cacheex_node_id(remote_node), username(cl));
|
---|
674 |
|
---|
675 | return 1;
|
---|
676 | }
|
---|
677 | int32_t camd35_cache_push_out(struct s_client *cl, struct ecm_request_t *er)
|
---|
678 | {
|
---|
679 | int8_t rc = (er->rc < E_NOTFOUND) ? E_FOUND : er->rc;
|
---|
680 | if(rc != E_FOUND && rc != E_UNHANDLED) { return -1; } //Maybe later we could support other rcs
|
---|
681 |
|
---|
682 | //E_FOUND : we have the CW,
|
---|
683 | //E_UNHANDLED : incoming ECM request
|
---|
684 |
|
---|
685 | if(cl->reader)
|
---|
686 | {
|
---|
687 | if(!tcp_connect(cl))
|
---|
688 | {
|
---|
689 | cs_debug_mask(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
|
---|
690 | return (-1);
|
---|
691 | }
|
---|
692 | }
|
---|
693 |
|
---|
694 | uint32_t size = sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw) + sizeof(uint8_t) +
|
---|
695 | (ll_count(er->csp_lastnodes) + 1) * 8;
|
---|
696 | unsigned char *buf;
|
---|
697 | if(!cs_malloc(&buf, size + 20)) //camd35_send() adds +20
|
---|
698 | { return -1; }
|
---|
699 |
|
---|
700 | buf[0] = 0x3f; //New Command: Cache-push
|
---|
701 | buf[1] = size & 0xff;
|
---|
702 | buf[2] = size >> 8;
|
---|
703 | buf[3] = rc;
|
---|
704 |
|
---|
705 | i2b_buf(2, er->srvid, buf + 8);
|
---|
706 | i2b_buf(2, er->caid, buf + 10);
|
---|
707 | i2b_buf(4, er->prid, buf + 12);
|
---|
708 | //i2b_buf(2, er->idx, buf + 16); // Not relevant...?
|
---|
709 |
|
---|
710 | #ifdef CS_CACHEEX
|
---|
711 | if(er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
|
---|
712 | {
|
---|
713 | buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime
|
---|
714 | if(er->cwc_next_cw_cycle == 1)
|
---|
715 | { buf[18] = (buf[18] | 0x80); } // set bit 8 to high
|
---|
716 |
|
---|
717 | if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
|
---|
718 | { cl->account->cwc_info++; }
|
---|
719 | else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
|
---|
720 | { cl->cwc_info++; }
|
---|
721 | #endif
|
---|
722 | cs_debug_mask(D_CWC, "CWC (CE) push to %s (camd3) cycletime: %isek - nextcwcycle: CW%i for %04X:%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
|
---|
723 | }
|
---|
724 |
|
---|
725 | buf[19] = er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0];
|
---|
726 |
|
---|
727 | uint8_t *ofs = buf + 20;
|
---|
728 |
|
---|
729 | //write oscam ecmd5:
|
---|
730 | memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); //16
|
---|
731 | ofs += sizeof(er->ecmd5);
|
---|
732 |
|
---|
733 | //write csp hashcode:
|
---|
734 | i2b_buf(4, htonl(er->csp_hash), ofs);
|
---|
735 | ofs += 4;
|
---|
736 |
|
---|
737 | //write cw:
|
---|
738 | memcpy(ofs, er->cw, sizeof(er->cw)); //16
|
---|
739 | ofs += sizeof(er->cw);
|
---|
740 |
|
---|
741 | //write node count:
|
---|
742 | *ofs = ll_count(er->csp_lastnodes) + 1;
|
---|
743 | ofs++;
|
---|
744 |
|
---|
745 | //write own node:
|
---|
746 | memcpy(ofs, camd35_node_id, 8);
|
---|
747 | ofs += 8;
|
---|
748 |
|
---|
749 | //write other nodes:
|
---|
750 | LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
|
---|
751 | uint8_t *node;
|
---|
752 | while((node = ll_li_next(li)))
|
---|
753 | {
|
---|
754 | memcpy(ofs, node, 8);
|
---|
755 | ofs += 8;
|
---|
756 | }
|
---|
757 | ll_li_destroy(li);
|
---|
758 |
|
---|
759 | int32_t res = camd35_send(cl, buf, size);
|
---|
760 | NULLFREE(buf);
|
---|
761 | return res;
|
---|
762 | }
|
---|
763 |
|
---|
764 | void camd35_recv_ce1_cwc_info(struct s_client *cl, uchar *buf, int32_t idx)
|
---|
765 | {
|
---|
766 | ECM_REQUEST *er = NULL;
|
---|
767 | int32_t i;
|
---|
768 |
|
---|
769 | for(i = 0; i < cfg.max_pending; i++)
|
---|
770 | {
|
---|
771 | if (cl->ecmtask[i].idx == idx)
|
---|
772 | {
|
---|
773 | er = &cl->ecmtask[i];
|
---|
774 | break;
|
---|
775 | }
|
---|
776 | }
|
---|
777 |
|
---|
778 | if(!er)
|
---|
779 | { return; }
|
---|
780 |
|
---|
781 | int8_t rc = buf[3];
|
---|
782 | if(rc != E_FOUND)
|
---|
783 | { return; }
|
---|
784 |
|
---|
785 | if(buf[18])
|
---|
786 | {
|
---|
787 | if(buf[18] & (0x01 << 7))
|
---|
788 | {
|
---|
789 | er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
|
---|
790 | er->parent->cwc_cycletime = er->cwc_cycletime;
|
---|
791 | er->cwc_next_cw_cycle = 1;
|
---|
792 | er->parent->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
|
---|
793 | }
|
---|
794 | else
|
---|
795 | {
|
---|
796 | er->cwc_cycletime = buf[18];
|
---|
797 | er->parent->cwc_cycletime = er->cwc_cycletime;
|
---|
798 | er->cwc_next_cw_cycle = 0;
|
---|
799 | er->parent->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
|
---|
800 | }
|
---|
801 | }
|
---|
802 |
|
---|
803 | if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
|
---|
804 | { cl->account->cwc_info++; }
|
---|
805 | else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
|
---|
806 | { cl->cwc_info++; }
|
---|
807 |
|
---|
808 | cs_debug_mask(D_CWC, "CWC (CE1) received from %s (camd3) cycletime: %isek - nextcwcycle: CW%i for %04X:%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
|
---|
809 |
|
---|
810 | }
|
---|
811 |
|
---|
812 | void camd35_cache_push_in(struct s_client *cl, uchar *buf)
|
---|
813 | {
|
---|
814 | int8_t rc = buf[3];
|
---|
815 | if(rc != E_FOUND && rc != E_UNHANDLED) //Maybe later we could support other rcs
|
---|
816 | { return; }
|
---|
817 |
|
---|
818 | ECM_REQUEST *er;
|
---|
819 | uint16_t size = buf[1] | (buf[2] << 8);
|
---|
820 | if(size < sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))
|
---|
821 | {
|
---|
822 | cs_debug_mask(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl));
|
---|
823 | return;
|
---|
824 | }
|
---|
825 |
|
---|
826 | if(!(er = get_ecmtask()))
|
---|
827 | { return; }
|
---|
828 |
|
---|
829 | er->srvid = b2i(2, buf + 8);
|
---|
830 | er->caid = b2i(2, buf + 10);
|
---|
831 | er->prid = b2i(4, buf + 12);
|
---|
832 | er->pid = b2i(2, buf + 16);
|
---|
833 | er->ecm[0] = buf[19]!=0x80 && buf[19]!=0x81 ? 0 : buf[19]; //odd/even byte, usefull to send it over CSP and to check cw for swapping
|
---|
834 | er->rc = rc;
|
---|
835 |
|
---|
836 | er->ecmlen = 0;
|
---|
837 |
|
---|
838 | #ifdef CS_CACHEEX
|
---|
839 | if(buf[18])
|
---|
840 | {
|
---|
841 | if(buf[18] & (0x01 << 7))
|
---|
842 | {
|
---|
843 | er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
|
---|
844 | er->cwc_next_cw_cycle = 1;
|
---|
845 | }
|
---|
846 | else
|
---|
847 | {
|
---|
848 | er->cwc_cycletime = buf[18];
|
---|
849 | er->cwc_next_cw_cycle = 0;
|
---|
850 | }
|
---|
851 | }
|
---|
852 |
|
---|
853 | if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
|
---|
854 | {
|
---|
855 | if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
|
---|
856 | { cl->account->cwc_info++; }
|
---|
857 | else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
|
---|
858 | { cl->cwc_info++; }
|
---|
859 | cs_debug_mask(D_CWC, "CWC (CE) received from %s (camd3) cycletime: %isek - nextcwcycle: CW%i for %04X:%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
|
---|
860 | }
|
---|
861 | #endif
|
---|
862 |
|
---|
863 |
|
---|
864 | uint8_t *ofs = buf + 20;
|
---|
865 |
|
---|
866 | //Read ecmd5
|
---|
867 | memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16
|
---|
868 | ofs += sizeof(er->ecmd5);
|
---|
869 |
|
---|
870 | if(!check_cacheex_filter(cl, er))
|
---|
871 | { return; }
|
---|
872 |
|
---|
873 | //Read csp_hash:
|
---|
874 | er->csp_hash = ntohl(b2i(4, ofs));
|
---|
875 | ofs += 4;
|
---|
876 |
|
---|
877 | //Read cw:
|
---|
878 | memcpy(er->cw, ofs, sizeof(er->cw)); //16
|
---|
879 | ofs += sizeof(er->cw);
|
---|
880 |
|
---|
881 | //Check auf neues Format:
|
---|
882 | uint8_t *data;
|
---|
883 | if(size > (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)))
|
---|
884 | {
|
---|
885 |
|
---|
886 | //Read lastnodes:
|
---|
887 | uint8_t count = *ofs;
|
---|
888 | ofs++;
|
---|
889 |
|
---|
890 | //check max nodes:
|
---|
891 | if(count > cacheex_maxhop(cl))
|
---|
892 | {
|
---|
893 | cs_debug_mask(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl));
|
---|
894 | NULLFREE(er);
|
---|
895 | return;
|
---|
896 | }
|
---|
897 | cs_debug_mask(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
|
---|
898 | er->csp_lastnodes = ll_create("csp_lastnodes");
|
---|
899 | while(count)
|
---|
900 | {
|
---|
901 | if(!cs_malloc(&data, 8))
|
---|
902 | { break; }
|
---|
903 | memcpy(data, ofs, 8);
|
---|
904 | ofs += 8;
|
---|
905 | ll_append(er->csp_lastnodes, data);
|
---|
906 | count--;
|
---|
907 | cs_debug_mask(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
|
---|
908 | }
|
---|
909 | }
|
---|
910 | else
|
---|
911 | {
|
---|
912 | cs_debug_mask(D_CACHEEX, "cacheex: received old cachex from %s", username(cl));
|
---|
913 | er->csp_lastnodes = ll_create("csp_lastnodes");
|
---|
914 | }
|
---|
915 |
|
---|
916 | //store remote node id if we got one. The remote node is the first node in the node list
|
---|
917 | data = ll_has_elements(er->csp_lastnodes);
|
---|
918 | if(data && !cl->ncd_skey[8]) //Ok, this is tricky, we use newcamd key storage for saving the remote node
|
---|
919 | {
|
---|
920 | memcpy(cl->ncd_skey, data, 8);
|
---|
921 | cl->ncd_skey[8] = 1; //Mark as valid node
|
---|
922 | }
|
---|
923 | cs_debug_mask(D_CACHEEX, "cacheex: received cacheex from remote node id %" PRIu64 "X", cacheex_node_id(cl->ncd_skey));
|
---|
924 |
|
---|
925 | //for compatibility: add peer node if no node received (not working now, maybe later):
|
---|
926 | if(!ll_count(er->csp_lastnodes) && cl->ncd_skey[8])
|
---|
927 | {
|
---|
928 | if(!cs_malloc(&data, 8))
|
---|
929 | { return; }
|
---|
930 | memcpy(data, cl->ncd_skey, 8);
|
---|
931 | ll_append(er->csp_lastnodes, data);
|
---|
932 | cs_debug_mask(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
|
---|
933 | }
|
---|
934 |
|
---|
935 | // if (!ll_count(er->csp_lastnodes)) {
|
---|
936 | // if (!cs_malloc(&data, 8))
|
---|
937 | // break;
|
---|
938 | // memcpy(data, &cl->ip, 4);
|
---|
939 | // memcpy(data+4, &cl->port, 2);
|
---|
940 | // memcpy(data+6, &cl->is_udp, 1);
|
---|
941 | // ll_append(er->csp_lastnodes, data);
|
---|
942 | // cs_debug_mask(D_CACHEEX, "cacheex: added compat remote node id %" PRIu64 "X", cacheex_node_id(data));
|
---|
943 | // }
|
---|
944 |
|
---|
945 | cacheex_add_to_cache(cl, er);
|
---|
946 | }
|
---|
947 |
|
---|
948 | #endif
|
---|
949 |
|
---|
950 |
|
---|
951 | /*
|
---|
952 | * client functions
|
---|
953 | */
|
---|
954 | void send_keepalive(struct s_client *cl)
|
---|
955 | {
|
---|
956 |
|
---|
957 | if(cl->reader && cl->reader->keepalive)
|
---|
958 | {
|
---|
959 | if(tcp_connect(cl))
|
---|
960 | {
|
---|
961 | #ifdef CS_CACHEEX
|
---|
962 | if(cl->reader->cacheex.mode>1){
|
---|
963 | camd35_cache_push_request_remote_id(cl);
|
---|
964 | return;
|
---|
965 | }
|
---|
966 | #endif
|
---|
967 |
|
---|
968 | uint8_t rbuf[32];//minimal size
|
---|
969 | memset(rbuf, 0, sizeof(rbuf));
|
---|
970 | rbuf[0] = 55;
|
---|
971 | rbuf[1] = 1;
|
---|
972 | rbuf[2] = 0;
|
---|
973 | camd35_send(cl, rbuf, 1); //send adds +20
|
---|
974 | }
|
---|
975 | }
|
---|
976 | }
|
---|
977 |
|
---|
978 |
|
---|
979 | void send_keepalive_answer(struct s_client *cl)
|
---|
980 | {
|
---|
981 | if(check_client(cl) && cl->account)
|
---|
982 | {
|
---|
983 | uint8_t rbuf[32];//minimal size
|
---|
984 | memset(rbuf, 0, sizeof(rbuf));
|
---|
985 | rbuf[0] = 55;
|
---|
986 | rbuf[1] = 1;
|
---|
987 | rbuf[2] = 0;
|
---|
988 | camd35_send(cl, rbuf, 1); //send adds +20
|
---|
989 | }
|
---|
990 | }
|
---|
991 |
|
---|
992 |
|
---|
993 | int32_t camd35_client_init(struct s_client *cl)
|
---|
994 | {
|
---|
995 |
|
---|
996 | unsigned char md5tmp[MD5_DIGEST_LENGTH];
|
---|
997 | cs_strncpy((char *)cl->upwd, cl->reader->r_pwd, sizeof(cl->upwd));
|
---|
998 | i2b_buf(4, crc32(0L, MD5((unsigned char *)cl->reader->r_usr, strlen(cl->reader->r_usr), md5tmp), 16), cl->ucrc);
|
---|
999 | aes_set_key(&cl->aes_keys, (char *)MD5(cl->upwd, strlen((char *)cl->upwd), md5tmp));
|
---|
1000 | cl->crypted=1;
|
---|
1001 |
|
---|
1002 | cs_log("%s proxy %s:%d", cl->reader->ph.desc, cl->reader->device, cl->reader->r_port);
|
---|
1003 |
|
---|
1004 | send_keepalive(cl);
|
---|
1005 |
|
---|
1006 | return(0);
|
---|
1007 | }
|
---|
1008 |
|
---|
1009 |
|
---|
1010 | void camd35_idle(void)
|
---|
1011 | {
|
---|
1012 | struct s_client *cl = cur_client();
|
---|
1013 |
|
---|
1014 | if(!cl->reader)
|
---|
1015 | { return; }
|
---|
1016 |
|
---|
1017 | if(cl->reader->keepalive)
|
---|
1018 | {
|
---|
1019 | send_keepalive(cl);
|
---|
1020 | }
|
---|
1021 | else if(cl->reader->tcp_ito)
|
---|
1022 | {
|
---|
1023 | //inactivity timeout check
|
---|
1024 | time_t now;
|
---|
1025 | int32_t time_diff;
|
---|
1026 | time(&now);
|
---|
1027 | time_diff = abs(now - cl->reader->last_s);
|
---|
1028 | if(time_diff>(cl->reader->tcp_ito*60))
|
---|
1029 | {
|
---|
1030 | if(check_client(cl) && cl->reader->tcp_connected && cl->reader->ph.type==MOD_CONN_TCP)
|
---|
1031 | {
|
---|
1032 | cs_debug_mask(D_READER, "%s inactive_timeout, close connection (fd=%d)", cl->reader->ph.desc, cl->pfd);
|
---|
1033 | network_tcp_connection_close(cl->reader, "inactivity");
|
---|
1034 | }
|
---|
1035 | else
|
---|
1036 | { cl->reader->last_s = now; }
|
---|
1037 | }
|
---|
1038 | }
|
---|
1039 | }
|
---|
1040 |
|
---|
1041 |
|
---|
1042 | static void *camd35_server(struct s_client *client, uchar *mbuf, int32_t n)
|
---|
1043 | {
|
---|
1044 | if(!client || !mbuf)
|
---|
1045 | { return NULL; }
|
---|
1046 |
|
---|
1047 | if(client->reader)
|
---|
1048 | {
|
---|
1049 | client->reader->last_g = time(NULL); // last receive is now
|
---|
1050 | if(mbuf[0] == 6 || mbuf[0] == 19) // check for emm command
|
---|
1051 | {
|
---|
1052 | client->reader->last_s = time(NULL); // fixup: last send is now (if client is only sending emms connection would be dropped!)
|
---|
1053 | }
|
---|
1054 | cs_log("%s_SERVER last = %d, last_s = %d, last_g = %d", client->reader->ph.desc, (int) client->last, (int) client->reader->last_s, (int) client->reader->last_g);
|
---|
1055 | }
|
---|
1056 | client->last = time(NULL); // last client action is now
|
---|
1057 |
|
---|
1058 |
|
---|
1059 | switch(mbuf[0])
|
---|
1060 | {
|
---|
1061 | case 0: // ECM
|
---|
1062 | case 3: // ECM (cascading)
|
---|
1063 | camd35_process_ecm(mbuf, n);
|
---|
1064 | break;
|
---|
1065 | #ifdef CS_CACHEEX
|
---|
1066 | case 0x3d: // Cache-push id request
|
---|
1067 | camd35_cache_push_receive_remote_id(client, mbuf); //reader send request id with its nodeid, so we save it!
|
---|
1068 | camd35_cache_push_send_own_id(client, mbuf);
|
---|
1069 | break;
|
---|
1070 | case 0x3e: // Cache-push id answer
|
---|
1071 | camd35_cache_push_receive_remote_id(client, mbuf);
|
---|
1072 | break;
|
---|
1073 | case 0x3f: // Cache-push
|
---|
1074 | camd35_cache_push_in(client, mbuf);
|
---|
1075 | break;
|
---|
1076 | #endif
|
---|
1077 | case 6: // EMM
|
---|
1078 | case 19: // EMM
|
---|
1079 | if(n > 2)
|
---|
1080 | { camd35_process_emm(mbuf, n, mbuf[1]); }
|
---|
1081 | break;
|
---|
1082 | case 55:
|
---|
1083 | //keepalive msg
|
---|
1084 | send_keepalive_answer(client);
|
---|
1085 | break;
|
---|
1086 | default:
|
---|
1087 | cs_log("unknown [cs357x/cs378x] command from %s! (%d) n=%d", username(client), mbuf[0], n);
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | return NULL; //to prevent compiler message
|
---|
1091 | }
|
---|
1092 |
|
---|
1093 | static int32_t camd35_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
|
---|
1094 | {
|
---|
1095 | static const char *typtext[] = {"ok", "invalid", "sleeping"};
|
---|
1096 |
|
---|
1097 | if(client->stopped)
|
---|
1098 | {
|
---|
1099 | if(er->srvid == client->lastsrvid && er->caid == client->lastcaid && er->pid == client->lastpid)
|
---|
1100 | {
|
---|
1101 | cs_log("%s is stopped - requested by server (%s)",
|
---|
1102 | client->reader->label, typtext[client->stopped]);
|
---|
1103 | return (-1);
|
---|
1104 | }
|
---|
1105 | else
|
---|
1106 | {
|
---|
1107 | client->stopped = 0;
|
---|
1108 | }
|
---|
1109 | }
|
---|
1110 |
|
---|
1111 | client->lastsrvid = er->srvid;
|
---|
1112 | client->lastcaid = er->caid;
|
---|
1113 | client->lastpid = er->pid;
|
---|
1114 |
|
---|
1115 |
|
---|
1116 |
|
---|
1117 | if(!tcp_connect(client)) { return -1; }
|
---|
1118 |
|
---|
1119 | client->reader->card_status = CARD_INSERTED; //for udp
|
---|
1120 |
|
---|
1121 | memset(buf, 0, 20);
|
---|
1122 | memset(buf + 20, 0xff, er->ecmlen + 15);
|
---|
1123 | buf[1] = er->ecmlen;
|
---|
1124 | i2b_buf(2, er->srvid, buf + 8);
|
---|
1125 | i2b_buf(2, er->caid, buf + 10);
|
---|
1126 | i2b_buf(4, er->prid, buf + 12);
|
---|
1127 | i2b_buf(2, er->idx, buf + 16);
|
---|
1128 | buf[18] = 0xff;
|
---|
1129 | buf[19] = 0xff;
|
---|
1130 | memcpy(buf + 20, er->ecm, er->ecmlen);
|
---|
1131 | return ((camd35_send(client, buf, 0) < 1) ? (-1) : 0);
|
---|
1132 | }
|
---|
1133 |
|
---|
1134 | static int32_t camd35_send_emm(EMM_PACKET *ep)
|
---|
1135 | {
|
---|
1136 | uchar buf[512];
|
---|
1137 | struct s_client *cl = cur_client();
|
---|
1138 |
|
---|
1139 |
|
---|
1140 | if(!tcp_connect(cl)) { return -1; }
|
---|
1141 |
|
---|
1142 | memset(buf, 0, 20);
|
---|
1143 | memset(buf + 20, 0xff, ep->emmlen + 15);
|
---|
1144 |
|
---|
1145 | buf[0] = 0x06;
|
---|
1146 | buf[1] = ep->emmlen;
|
---|
1147 | memcpy(buf + 10, ep->caid, 2);
|
---|
1148 | memcpy(buf + 12, ep->provid, 4);
|
---|
1149 | memcpy(buf + 20, ep->emm, ep->emmlen);
|
---|
1150 |
|
---|
1151 | return ((camd35_send_without_timeout(cl, buf, 0) < 1) ? 0 : 1);
|
---|
1152 | }
|
---|
1153 |
|
---|
1154 | static int32_t camd35_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t rc2 __attribute__((unused)))
|
---|
1155 | {
|
---|
1156 | uint16_t idx;
|
---|
1157 | static const char *typtext[] = {"ok", "invalid", "sleeping"};
|
---|
1158 | struct s_reader *rdr = client->reader;
|
---|
1159 | rdr->last_g = time(NULL); // last receive is now
|
---|
1160 |
|
---|
1161 | // reading CMD05 Emm request and set serial
|
---|
1162 | if(buf[0] == 0x05 && buf[1] == 111)
|
---|
1163 | {
|
---|
1164 |
|
---|
1165 | //cs_log("CMD05: %s", cs_hexdump(1, buf, buf[1], tmp, sizeof(tmp)));
|
---|
1166 | rdr->nprov = 0; //reset if number changes on reader change
|
---|
1167 | rdr->nprov = buf[47];
|
---|
1168 | rdr->caid = b2i(2, buf + 20);
|
---|
1169 | rdr->auprovid = b2i(4, buf + 12);
|
---|
1170 |
|
---|
1171 | int32_t i;
|
---|
1172 | for(i = 0; i < rdr->nprov; i++)
|
---|
1173 | {
|
---|
1174 | if(((rdr->caid >= 0x1700) && (rdr->caid <= 0x1799)) || // Betacrypt
|
---|
1175 | ((rdr->caid >= 0x0600) && (rdr->caid <= 0x0699))) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
|
---|
1176 | {
|
---|
1177 | rdr->prid[i][0] = buf[48 + (i * 5)];
|
---|
1178 | memcpy(&rdr->prid[i][1], &buf[50 + (i * 5)], 3);
|
---|
1179 | }
|
---|
1180 | else
|
---|
1181 | {
|
---|
1182 | rdr->prid[i][2] = buf[48 + (i * 5)];
|
---|
1183 | rdr->prid[i][3] = buf[49 + (i * 5)];
|
---|
1184 | memcpy(&rdr->sa[i][0], &buf[50 + (i * 5)], 4);
|
---|
1185 | }
|
---|
1186 | }
|
---|
1187 |
|
---|
1188 | memcpy(rdr->hexserial, buf + 40, 6);
|
---|
1189 | rdr->hexserial[6] = 0;
|
---|
1190 | rdr->hexserial[7] = 0;
|
---|
1191 |
|
---|
1192 | rdr->blockemm = 0;
|
---|
1193 | rdr->blockemm |= (buf[128] == 1) ? 0 : EMM_GLOBAL;
|
---|
1194 | rdr->blockemm |= (buf[129] == 1) ? 0 : EMM_SHARED;
|
---|
1195 | rdr->blockemm |= (buf[130] == 1) ? 0 : EMM_UNIQUE;
|
---|
1196 | cs_log("%s CMD05 AU request for caid: %04X auprovid: %06X",
|
---|
1197 | rdr->label,
|
---|
1198 | rdr->caid,
|
---|
1199 | rdr->auprovid);
|
---|
1200 | }
|
---|
1201 |
|
---|
1202 | if(buf[0] == 0x08
|
---|
1203 | && ((rdr->ph.type == MOD_CONN_TCP && !cfg.c35_tcp_suppresscmd08)
|
---|
1204 | || (rdr->ph.type == MOD_CONN_UDP
|
---|
1205 | && !cfg.c35_udp_suppresscmd08)))
|
---|
1206 | {
|
---|
1207 | if(buf[21] == 0xFF)
|
---|
1208 | {
|
---|
1209 | client->stopped = 2; // server says sleep
|
---|
1210 | rdr->card_status = NO_CARD;
|
---|
1211 | }
|
---|
1212 | else
|
---|
1213 | {
|
---|
1214 | #ifdef WITH_LB
|
---|
1215 | if(!cfg.lb_mode)
|
---|
1216 | {
|
---|
1217 | #endif
|
---|
1218 | client->stopped = 1; // server says invalid
|
---|
1219 | rdr->card_status = CARD_FAILURE;
|
---|
1220 | #ifdef WITH_LB
|
---|
1221 | }
|
---|
1222 | #endif
|
---|
1223 | }
|
---|
1224 |
|
---|
1225 | cs_log(
|
---|
1226 | "%s CMD08 (%02X - %d) stop request by server (%s)", rdr->label, buf[21], buf[21], typtext[client->stopped]);
|
---|
1227 | }
|
---|
1228 |
|
---|
1229 | #ifdef CS_CACHEEX
|
---|
1230 | if(buf[0] == 0x3d) // Cache-push id request
|
---|
1231 | {
|
---|
1232 | camd35_cache_push_receive_remote_id(client, buf); //client send request id with its nodeid, so we save it!
|
---|
1233 | camd35_cache_push_send_own_id(client, buf);
|
---|
1234 | return -1;
|
---|
1235 | }
|
---|
1236 | if(buf[0] == 0x3e) // Cache-push id answer
|
---|
1237 | {
|
---|
1238 | camd35_cache_push_receive_remote_id(client, buf);
|
---|
1239 | return -1;
|
---|
1240 | }
|
---|
1241 | if(buf[0] == 0x3f) //cache-push
|
---|
1242 | {
|
---|
1243 | camd35_cache_push_in(client, buf);
|
---|
1244 | return -1;
|
---|
1245 | }
|
---|
1246 | #endif
|
---|
1247 |
|
---|
1248 | if(buf[0] == 55) //keepalive answer
|
---|
1249 | { return -1; }
|
---|
1250 |
|
---|
1251 | // CMD44: old reject command introduced in mpcs
|
---|
1252 | // keeping this for backward compatibility
|
---|
1253 | if((buf[0] != 1) && (buf[0] != 0x44) && (buf[0] != 0x08))
|
---|
1254 | { return (-1); }
|
---|
1255 |
|
---|
1256 | idx = b2i(2, buf + 16);
|
---|
1257 |
|
---|
1258 | #ifdef CS_CACHEEX
|
---|
1259 | if(buf[0] == 0x01 && buf[18] < 0xFF && buf[18] > 0x00) // cwc info ; normal camd3 ecms send 0xFF but we need no cycletime of 255 ;)
|
---|
1260 | {
|
---|
1261 | camd35_recv_ce1_cwc_info(client, buf, idx);
|
---|
1262 | }
|
---|
1263 | #endif
|
---|
1264 |
|
---|
1265 | *rc = ((buf[0] != 0x44) && (buf[0] != 0x08));
|
---|
1266 |
|
---|
1267 | memcpy(dcw, buf + 20, 16);
|
---|
1268 | return (idx);
|
---|
1269 | }
|
---|
1270 |
|
---|
1271 | /*
|
---|
1272 | * module definitions
|
---|
1273 | */
|
---|
1274 | #ifdef MODULE_CAMD35
|
---|
1275 | void module_camd35(struct s_module *ph)
|
---|
1276 | {
|
---|
1277 | ph->ptab.nports = 1;
|
---|
1278 | ph->ptab.ports[0].s_port = cfg.c35_port;
|
---|
1279 |
|
---|
1280 | ph->desc = "cs357x";
|
---|
1281 | ph->type = MOD_CONN_UDP;
|
---|
1282 | ph->large_ecm_support = 1;
|
---|
1283 | ph->listenertype = LIS_CAMD35UDP;
|
---|
1284 | IP_ASSIGN(ph->s_ip, cfg.c35_srvip);
|
---|
1285 | ph->s_handler = camd35_server;
|
---|
1286 | ph->recv = camd35_recv;
|
---|
1287 | ph->send_dcw = camd35_send_dcw;
|
---|
1288 | ph->c_init = camd35_client_init;
|
---|
1289 | ph->c_recv_chk = camd35_recv_chk;
|
---|
1290 | ph->c_send_ecm = camd35_send_ecm;
|
---|
1291 | ph->c_send_emm = camd35_send_emm;
|
---|
1292 | ph->c_idle = camd35_idle;
|
---|
1293 | #ifdef CS_CACHEEX
|
---|
1294 | ph->c_cache_push = camd35_cache_push_out;
|
---|
1295 | ph->c_cache_push_chk = camd35_cache_push_chk;
|
---|
1296 | #endif
|
---|
1297 | ph->num = R_CAMD35;
|
---|
1298 | }
|
---|
1299 | #endif
|
---|
1300 |
|
---|
1301 | #ifdef MODULE_CAMD35_TCP
|
---|
1302 | void module_camd35_tcp(struct s_module *ph)
|
---|
1303 | {
|
---|
1304 | ph->desc = "cs378x";
|
---|
1305 | ph->type = MOD_CONN_TCP;
|
---|
1306 | ph->large_ecm_support = 1;
|
---|
1307 | ph->listenertype = LIS_CAMD35TCP;
|
---|
1308 | ph->ptab = cfg.c35_tcp_ptab;
|
---|
1309 | IP_ASSIGN(ph->s_ip, cfg.c35_tcp_srvip);
|
---|
1310 | ph->s_handler = camd35_server;
|
---|
1311 | ph->recv = camd35_recv;
|
---|
1312 | ph->send_dcw = camd35_send_dcw;
|
---|
1313 | ph->c_init = camd35_client_init;
|
---|
1314 | ph->c_recv_chk = camd35_recv_chk;
|
---|
1315 | ph->c_send_ecm = camd35_send_ecm;
|
---|
1316 | ph->c_send_emm = camd35_send_emm;
|
---|
1317 | ph->c_idle = camd35_idle;
|
---|
1318 | #ifdef CS_CACHEEX
|
---|
1319 | ph->c_cache_push = camd35_cache_push_out;
|
---|
1320 | ph->c_cache_push_chk = camd35_cache_push_chk;
|
---|
1321 | #endif
|
---|
1322 | ph->num = R_CS378X;
|
---|
1323 | }
|
---|
1324 | #endif
|
---|
1325 | #endif
|
---|