source: trunk/module-pandora.c@ 8455

Last change on this file since 8455 was 8455, checked in by gf, 9 years ago

Make ptab in struct s_module embedded not a pointer.

This blows up bss (static) memory nearly twice but we'll get that
back and lots more once we slim down struct s_port in the next
commit.

  • Property svn:eol-style set to LF
File size: 7.3 KB
Line 
1#include "globals.h"
2
3#ifdef MODULE_PANDORA
4
5#include "cscrypt/md5.h"
6#include "oscam-client.h"
7#include "oscam-ecm.h"
8#include "oscam-net.h"
9#include "oscam-string.h"
10
11#define CWS_NETMSGSIZE 320
12#define START_TIME 150000
13#define MAX_TIME 500000
14
15static void simple_crypt(uchar *buf, int len, uchar * key, int key_len) {
16 int i, x;
17 for (i = 0, x = 0; i < len; i++) {
18 buf[i] ^= key[x++];
19 if (x >= key_len)
20 x = 0;
21 }
22}
23
24static void pandora_process_request(struct s_client *cl, uchar *buf, int32_t l) {
25 int ecmlen;
26 ECM_REQUEST *er;
27 uchar md5tmp[MD5_DIGEST_LENGTH];
28
29 if (!(er = get_ecmtask()))
30 return;
31 er->caid = b2i(2, buf + 1);
32 er->srvid = b2i(2, buf + 3);
33 er->prid = b2i(4, buf + 5);
34 //er->ecmcrc32 = crc32(0L, buf+10, CS_ECMSTORESIZE);
35 er->chid = b2i(2, buf + 10 + CS_ECMSTORESIZE);
36
37 if (l > 12 + CS_ECMSTORESIZE + 16) {
38 ecmlen = b2i(2, buf + 12 + CS_ECMSTORESIZE);
39 if ((ecmlen > 320) || cl->pand_ignore_ecm)
40 er->ecmlen = 0;
41 else {
42 if (!memcmp(buf + 10,
43 MD5(buf + 14 + CS_ECMSTORESIZE, ecmlen, md5tmp),
44 CS_ECMSTORESIZE)) {
45 er->ecmlen = ecmlen;
46 memcpy(er->ecm, buf + 14 + CS_ECMSTORESIZE, ecmlen);
47 //set_ecmhash(cl, er);
48 } else
49 er->ecmlen = 0;
50 }
51 } else
52 er->ecmlen = 0;
53
54 if (!er->ecmlen)
55 usleep(cl->pand_autodelay);
56 get_cw(cl, er);
57}
58
59static int pandora_recv(struct s_client *cl, uchar *buf, int32_t l) {
60 int ret;
61
62 if (!cl->udp_fd)
63 return (-9);
64 if (cl->typ != 'c')
65 ret = recv_from_udpipe(buf);
66 else {
67 ret = recvfrom(cl->udp_fd, buf, l, 0, (struct sockaddr *)&cl->udp_sa, &cl->udp_sa_len);
68 }
69 if (ret < 1)
70 return (-1);
71
72 simple_crypt(buf, ret, cl->pand_md5_key, 16);
73 cl->last = time((time_t *) 0);
74
75 if (cl->typ != 'c')
76 pandora_process_request(cl, buf, ret);
77 return (ret);
78}
79
80static void pandora_send_dcw(struct s_client *cl, ECM_REQUEST *er) {
81 uchar msgbuf[CWS_NETMSGSIZE], len;
82 if (cfg.pand_skip_send_dw)
83 return;
84 if (er->rc < 4) {
85 msgbuf[0] = 2; //DW_FOUND
86 memcpy(&msgbuf[1], er->cw, 16);
87 len = 1 + 16;
88 cl->pand_autodelay = START_TIME;
89 } else {
90 msgbuf[0] = 0xFF; //DW_NOT_FOUND
91 len = 1;
92 if (cl->pand_autodelay < MAX_TIME)
93 cl->pand_autodelay += 100000;
94 }
95 simple_crypt(msgbuf, len, cl->pand_md5_key, 16);
96 sendto(cl->udp_fd, msgbuf, len, 0, (struct sockaddr *) &cl->udp_sa, cl->udp_sa_len);
97}
98
99int pandora_auth_client(struct s_client *cl, IN_ADDR_T ip) {
100 int ok;
101 struct s_auth *account;
102
103#ifdef IPV6SUPPORT
104 // FIXME: Add IPv6 support
105 (void)ip; // Prevent warning about unused var "ip"
106#else
107 if (!cl->pand_ignore_ecm && cfg.pand_allowed) {
108 struct s_ip *p_ip;
109 for (ok = 0, p_ip = cfg.pand_allowed; (p_ip) && (!ok); p_ip
110 = p_ip->next)
111 ok = ((ip >= p_ip->ip[0]) && (ip <= p_ip->ip[1]));
112
113 if (!ok) {
114 cs_auth_client(cl, (struct s_auth *) 0, "IP not allowed");
115 return 0;
116 }
117 }
118#endif
119
120 for (ok = 0, account = cfg.account; cfg.pand_usr && account && !ok; account = account->next) {
121 ok = streq(cfg.pand_usr, account->usr);
122 if (ok && cs_auth_client(cl, account, NULL))
123 cs_disconnect_client(cl);
124 }
125 if (!ok)
126 cs_auth_client(cl, (struct s_auth *) (-1), NULL);
127 return ok;
128}
129
130static void * pandora_server(struct s_client *cl, uchar *UNUSED(mbuf),
131 int32_t UNUSED(len)) {
132 uchar md5tmp[MD5_DIGEST_LENGTH];
133 if (!cl->init_done) {
134 if (cfg.pand_pass) {
135 cl->pand_autodelay = 150000;
136 memcpy(cl->pand_md5_key,
137 MD5((uchar*)cfg.pand_pass, strlen(cfg.pand_pass), md5tmp), 16);
138 cl->pand_ignore_ecm = (cfg.pand_ecm) ? 0 : 1;
139 cl->crypted = 1;
140 pandora_auth_client(cl, cl->ip);
141 cl->init_done = 1;
142 } else {
143 cs_log("Password for Pandora share MUST be set !!!");
144 }
145 }
146 return NULL;
147}
148
149/************************************************************************************************************************
150 * client functions
151 *************************************************************************************************************************/
152int pandora_client_init(struct s_client *cl) {
153 static struct sockaddr_in loc_sa;
154 int16_t p_proto;
155 char ptxt[16];
156 struct s_reader *rdr = cl->reader;
157 uchar md5tmp[MD5_DIGEST_LENGTH];
158
159 cl->pfd = 0;
160 if (rdr->r_port <= 0) {
161 cs_log("invalid port %d for server %s", rdr->r_port, rdr->device);
162 return (1);
163 }
164 p_proto = IPPROTO_UDP;
165
166 set_null_ip(&cl->ip);
167 memset((char *) &loc_sa, 0, sizeof(loc_sa));
168 loc_sa.sin_family = AF_INET;
169
170 if (IP_ISSET(cfg.srvip))
171 IP_ASSIGN(SIN_GET_ADDR(loc_sa), cfg.srvip);
172 else
173 loc_sa.sin_addr.s_addr = INADDR_ANY;
174 loc_sa.sin_port = htons(rdr->l_port);
175
176 if ((cl->udp_fd = socket(PF_INET, SOCK_DGRAM, p_proto)) < 0) {
177 cs_log("Socket creation failed (errno=%d)", errno);
178 return 1;
179 }
180
181 set_socket_priority(cl->udp_fd, cfg.netprio);
182
183 if (rdr->l_port > 0) {
184 if (bind(cl->udp_fd, (struct sockaddr *) &loc_sa, sizeof(loc_sa)) < 0) {
185 cs_log("bind failed (errno=%d)", errno);
186 close(cl->udp_fd);
187 return (1);
188 }
189 snprintf(ptxt, sizeof(ptxt), ", port=%d", rdr->l_port);
190 } else
191 ptxt[0] = '\0';
192
193 memcpy(cl->pand_md5_key, MD5((uchar*)rdr->r_pwd, strlen(rdr->r_pwd), md5tmp), 16);
194 cl->crypted = 1;
195
196 //cl->grp = 0xFFFFFFFF;
197 //rdr->caid[0] = rdr->ctab.caid[0];
198
199 cl->pand_send_ecm = rdr->pand_send_ecm;
200 memset((char *) &cl->udp_sa, 0, sizeof(cl->udp_sa));
201#ifdef IPV6SUPPORT
202 ((struct sockaddr_in *)(&cl->udp_sa))->sin_family = AF_INET;
203 ((struct sockaddr_in *)(&cl->udp_sa))->sin_port = htons((u_short) rdr->r_port);
204#else
205 cl->udp_sa.sin_family = AF_INET;
206 cl->udp_sa.sin_port = htons((u_short) rdr->r_port);
207#endif
208
209 cs_log("proxy %s:%d pandora %s (%s)", rdr->device, rdr->r_port, rdr->pand_send_ecm?"with ECM support":"", ptxt );
210
211 cl->pfd = cl->udp_fd;
212 //fcntl(cl->udp_fd, F_SETFL, fcntl(cl->udp_fd, F_GETFL, 0) | O_NONBLOCK); //!!!!!
213 return (0);
214}
215
216static int pandora_send_ecm(struct s_client *cl, ECM_REQUEST *er, uchar *UNUSED(buf)) {
217 uchar md5tmp[MD5_DIGEST_LENGTH];
218 uchar msgbuf[CWS_NETMSGSIZE];
219 int ret, len;
220 uchar adel;
221 adel = (cfg.ctimeout > 7) ? 7 : cfg.ctimeout;
222
223 msgbuf[0] = 1;
224 msgbuf[1] = er->caid >> 8;
225 msgbuf[2] = er->caid & 0xFF;
226 msgbuf[3] = er->srvid >> 8;
227 msgbuf[4] = er->srvid & 0xFF;
228 msgbuf[5] = er->prid >> 24;
229 msgbuf[6] = er->prid >> 16;
230 msgbuf[7] = er->prid >> 8;
231 msgbuf[8] = er->prid & 0xFF;
232 msgbuf[9] = adel;
233 memcpy(&msgbuf[10], MD5(er->ecm, er->ecmlen, md5tmp), CS_ECMSTORESIZE);
234 msgbuf[10 + CS_ECMSTORESIZE] = er->chid >> 8;
235 msgbuf[11 + CS_ECMSTORESIZE] = er->chid & 0xFF;
236 len = 12 + CS_ECMSTORESIZE;
237 if (cl->pand_send_ecm) {
238 msgbuf[12 + CS_ECMSTORESIZE] = er->ecmlen >> 8;
239 msgbuf[13 + CS_ECMSTORESIZE] = er->ecmlen & 0xFF;
240 memcpy(&msgbuf[14 + CS_ECMSTORESIZE], er->ecm, er->ecmlen);
241 len += er->ecmlen + 2;
242 }
243 simple_crypt(msgbuf, len, cl->pand_md5_key, 16);
244 ret = sendto(cl->pfd, msgbuf, len, 0, (struct sockaddr *) &cl->udp_sa, cl->udp_sa_len);
245 return ((ret < len) ? (-1) : 0);
246}
247
248static int pandora_recv_chk(struct s_client *UNUSED(cl), uchar *dcw, int *rc,
249 uchar *buf, int UNUSED(n)) {
250 if (buf[0] != 0x2)
251 return (-1);
252 *rc = 1;
253 memcpy(dcw, buf + 1, 16);
254 return (0);
255}
256
257void module_pandora(struct s_module *ph) {
258 ph->ptab.nports = 1;
259 ph->ptab.ports[0].s_port = cfg.pand_port;
260 ph->num = R_PANDORA;
261
262 ph->desc = "pandora";
263 ph->type = MOD_CONN_UDP;
264 ph->large_ecm_support = 1;
265 //ph->watchdog = 1;
266 IP_ASSIGN(ph->s_ip, cfg.pand_srvip);
267 ph->s_handler = pandora_server;
268 ph->recv = pandora_recv;
269 ph->send_dcw = pandora_send_dcw;
270
271 ph->c_init = pandora_client_init;
272 ph->c_recv_chk = pandora_recv_chk;
273 ph->c_send_ecm = pandora_send_ecm;
274}
275
276#endif
Note: See TracBrowser for help on using the repository browser.