示例#1
0
int pandora_auth_client(struct s_client *cl, IN_ADDR_T ip) {
	int ok;
	struct s_auth *account;

#ifdef IPV6SUPPORT
	// FIXME: Add IPv6 support
	(void)ip; // Prevent warning about unused var "ip"
#else
	if (!cl->pand_ignore_ecm && cfg.pand_allowed) {
		struct s_ip *p_ip;
		for (ok = 0, p_ip = cfg.pand_allowed; (p_ip) && (!ok); p_ip
				= p_ip->next)
			ok = ((ip >= p_ip->ip[0]) && (ip <= p_ip->ip[1]));

		if (!ok) {
			cs_auth_client(cl, (struct s_auth *) 0, "IP not allowed");
			return 0;
		}
	}
#endif

	for (ok = 0, account = cfg.account; cfg.pand_usr && account && !ok; account = account->next) {
		ok = streq(cfg.pand_usr, account->usr);
		if (ok && cs_auth_client(cl, account, NULL))
			cs_disconnect_client(cl);
	}
	if (!ok)
		cs_auth_client(cl, (struct s_auth *) (-1), NULL);
	return ok;
}
示例#2
0
static int32_t __camd35_send(struct s_client *cl, uchar *buf, int32_t buflen, int answer_awaited)
{
	int32_t l;
	unsigned char rbuf[REQ_SIZE + 15 + 4], *sbuf = rbuf + 4;

	if(!cl->udp_fd || !cl->crypted) { return (-1); }  //exit if no fd or aes key not set!

	//Fix ECM len > 255
	if(buflen <= 0)
		{ buflen = ((buf[0] == 0) ? (((buf[21] & 0x0f) << 8) | buf[22]) + 3 : buf[1]); }
	l = 20 + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0) + buflen;
	memcpy(rbuf, cl->ucrc, 4);
	memcpy(sbuf, buf, l);
	memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's
	i2b_buf(4, crc32(0L, sbuf + 20, buflen), sbuf + 4);
	l = boundary(4, l);
	cs_log_dump_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, sbuf, l, "send %d bytes to %s", l, username(cl));
	aes_encrypt_idx(cl->aes_keys, sbuf, l);

	int32_t status;
	if(cl->is_udp)
	{
		status = sendto(cl->udp_fd, rbuf, l + 4, 0, (struct sockaddr *)&cl->udp_sa, cl->udp_sa_len);
		if(status == -1) { set_null_ip(&SIN_GET_ADDR(cl->udp_sa)); }
	}
	else
	{
		status = send(cl->udp_fd, rbuf, l + 4, 0);

		if(cl->typ == 'p' && cl->reader)
		{
			if(status == -1) { network_tcp_connection_close(cl->reader, "can't send"); }
		}
		else if(cl->typ == 'c')
		{
			if(status == -1) { cs_disconnect_client(cl); }
		}
	}
	if(status != -1)
	{
		if(cl->reader && answer_awaited)
		{
			cl->reader->last_s = time(NULL);
		}
		if(cl->reader && !answer_awaited)
		{
			cl->reader->last_s = cl->reader->last_g = time(NULL);
		}
		cl->last = time(NULL);

	}
	return status;
}
示例#3
0
static void monitor_login(char *usr){
	char *pwd=NULL;
	int8_t res = 0;
	if ((usr) && (pwd=strchr(usr, ' ')))
		*pwd++=0;
	if (pwd)
		res = monitor_auth_client(trim(usr), trim(pwd));
	else
		res = monitor_auth_client(NULL, NULL);

	if (res == -1) {
		cs_disconnect_client(cur_client());
		return;
	}
	monitor_send_login();
}
示例#4
0
static void * radegast_server(void *cli)
{
  int32_t n;
  uchar mbuf[1024];

	struct s_client * client = (struct s_client *) cli;
  client->thread=pthread_self();
  pthread_setspecific(getclient, cli);

  radegast_auth_client(cur_client()->ip);
  while ((n=get_request(mbuf))>0)
  {
    switch(mbuf[0])
    {
      case 1:
        radegast_process_ecm(mbuf+2, mbuf[1]);
        break;
      default:
        radegast_process_unknown(mbuf);
    }
  }
  cs_disconnect_client(client);
  return NULL;
}
示例#5
0
static int32_t camd35_recv(struct s_client *client, uchar *buf, int32_t l)
{
	int32_t rc, s, rs, n = 0, buflen = 0, len = 0;
	for(rc = rs = s = 0; !rc; s++)
	{
		switch(s)
		{
		case 0:
			if(!client->udp_fd) { return (-9); }
			if(client->is_udp && client->typ == 'c')
			{
				rs = recv_from_udpipe(buf);
			}
			else
			{
				//read minimum packet size (4 byte ucrc + 32 byte data) to detect packet size (tcp only)

				//rs = cs_recv(client->udp_fd, buf, client->is_udp ? l : 36, 0);
				if(client->is_udp){
					while (1){
					rs = cs_recv(client->udp_fd, buf, l, 0);
						if (rs < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}else {break;}
					}
				}else{
					int32_t tot=36, readed=0;
					rs = 0;
					do
					{
						readed = cs_recv(client->udp_fd, buf+rs, tot, 0);
						if (readed < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}
						if (readed == 0){ // nothing to read left!
							rc = -5;
							break;
						}
						if (readed > 0){ // received something, add it!
							tot-=readed;
						rs+=readed;
						}
					}
					while(tot!=0);
				}

			}
			if(rs < 36)
			{	
				if(rc != -5)
					{ rc = -1; }
				goto out;
			}
			break;
		case 1:
			switch(camd35_auth_client(client, buf))
			{
			case  0:
				break;  // ok
			case  1:
				rc = -2;
				break; // unknown user
			default:
				rc = -9;
				break; // error's from cs_auth()
			}
			memmove(buf, buf + 4, rs -= 4);
			break;
		case 2:
			aes_decrypt(client->aes_keys, buf, rs);
			if(rs != boundary(4, rs))
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "WARNING: packet size has wrong decryption boundary");

			n = (buf[0] == 3) ? 0x34 : 0;

			//Fix for ECM request size > 255 (use ecm length field)
			if(buf[0] == 0)
				{ buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; }
			else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f)  //cacheex-push
				{ buflen = buf[1] | (buf[2] << 8); }
			else
				{ buflen = buf[1]; }

			n = boundary(4, n + 20 + buflen);
			if(!(client->is_udp && client->typ == 'c') && (rs < n) && ((n - 32) > 0))
			{

				//len = cs_recv(client->udp_fd, buf+32, n-32, 0); // read the rest of the packet
				int32_t tot=n-32, readed=0;
				len = 0;
				do{
					readed = cs_recv(client->udp_fd, buf+32+len, tot, 0); // read the rest of the packet
					if (readed < 0){
						if(errno == EINTR) { continue; }  // try again in case of interrupt
						if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
						cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
						break;
					}
					if (readed == 0){ // nothing to read left!
						break;
					}
					if (readed > 0){ // received something, add it!
					tot-=readed;
					len+=readed;
					}
				}
				while(tot!=0);


				if(len > 0)
				{
					rs += len;
					aes_decrypt(client->aes_keys, buf + 32, len);
				}
				if(len < 0)
				{
					rc = -1;
					goto out;
				}
			}

			cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
						  buf, rs, "received %d bytes from %s", rs, remote_txt());

			if(n < rs)
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "ignoring %d bytes of garbage", rs - n);
			else if(n > rs) { rc = -3; }
			break;
		case 3:
			if(crc32(0L, buf + 20, buflen) != b2i(4, buf + 4)) { rc = -4; }
			if(!rc) { rc = n; }
			break;
		}
	}

out:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER, buf, rs,
					  "received %d bytes from %s (native)", rs, remote_txt());
	}
	if(rc >= 0) { client->last = time(NULL); }  // last client action is now
	switch(rc)
	{
		//case 0:   break;
	case -1:
		cs_log("packet is too small (received %d bytes, expected %d bytes)", rs, l);
		break;
	case -2:
		if(cs_auth_client(client, 0, "unknown user"))
			{ cs_disconnect_client(client); }
		break;
	case -3:
		cs_log("incomplete request !");
		break;
	case -4:
		cs_log("checksum error (wrong password ?)");
		break;
	case -5:
		cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "connection closed");
		break;		
		//default:  cs_log_dbg(D_TRACE, "camd35_recv returns rc=%d", rc); break;
	}

	return (rc);
}
示例#6
0
static void cs_fake_client(struct s_client *client, char *usr, int32_t uniq, IN_ADDR_T ip)
{
    /* Uniq = 1: only one connection per user
     *
     * Uniq = 2: set (new connected) user only to fake if source
     *           ip is different (e.g. for newcamd clients with
     *           different CAID's -> Ports)
     *
     * Uniq = 3: only one connection per user, but only the last
     *           login will survive (old mpcs behavior)
     *
     * Uniq = 4: set user only to fake if source ip is
     *           different, but only the last login will survive
     */
    struct s_client *cl;
    struct s_auth *account;
    cs_writelock(&fakeuser_lock);
    for (cl = first_client->next; cl; cl = cl->next)
    {
        account = cl->account;
        if (cl != client && cl->typ == 'c' && !cl->dup && account && streq(account->usr, usr)
                && uniq < 5 && ((uniq % 2) || !IP_EQUAL(cl->ip, ip)))
        {
            char buf[20];
            if (uniq  == 3 || uniq == 4)
            {
                cl->dup = 1;
                cl->aureader_list = NULL;
                cs_strncpy(buf, cs_inet_ntoa(cl->ip), sizeof(buf));
                cs_log("client(%8lX) duplicate user '%s' from %s (prev %s) set to fake (uniq=%d)",
                       (unsigned long)cl->thread, usr, cs_inet_ntoa(ip), buf, uniq);
                if (cl->failban & BAN_DUPLICATE) {
                    cs_add_violation(cl, usr);
                }
                if (cfg.dropdups) {
                    cs_writeunlock(&fakeuser_lock);
                    cs_sleepms(100); // sleep a bit to prevent against saturation from fast reconnecting clients
                    kill_thread(cl);
                    cs_writelock(&fakeuser_lock);
                }
            } else {
                client->dup = 1;
                client->aureader_list = NULL;
                cs_strncpy(buf, cs_inet_ntoa(ip), sizeof(buf));
                cs_log("client(%8lX) duplicate user '%s' from %s (current %s) set to fake (uniq=%d)",
                       (unsigned long)pthread_self(), usr, cs_inet_ntoa(cl->ip), buf, uniq);
                if (client->failban & BAN_DUPLICATE) {
                    cs_add_violation_by_ip(ip, get_module(client)->ptab->ports[client->port_idx].s_port, usr);
                }
                if (cfg.dropdups) {
                    cs_writeunlock(&fakeuser_lock);		// we need to unlock here as cs_disconnect_client kills the current thread!
                    cs_sleepms(100); // sleep a bit to prevent against saturation from fast reconnecting clients
                    cs_disconnect_client(client);
                    cs_writelock(&fakeuser_lock);
                }
                break;
            }
        }
    }
    cs_writeunlock(&fakeuser_lock);
}
示例#7
0
static int32_t monitor_recv(struct s_client * client, uchar *buf, int32_t l)
{
	int32_t n;
	uchar nbuf[3] = { 'U', 0, 0 };
	static int32_t bpos=0, res = 0;
	static uchar *bbuf=NULL;
	if (!bbuf)
	{
		if (!cs_malloc(&bbuf, l))
			return 0;
	}
	if (bpos)
		memcpy(buf, bbuf, n=bpos);
	else
		n=recv_from_udpipe(buf);
	bpos=0;
	if (!n) return buf[0]=0;
	if (buf[0]=='&')
	{
		int32_t bsize;
		if (n<21)	// 5+16 is minimum
		{
			cs_log("packet too small!");
			return buf[0]=0;
		}
		res = secmon_auth_client(buf+1);
		if (res == -1) {
			cs_disconnect_client(client);
			return 0;
		}
		if (!res)
			return buf[0]=0;
		aes_decrypt(client, buf+5, 16);
		bsize=boundary(4, buf[9]+5)+5;
		// cs_log("n=%d bsize=%d", n, bsize);
		if (n>bsize)
		{
			// cs_log("DO >>>> copy-back");
			memcpy(bbuf, buf+bsize, bpos=n-bsize);
			n=bsize;
			uchar *nbuf_cpy;
			if (cs_malloc(&nbuf_cpy, sizeof(nbuf))) {
				memcpy(nbuf_cpy, nbuf, sizeof(nbuf));
				add_job(client, ACTION_CLIENT_UDP, &nbuf_cpy, sizeof(nbuf));
			}
		}
		else if (n<bsize)
		{
			cs_log("packet-size mismatch !");
			return buf[0]=0;
		}
		aes_decrypt(client, buf+21, n-21);
		uchar tmp[10];
		if (memcmp(buf+5, i2b_buf(4, crc32(0L, buf+10, n-10), tmp), 4))
		{
			cs_log("CRC error ! wrong password ?");
			return buf[0]=0;
		}
		n=buf[9];
		memmove(buf, buf+10, n);
	}
	else
	{
		uchar *p;
		if (monitor_check_ip() == -1) {
			cs_disconnect_client(client);
			return 0;
		}
		buf[n]='\0';
		if ((p=(uchar *)strchr((char *)buf, 10)) && (bpos=n-(p-buf)-1))
		{
			memcpy(bbuf, p+1, bpos);
			n=p-buf;
			uchar *nbuf_cpy;
			if (cs_malloc(&nbuf_cpy, sizeof(nbuf))) {
				memcpy(nbuf_cpy, nbuf, sizeof(nbuf));
				add_job(client, ACTION_CLIENT_UDP, &nbuf_cpy, sizeof(nbuf));
			}
		}
	}
	buf[n]='\0';
	n=strlen(trim((char *)buf));
	if (n) client->last=time((time_t *) 0);
	return n;
}