1 #define MODULE_LOG_PREFIX "pandora"
7 #include "cscrypt/md5.h"
8 #include "oscam-client.h"
10 #include "oscam-net.h"
11 #include "oscam-string.h"
13 #define CWS_NETMSGSIZE 320
14 #define START_TIME 150000
15 #define MAX_TIME 500000
17 static void simple_crypt(uint8_t *buf
, int len
, uint8_t *key
, int key_len
)
20 for(i
= 0, x
= 0; i
< len
; i
++)
28 static void pandora_process_request(struct s_client
*cl
, uint8_t *buf
, int32_t l
)
32 uint8_t md5tmp
[MD5_DIGEST_LENGTH
];
34 if(l
< 10 + CS_ECMSTORESIZE
+ 2)
37 if(!(er
= get_ecmtask()))
39 er
->caid
= b2i(2, buf
+ 1);
40 er
->srvid
= b2i(2, buf
+ 3);
41 er
->prid
= b2i(4, buf
+ 5);
42 //er->ecmcrc32 = crc32(0L, buf+10, CS_ECMSTORESIZE);
43 er
->chid
= b2i(2, buf
+ 10 + CS_ECMSTORESIZE
);
45 if(!cl
->pand_ignore_ecm
&& (l
>= 10 + CS_ECMSTORESIZE
+ 2 + 2))
47 ecmlen
= b2i(2, buf
+ 10 + CS_ECMSTORESIZE
+ 2);
49 if(ecmlen
< 0 || ecmlen
> MAX_ECM_SIZE
50 || ((10 + CS_ECMSTORESIZE
+ 2 + 2 + ecmlen
) > CWS_NETMSGSIZE
)
51 || ((10 + CS_ECMSTORESIZE
+ 2 + 2 + ecmlen
) > l
))
57 if(!memcmp(buf
+ 10, MD5(buf
+ 14 + CS_ECMSTORESIZE
, ecmlen
, md5tmp
), CS_ECMSTORESIZE
))
60 memcpy(er
->ecm
, buf
+ 14 + CS_ECMSTORESIZE
, ecmlen
);
61 //set_ecmhash(cl, er);
71 { usleep(cl
->pand_autodelay
); }
75 static int pandora_recv(struct s_client
*cl
, uint8_t *buf
, int32_t l
)
82 { ret
= recv_from_udpipe(buf
); }
85 ret
= recvfrom(cl
->udp_fd
, buf
, l
, 0, (struct sockaddr
*)&cl
->udp_sa
, &cl
->udp_sa_len
);
90 simple_crypt(buf
, ret
, cl
->pand_md5_key
, 16);
91 cl
->last
= time((time_t *) 0);
94 { pandora_process_request(cl
, buf
, ret
); }
98 static void pandora_send_dcw(struct s_client
*cl
, ECM_REQUEST
*er
)
100 uint8_t msgbuf
[CWS_NETMSGSIZE
], len
;
101 if(cfg
.pand_skip_send_dw
)
103 if(er
->rc
< E_NOTFOUND
)
105 msgbuf
[0] = 2; // DW_FOUND
106 memcpy(&msgbuf
[1], er
->cw
, 16);
108 cl
->pand_autodelay
= START_TIME
;
112 msgbuf
[0] = 0xFF; // DW_NOT_FOUND
114 if(cl
->pand_autodelay
< MAX_TIME
)
115 { cl
->pand_autodelay
+= 100000; }
117 simple_crypt(msgbuf
, len
, cl
->pand_md5_key
, 16);
118 sendto(cl
->udp_fd
, msgbuf
, len
, 0, (struct sockaddr
*) &cl
->udp_sa
, cl
->udp_sa_len
);
121 int pandora_auth_client(struct s_client
*cl
, IN_ADDR_T ip
)
124 struct s_auth
*account
;
127 // FIXME: Add IPv6 support
128 (void)ip
; // Prevent warning about unused var "ip"
130 if(!cl
->pand_ignore_ecm
&& cfg
.pand_allowed
)
133 for(ok
= 0, p_ip
= cfg
.pand_allowed
; (p_ip
) && (!ok
); p_ip
135 { ok
= ((ip
>= p_ip
->ip
[0]) && (ip
<= p_ip
->ip
[1])); }
139 cs_auth_client(cl
, (struct s_auth
*) 0, "IP not allowed");
145 for(ok
= 0, account
= cfg
.account
; cfg
.pand_usr
&& account
&& !ok
; account
= account
->next
)
147 ok
= streq(cfg
.pand_usr
, account
->usr
);
148 if(ok
&& cs_auth_client(cl
, account
, NULL
))
149 { cs_disconnect_client(cl
); }
152 { cs_auth_client(cl
, (struct s_auth
*)(-1), NULL
); }
156 static void *pandora_server(struct s_client
*cl
, uint8_t *UNUSED(mbuf
), int32_t UNUSED(len
))
158 uint8_t md5tmp
[MD5_DIGEST_LENGTH
];
163 cl
->pand_autodelay
= 150000;
164 memcpy(cl
->pand_md5_key
, MD5((uint8_t *)cfg
.pand_pass
, cs_strlen(cfg
.pand_pass
), md5tmp
), 16);
165 cl
->pand_ignore_ecm
= (cfg
.pand_ecm
) ? 0 : 1;
167 pandora_auth_client(cl
, cl
->ip
);
172 cs_log("Password for Pandora share MUST be set !!!");
178 /************************************************************************************************************************
180 *************************************************************************************************************************/
181 int pandora_client_init(struct s_client
*cl
)
183 static struct sockaddr_in loc_sa
;
186 struct s_reader
*rdr
= cl
->reader
;
187 uint8_t md5tmp
[MD5_DIGEST_LENGTH
];
192 cs_log("invalid port %d for server %s", rdr
->r_port
, rdr
->device
);
195 p_proto
= IPPROTO_UDP
;
197 set_null_ip(&cl
->ip
);
198 memset((char *) &loc_sa
, 0, sizeof(loc_sa
));
199 loc_sa
.sin_family
= AF_INET
;
201 if(IP_ISSET(cfg
.srvip
))
202 { IP_ASSIGN(SIN_GET_ADDR(loc_sa
), cfg
.srvip
); }
204 { loc_sa
.sin_addr
.s_addr
= INADDR_ANY
; }
205 loc_sa
.sin_port
= htons(rdr
->l_port
);
207 if((cl
->udp_fd
= socket(PF_INET
, SOCK_DGRAM
, p_proto
)) < 0)
209 cs_log("Socket creation failed (errno=%d)", errno
);
214 setsockopt(cl
->udp_fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
));
216 set_so_reuseport(cl
->udp_fd
);
218 set_socket_priority(cl
->udp_fd
, cfg
.netprio
);
222 if(bind(cl
->udp_fd
, (struct sockaddr
*) &loc_sa
, sizeof(loc_sa
)) < 0)
224 cs_log("bind failed (errno=%d)", errno
);
228 snprintf(ptxt
, sizeof(ptxt
), ", port=%d", rdr
->l_port
);
233 memcpy(cl
->pand_md5_key
, MD5((uint8_t *)rdr
->r_pwd
, cs_strlen(rdr
->r_pwd
), md5tmp
), 16);
236 //cl->grp = 0xFFFFFFFF;
237 //rdr->caid[0] = rdr->ctab.caid[0];
239 cl
->pand_send_ecm
= rdr
->pand_send_ecm
;
240 memset((char *) &cl
->udp_sa
, 0, sizeof(cl
->udp_sa
));
242 ((struct sockaddr_in
*)(&cl
->udp_sa
))->sin_family
= AF_INET
;
243 ((struct sockaddr_in
*)(&cl
->udp_sa
))->sin_port
= htons((u_short
) rdr
->r_port
);
245 cl
->udp_sa
.sin_family
= AF_INET
;
246 cl
->udp_sa
.sin_port
= htons((u_short
) rdr
->r_port
);
249 cs_log("proxy %s:%d pandora %s (%s)", rdr
->device
, rdr
->r_port
, rdr
->pand_send_ecm
? "with ECM support" : "", ptxt
);
251 cl
->pfd
= cl
->udp_fd
;
252 //set_nonblock(cl->udp_fd, true); //!!!!!
256 static int pandora_send_ecm(struct s_client
*cl
, ECM_REQUEST
*er
)
258 uint8_t md5tmp
[MD5_DIGEST_LENGTH
];
259 uint8_t msgbuf
[CWS_NETMSGSIZE
];
262 adel
= (cfg
.ctimeout
> 7) ? 7 : cfg
.ctimeout
;
265 msgbuf
[1] = er
->caid
>> 8;
266 msgbuf
[2] = er
->caid
& 0xFF;
267 msgbuf
[3] = er
->srvid
>> 8;
268 msgbuf
[4] = er
->srvid
& 0xFF;
269 msgbuf
[5] = er
->prid
>> 24;
270 msgbuf
[6] = er
->prid
>> 16;
271 msgbuf
[7] = er
->prid
>> 8;
272 msgbuf
[8] = er
->prid
& 0xFF;
274 memcpy(&msgbuf
[10], MD5(er
->ecm
, er
->ecmlen
, md5tmp
), CS_ECMSTORESIZE
);
275 msgbuf
[10 + CS_ECMSTORESIZE
] = er
->chid
>> 8;
276 msgbuf
[11 + CS_ECMSTORESIZE
] = er
->chid
& 0xFF;
277 len
= 12 + CS_ECMSTORESIZE
;
278 if(cl
->pand_send_ecm
)
280 if(len
+2+er
->ecmlen
> CWS_NETMSGSIZE
)
282 msgbuf
[12 + CS_ECMSTORESIZE
] = er
->ecmlen
>> 8;
283 msgbuf
[13 + CS_ECMSTORESIZE
] = er
->ecmlen
& 0xFF;
284 memcpy(&msgbuf
[14 + CS_ECMSTORESIZE
], er
->ecm
, er
->ecmlen
);
285 len
+= er
->ecmlen
+ 2;
287 simple_crypt(msgbuf
, len
, cl
->pand_md5_key
, 16);
288 ret
= sendto(cl
->pfd
, msgbuf
, len
, 0, (struct sockaddr
*) &cl
->udp_sa
, cl
->udp_sa_len
);
289 return ((ret
< len
) ? (-1) : 0);
292 static int pandora_recv_chk(struct s_client
*UNUSED(cl
), uint8_t *dcw
, int *rc
, uint8_t *buf
, int UNUSED(n
))
297 memcpy(dcw
, buf
+ 1, 16);
301 void module_pandora(struct s_module
*ph
)
304 ph
->ptab
.ports
[0].s_port
= cfg
.pand_port
;
307 ph
->desc
= "pandora";
308 ph
->type
= MOD_CONN_UDP
;
309 ph
->large_ecm_support
= 1;
311 IP_ASSIGN(ph
->s_ip
, cfg
.pand_srvip
);
312 ph
->s_handler
= pandora_server
;
313 ph
->recv
= pandora_recv
;
314 ph
->send_dcw
= pandora_send_dcw
;
316 ph
->c_init
= pandora_client_init
;
317 ph
->c_recv_chk
= pandora_recv_chk
;
318 ph
->c_send_ecm
= pandora_send_ecm
;