Author Topic: Delphi newcamd source  (Read 2447 times)

0 Members and 1 Guest are viewing this topic.

Offline bordan

  • Sr. Member
  • ****
  • Posts: 189
Delphi newcamd source
« on: October 02, 2009, 01:06:13 PM »

Ako ste delphi programer kontaktirajte me i ukjucite se u novim projectima .

unit module-newcamd-0rginal_c;



interface

uses
   Windows, Messages, SysUtils, Classes;



const CWS_NETMSGSIZE   = 272;
{$EXTERNALSYM CWS_NETMSGSIZE}

type
   uint8 = type Byte;
   {$EXTERNALSYM uint8}
   Puint8 = ^uint8;
   {$EXTERNALSYM Puint8}
type
   uint16 = type WORD;
   {$EXTERNALSYM uint16}
   Puint16 = ^uint16;
   {$EXTERNALSYM Puint16}
type
   uint32 = type WORD;
   {$EXTERNALSYM uint32}
   Puint32 = ^uint32;
   {$EXTERNALSYM Puint32}
type
   LongIntuint64 = type Cardinal;
   {$EXTERNALSYM LongIntuint64}
   PLongIntuint64 = ^LongIntuint64;
   {$EXTERNALSYM PLongIntuint64}

const CWS_FIRSTCMDNO   = $e0;
{$EXTERNALSYM CWS_FIRSTCMDNO}
type const
   (**** Convert following enum types to constants. ****
    **** e.g. v1 = n, where v1 is constant and n is the value ****
    **** if a constant has a value, do not assign a new value ****)

begin
 MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
 MSG_CLIENT_2_SERVER_LOGIN_ACK,
 MSG_CLIENT_2_SERVER_LOGIN_NAK,
 MSG_CARD_DATA_REQ,
 MSG_CARD_DATA,
 MSG_SERVER_2_CLIENT_NAME,
 MSG_SERVER_2_CLIENT_NAME_ACK,
 MSG_SERVER_2_CLIENT_NAME_NAK,
 MSG_SERVER_2_CLIENT_LOGIN,
 MSG_SERVER_2_CLIENT_LOGIN_ACK,
 MSG_SERVER_2_CLIENT_LOGIN_NAK,
 MSG_ADMIN,
 MSG_ADMIN_ACK,
 MSG_ADMIN_LOGIN,
 MSG_ADMIN_LOGIN_ACK,
 MSG_ADMIN_LOGIN_NAK,
 MSG_ADMIN_COMMAND,
 MSG_ADMIN_COMMAND_ACK,
 MSG_ADMIN_COMMAND_NAK,
 MSG_KEEPALIVE = CWS_FIRSTCMDNO + $1d
 end; net_msg_type
    = type ;
   {$EXTERNALSYM }
   P = ^;
   {$EXTERNALSYM P}t
   (**** Convert following enum types to constants. ****
    **** e.g. v1 = n, where v1 is constant and n is the value ****
    **** if a constant has a value, do not assign a new value ****)

begin
 COMMTYPE_CLIENT,
 COMMTYPE_SERVER
 end; comm_type
    = type ;
   {$EXTERNALSYM }
   P = ^;
   {$EXTERNALSYM P}EQ_SIZE   2
   uchar   *req:=0;
integer ncd_proto:=NCD_AUTO;

integer network_message_send(integer handle, uint16 *netMsgId, uint8 *buffer,
                integer len, uint8 *deskey, comm_type_t commType,
                ushort sid)
begin
  netbuf: array[0..CWS_NETMSGSIZE-1] of uint8;
 integer head_size;
 head_size := (ncd_proto = NCD_524)?8:12;

 if (len < 3 or len + head_size > CWS_NETMSGSIZE or handle < 0) then
  result:= -1;
 buffer[1] := (buffer[1] and $f0) or (((len - 3) shr 8) and $0f);
 buffer[2] := (len - 3) and $ff;
 memcpy(netbuf+head_size, buffer, len);
 len:= mod + head_size;
 if (netMsgId) then begin
  case(commType) of
  begin
COMMTYPE_CLIENT:
   (netMsgId):= mod + 1;
      break;
COMMTYPE_SERVER:
   if( *netMsgId := $FFFE ) *netMsgId = 0; // èëè 0xFFFF ?
   break;
   end;
  netbuf[2] := (netMsgId) shr 8;
  netbuf[3] := (netMsgId) and $ff;
  end;
 else
  netbuf[2] := netbuf[3] = 0;
 FillChar(netbuf+4, 0, (ncd_proto := NCD_524)?4:8);
 if( sid ) then begin
  netbuf[(ncd_proto := NCD_524)?6:4] = (uchar((sid shr 8); //sid
  netbuf[(ncd_proto := NCD_524)?7:5] = (uchar((sid);
  end;
 netbuf[0] := (len - 2) shr 8;
 netbuf[1] := (len - 2) and $ff;
 cs_ddump(netbuf, len, 'send mod d bytes to mod s', len, remote_txt());
 if ((len = des_encrypt(netbuf, len, deskey)) < 0) then
  result:= -1;
 netbuf[0] := (len - 2) shr 8;
 netbuf[1] := (len - 2) and $ff;
 result:= send(handle, netbuf, len, 0);
 end;

integer network_message_receive(integer handle, uint16 *netMsgId, uint8 *buffer,
                  uint8 *deskey, comm_type_t commType)
begin
 integer len, ncd_off, msgid;
  netbuf: array[0..CWS_NETMSGSIZE-1] of uint8;
 integer returnLen;

 if ( not buffer or handle < 0) then
  result:= -1;
 len := recv(handle, netbuf, 2, 0);
 cs_debug('nmr(): len:= mod d, errno= mod d', len, (len = -1)?errno:0);
 if ( not len) then begin
  cs_debug('nmr: 1 result:= 0');
  network_tcp_connection_close(handle);
  result:= 0;
  end;
 if (len <> 2) then begin
  cs_debug('nmr: len <> 2');
  network_tcp_connection_close(handle);
  result:= -1;
  end;
 if (((netbuf[0] shl 8) or netbuf[1]) > CWS_NETMSGSIZE - 2) then begin
  cs_debug('nmr: 1 result:= -1');
  result:= -1;
  end;

 len := recv(handle, netbuf+2, (netbuf[0] shl 8) or netbuf[1], 0);
 if ( not len) then begin
  cs_debug('nmr: 2 result:= 0');
  result:= 0;
  end;
 if (len <> ((netbuf[0] shl 8) or netbuf[1])) then begin
  cs_debug('nmr: 2 result:= -1');
  result:= -1;
  end;
 len:= mod + 2;
 if ((len = des_decrypt(netbuf, len, deskey)) < 11 ) begin  // 15(newcamd525) then or 11 ???
  cs_debug('nmr: can't decrypt, invalid des key?');
  sleep(2);
  result:= -1;
  end;
 //cs_ddump(netbuf, len, "nmr: decrypted data, len=%d", len);
 msgid := (netbuf[2] shl 8) or netbuf[3];

 if( ncd_proto = NCD_AUTO ) then begin
  // auto detect
  integer l5 := (((netbuf[13] and $0f) shl 8) or netbuf[14]) + 3;
  integer l4 := (((netbuf[9] and $0f) shl 8) or netbuf[10]) + 3;
 
  if( (l5<=len-12) and ((netbuf[12] and $F0) = $E0 or (netbuf[12] and $F0) = $80) )
   ncd_proto := NCD_525;
  else if( (l4<=len-8) and ((netbuf[8] and $F0) = $E0 or (netbuf[9] and $F0) = $80) )
   ncd_proto := NCD_524;
  else begin
   cs_debug('nmr: 4 result:= -1');
   result:= -1;
   end;

  cs_debug('nmr: autodetect: newcamd52 mod d used', (ncd_proto := NCD_525)?5:4);
  end;
 
 ncd_off:=(ncd_proto = NCD_525)?4:0;

 returnLen := (((netbuf[9+ncd_off] and $0f) shl 8) or netbuf[10+ncd_off]) + 3;
 if ( returnLen > (len-(8+ncd_off)) ) then begin
  cs_debug('nmr: 4 result:= -1');
  result:= -1;
  end;

// cs_ddump(netbuf, len, "nmr: decrypted data");
 if (netMsgId) then
 begin
  case (commType) of
  begin
COMMTYPE_SERVER:
   *netMsgId := msgid;
   break;

COMMTYPE_CLIENT:
   //if (*netMsgId != ((netbuf[2] << 8) | netbuf[3])) {
    cs_debug('nmr: netMsgId:= mod d, from server= mod d, ', *netMsgId, msgid );
    //return -2;
   //}
   break;

  default:
   cs_debug('nmr: 5 result:= -1');
   result:= -1;
   break;
   end;
  end;
 case(commType) of
 begin
COMMTYPE_SERVER:
  buffer[0]:=(ncd_proto = NCD_525)?netbuf[4]:netbuf[6]; // sid
  buffer[1]:=(ncd_proto = NCD_525)?netbuf[5]:netbuf[7];
    break;
COMMTYPE_CLIENT:
  buffer[0]:=netbuf[2]; // msgid
  buffer[1]:=netbuf[3];
  break;
  end;
 
 memcpy(buffer+2, netbuf+(8+ncd_off), returnLen);
 result:= returnLen+2;
 end;

procedure network_cmd_no_data_send(handle: integer; var netMsgId: uint16; cmd: net_msg_type_t; var deskey: uint8; commType: comm_type_t)
begin
  buffer: array[0..CWS_NETMSGSIZE-1] of uint8;

 buffer[0] := cmd; buffer[1] = 0;
 network_message_send(handle, netMsgId, buffer, 3, deskey, commType, 0);
 end;

integer network_cmd_no_data_receive(integer handle, uint16 *netMsgId,
                    uint8 *deskey, comm_type_t commType)
begin
  buffer: array[0..CWS_NETMSGSIZE-1] of uint8;

 if (network_message_receive(handle, netMsgId, buffer, deskey, commType) <> 3+2) then
  result:= -1;
 result:= buffer[2];
 end;

integer
connect_nonb(integer sockfd, struct sockaddr *saptr, socklen_t salen, integer nsec)
begin
 integer               flags, n, error;
 socklen_t        len;
 fd_set           rset, wset;
 struct timeval   tval;

 flags := fcntl(sockfd, F_GETFL, 0);
 fcntl(sockfd, F_SETFL, flags or O_NONBLOCK);

 error := 0;
 cs_debug('conn_nb 1 (fd:= mod d)', sockfd);
 
 if ( (n = connect(sockfd, saptr, salen)) < 0) then begin
  if( errno = EALREADY ) then begin
   cs_debug('conn_nb in progress, errno:= mod d', errno);
   result:= (-1);
   end;
  else if( errno = EISCONN ) then begin
   cs_debug('conn_nb already connected, errno:= mod d', errno);
   goto done;
   end;
  cs_debug('conn_nb 2 (fd:= mod d)', sockfd);
  if (errno <> EINPROGRESS) then begin
   cs_debug('conn_nb 3 (fd:= mod d)', sockfd);
   result:= (-1);
   end;
  end;

 (* Do whatever we want while the connect is taking place. *)
 if (n = 0) then
  goto done;   (* connect completed immediately *)

 FD_ZERO( and rset);
 FD_SET(sockfd, and rset);
 wset := rset;
 tval.tv_sec := nsec;
 tval.tv_usec := 0;

 if ( (n = select(sockfd+1, and rset, and wset, 0, nsec ? and tval : 0)) = 0) then begin
   //close(sockfd);      // timeout
   cs_debug('conn_nb 4 (fd:= mod d)', sockfd);
   errno := ETIMEDOUT;
   result:= (-1);
  end;

 cs_debug('conn_nb 5 (fd:= mod d)', sockfd);

 if (FD_ISSET(sockfd, and rset) or FD_ISSET(sockfd, and wset)) then begin
  cs_debug('conn_nb 6 (fd:= mod d)', sockfd);
  len := SizeOf(error);
  if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, and error, and len) < 0) then begin
   cs_debug('conn_nb 7 (fd:= mod d)', sockfd);
   result:= (-1);         // Solaris pending error
   end;
  end; else begin
  cs_debug('conn_nb 8 (fd:= mod d)', sockfd);
  result:= -2;
  end;

done:
 cs_debug('conn_nb 9 (fd:= mod d)', sockfd);
 fcntl(sockfd, F_SETFL, flags);   (* restore file status flags *)

 if (error) then begin
  cs_debug('conn_nb 10 (fd:= mod d)', sockfd);
  //close(sockfd);      /* just in case */
  errno := error;
  result:= (-1);
  end;
 result:=(0);
 end;

integer network_tcp_connection_open(uint8 *hostname, uint16 port)
begin
 integer flags;
 if( connect_nonb(client[cs_idx].udp_fd, then
   (struct sockaddr ) and client[cs_idx].udp_sa,
   SizeOf(client[cs_idx].udp_sa), 5) < 0)
 begin
  cs_log('connect(fd:= mod d) failed: (errno= mod d)', client[cs_idx].udp_fd, errno);
  result:= -1;
  end;
 flags := fcntl(client[cs_idx].udp_fd, F_GETFL, 0);
 flags and :=~ O_NONBLOCK;
 fcntl(client[cs_idx].udp_fd, F_SETFL, flags );

 result:= client[cs_idx].udp_fd;
 end;

procedure newcamd_reply_ka()
begin
 if( not client[cs_idx].udp_fd ) then
 begin
  cs_debug('invalid client fd:= mod d', client[cs_idx].udp_fd);
  Exit;
  end;
 cs_debug('send keep_alive');
 network_cmd_no_data_send(client[cs_idx].udp_fd, and client[cs_idx].ncd_msgid,
              MSG_KEEPALIVE, client[cs_idx].ncd_skey,
              COMMTYPE_SERVER);
 end;

integer connect_newcamd_server()
begin
 uint32 i;
  buf: array[0..CWS_NETMSGSIZE-1] of uint8;
  keymod: array[0..14-1] of uint8;
 uint8 *key;
 integer handle:=0;

 uint32 index;
 uint8 *passwdcrypt;
 uint8 login_answer;
 integer bytes_received;

 if(reader[ridx].device[0] = 0 or reader[ridx].r_pwd[0] = 0 or then
   reader[ridx].r_usr[0] = 0 or reader[ridx].r_port = 0)
  result:= -5;

 // 1. Connect
 //
 handle := network_tcp_connection_open((uint8 )reader[ridx].device, reader[ridx].r_port);
 if(handle < 0) then result:= -1;
 
 // 2. Get init sequence
 //
 reader[ridx].ncd_msgid := 0;
 if( read(handle, keymod, SizeOf(keymod)) <> SizeOf(keymod)) then begin
  cs_log('server does not result:= 14 bytes');
  network_tcp_connection_close(handle);
  result:= -2;
  end;
 cs_ddump(keymod, 14, 'server init sequence:');
 key := des_login_key_get(keymod, reader[ridx].ncd_key, 14);

 // 3. Send login info
 //
 index := 3;
 buf[0] := MSG_CLIENT_2_SERVER_LOGIN;
 buf[1] := 0;
 StrCopy((Char )buf+index, reader[ridx].r_usr);
 passwdcrypt := (uint8*)__md5_crypt(reader[ridx].r_pwd, "$1$abcdefgh$");
 index:= mod + strlen(reader[ridx].r_usr)+1;
StrCopy((function )buf+index, ( Char )passwdcrypt): Char;

 //cs_debug("login to server %s:%d user=%s, pwd=%s, len=%d", reader[ridx].device,
 //     reader[ridx].r_port, reader[ridx].r_usr, reader[ridx].r_pwd,
 //     index+strlen(passwdcrypt)+1);
 network_message_send(handle, 0, buf, index+strlen((Char )passwdcrypt)+1, key,
            COMMTYPE_CLIENT, $8888);

 // 3.1 Get login answer
 //
 login_answer=network_cmd_no_data_receive(handle, and reader[ridx].ncd_msgid,
                      key, COMMTYPE_CLIENT);
 if( login_answer = MSG_CLIENT_2_SERVER_LOGIN_NAK ) then
 begin
  cs_log('login failed for user ' mod s'', reader[ridx].r_usr);
  network_tcp_connection_close(handle);
  result:= -3;
  end;
 if( login_answer <> MSG_CLIENT_2_SERVER_LOGIN_ACK ) then
 begin
  cs_log('expected MSG_CLIENT_2_SERVER_LOGIN_ACK ( mod 02X), received mod 02X',
       MSG_CLIENT_2_SERVER_LOGIN_ACK, login_answer);
  network_tcp_connection_close(handle);
  result:= -3;
  end;

 // 4. Send MSG_CARD_DATE_REQ
 //
 key := des_login_key_get(reader[ridx].ncd_key, passwdcrypt, strlen((Char )passwdcrypt));

 network_cmd_no_data_send(handle, and reader[ridx].ncd_msgid, MSG_CARD_DATA_REQ,
              key, COMMTYPE_CLIENT);
 bytes_received = network_message_receive(handle, and reader[ridx].ncd_msgid, buf,
                      key, COMMTYPE_CLIENT);
 if( bytes_received < 16 or buf[2] <> MSG_CARD_DATA ) then begin
  cs_log('expected MSG_CARD_DATA ( mod 02X), received mod 02X',
       MSG_CARD_DATA, buf[2]);
  network_tcp_connection_close(handle);
  result:= -4;
  end;

 // 5. Parse CAID and PROVID(s)
 //
 reader[ridx].caid[0] := (ushort(((buf[4+2] shl 8) or buf[5+2]);
 memcpy( and reader[ridx].hexserial, buf+6+2, 8);
 cs_log('Newcamd Server: mod s: mod d - UserID: mod i', reader[ridx].device, reader[ridx].r_port, buf[3+2]);
 cs_log('CAID: mod 04X - UA: mod 02X mod 02X mod 02X mod 02X mod 02X mod 02X mod 02X mod 02X - Provider # mod reader: array[0..ridx-1] of i',.caid[0], reader[ridx].hexserial[0], reader[ridx].hexserial[1], reader[ridx].hexserial[2], reader[ridx].hexserial[3], reader[ridx].hexserial[4], reader[ridx].hexserial[5], reader[ridx].hexserial[6], reader[ridx].hexserial[7], buf[14+2]);
 reader[ridx].nprov := buf[14+2];
 FillChar(reader[ridx].prid, $ff, SizeOf(reader[ridx].prid));
 for (i:=0; i < reader[ridx].nprov; i++) begin
  reader[ridx].availkeys[0] := 1;
  reader[ridx].prid[0] := buf[15+2+11*i];
  reader[ridx].prid[1] := buf[16+2+11*i];
  reader[ridx].prid[2] := buf[17+2+11*i];
  memcpy( reader: array[0..ridx-1] of and.sa, buf+22+2+11*i, 4); // the 4 first bytes are not read
  cs_log('Provider ID: mod 02X mod 02X mod 02X - SA: mod 02X mod 02X mod 02X mod reader: array[0..ridx-1] of 02X',.prid[1], reader[ridx].prid[2], reader[ridx].prid[3], reader[ridx].sa[0], reader[ridx].sa[1], reader[ridx].sa[2], reader[ridx].sa[3]);
  end;
 memcpy(reader[ridx].ncd_skey, key, 16);

 // 6. Set connected info
 //
 reader[ridx].tcp_connected:=1;
 reader[ridx].last_g := reader[ridx].last_s = time((time_t )0);

// cs_log("last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
 
 // !!! Only after connect() on client[cs_idx].udp_fd (Linux)
 pfd:=client[cs_idx].udp_fd;  

 result:= 0;
 end;

integer newcamd_connect()
begin
 if ( not reader[ridx].tcp_connected and connect_newcamd_server() < 0 ) then result:= 0;
 if ( not client[cs_idx].udp_fd) then result:= 0;

 result:= 1;
 end;


integer newcamd_send(uchar *buf, integer ml, ushort sid)
begin
 if( not newcamd_connect() ) result:= (-1) then ;

 //cs_ddump(buf, ml, "send %d bytes to %s", ml, remote_txt());
 result:=(network_message_send(client[cs_idx].udp_fd, and reader[ridx].ncd_msgid,
     buf, ml, reader[ridx].ncd_skey, COMMTYPE_CLIENT, sid));
 end;

integer newcamd_recv(uchar *buf, integer l)
begin
 integer rc, rs;
 if (is_server) then
  rs=network_message_receive(client[cs_idx].udp_fd,
                and client[cs_idx].ncd_msgid, buf,
                client[cs_idx].ncd_skey, COMMTYPE_SERVER);
 else
 begin
  if ( not client[cs_idx].udp_fd) result:= (-1) then ;
  rs=network_message_receive(client[cs_idx].udp_fd,
                and reader[ridx].ncd_msgid,buf,
                reader[ridx].ncd_skey, COMMTYPE_CLIENT);
  end;
 if (rs<5) rc:=(-1) then ;
 else rc:=rs;
 cs_ddump(buf, rs, 'received mod d bytes from mod s', rs, remote_txt());
 client[cs_idx].last := time((time_t ) 0);
 if( rc = -1 ) then
    if (rs > 0) then
  cs_log('packet to small ( mod d bytes)', rs);
  else
   cs_log('Connection closed to mod s', remote_txt());
 result:=(rc);
 end;

WORD seed;
uchar fast_rnd()
begin
 WORD offset := 12923;
 WORD multiplier := 4079;

 seed := seed * multiplier + offset;
 result:= (uchar((seed mod $FF);
 end;

FILTER mk_user_au_ftab(integer au)
begin
 integer i,j,found;
 FILTER filt;
 FILTER *pufilt;

 filt.caid := reader[au].caid[0];
 if (filt.caid := 0) then filt.caid = client[cs_idx].ftab.filts[0].caid;
 filt.nprids := 0;
 FillChar( and filt.prids, 0, SizeOf(filt.prids));
 pufilt := and client[cs_idx].ftab.filts[0];

 for( i:=0; i  filt.prids[filt.nprids++] := b2i(3, and reader[au].prid[1]);

 for( i:=0; i begin
  for( j:=found=0; ( not found) and (j   if (pufilt^.prids := filt.prids[j]) then found=1;
  if( not found ) then
   filt.prids[filt.nprids++] := pufilt^.prids;
  end;

 result:= filt;
 end;

FILTER mk_user_ftab()
begin
 FILTER *psfilt := 0;
 FILTER filt;
 integer port_idx,i,j,k,c;

 filt.caid := 0;
 filt.nprids := 0;
 FillChar( and filt.prids, 0, SizeOf(filt.prids));

 port_idx := client[cs_idx].port_idx;
 psfilt := and cfg^.ncd_ptab.ports[port_idx].ftab.filts[0];

 // 1. CAID
 // search server CAID in client CAID
 for( c:=i=0; i begin
  integer ctab_caid;
  ctab_caid := client[cs_idx].ctab.caid and client[cs_idx].ctab.mask;
  if( ctab_caid ) then c:= mod + 1;
  if( psfilt^.caid = ctab_caid ) then
  begin
   filt.caid:=ctab_caid;
   break;
   end;
  end;
 if( c and not filt.caid ) then
 begin
  cs_log('no valid CAID found in CAID for user ' mod s'', client[cs_idx].usr);
  result:= filt;
  end;

 // search CAID in client IDENT
 cs_debug('client[ mod d]. mod s nfilts= mod d, filt.caid= mod 04X', cs_idx,
      client[cs_idx].usr, client[cs_idx].ftab.nfilts, filt.caid);

 if( not filt.caid and client[cs_idx].ftab.nfilts ) then
 begin
  integer fcaids;
  for( i:=fcaids=0; i  begin
   ushort ucaid:=client[cs_idx].ftab.filts.caid;
   if( ucaid ) then fcaids:= mod + 1;
   if( ucaid and psfilt^.caid = ucaid ) then
   begin
    filt.caid := ucaid;
    break;
    end;
   end;
  if( fcaids = client[cs_idx].ftab.nfilts and not filt.caid ) then
  begin
   cs_log('no valid CAID found in IDENT for user ' mod s'', client[cs_idx].usr);
   //cs_disconnect_client();
   result:= filt;
   end;
  end;
 // empty client CAID - use server CAID
 if( not filt.caid ) then filt.caid:=psfilt^.caid;

 // 2. PROVID
 if( not client[cs_idx].ftab.nfilts ) then
 begin
  integer r,f, add;
  for (i:=0; i   // use server PROVID(s) (and only those which are in user's groups)
   add := 0;
   for (r:=0; not add and r   if (reader[r].grp and client[cs_idx].grp) then begin
    if ( not reader[r].ftab.nfilts) then begin
     if (reader[r].typ and R_IS_NETWORK) then add := 1;
     for (j:=0; not add and j      if (b2i(3, and reader[r].prid[j][1]) := psfilt^.prids) then add = 1;
     end; else begin
     for (j:=0; not add and j      ulong rcaid := reader[r].ftab.filts[j].caid;
      if ( not rcaid or rcaid = filt.caid) then begin
       for (k:=0; not add and k        if (reader[r].ftab.filts[j].prids[k] := psfilt^.prids) then add = 1;
       end;
      end;
     end;
    end;
    end;
   if (add) then filt.prids[filt.nprids++] := psfilt^.prids;
   end;
  result:= filt;
  end;

 // search in client IDENT
  for( j:=0; j  begin
   ulong ucaid := client[cs_idx].ftab.filts[j].caid;
   cs_debug('client caid # mod d: mod 04X', j, ucaid);
   if( not ucaid or ucaid = filt.caid ) then
   begin
   for (i:=0; i   begin
    cs_debug('search server provid # mod d: mod 06X', i, psfilt^.prids);
    if( client[cs_idx].ftab.filts[j].nprids ) then
    begin
     for( k:=0; k      if (client[cs_idx].ftab.filts[j].prids[k] = psfilt^.prids) then
       filt.prids[filt.nprids++]:=client[cs_idx].ftab.filts[j].prids[k];
     end; else begin
     filt.prids[filt.nprids++] := psfilt^.prids;
    // allow server PROVID(s) if no PROVID(s) specified in IDENT
     end;
    end;
   end;
  end;
 
 if( not filt.nprids ) then
 begin
  cs_log('no valid PROVID(s) found in CAID for user ' mod s'', client[cs_idx].usr);
  //cs_disconnect_client();
  end;

 result:= filt;
 end;

integer newcamd_auth_client(in_addr_t ip)
begin
  integer i, ok := 0;
  uchar *usr:=0, *pwd=0;
  struct s_auth *account;
   buf: array[0..14-1] of uchar;
  uchar *key:=0;
  uint8 *passwdcrypt := 0;
  integer au;

  // make random 14 bytes
  seed := (function) time((time_t)0): WORD;
  for( i:=0; i<14; i++ ) buf=fast_rnd();

  // send init sequence
  send(client[cs_idx].udp_fd, buf, 14, 0);
  key := des_login_key_get(buf, cfg^.ncd_key, 14);
  memcpy(client[cs_idx].ncd_skey, key, 16);
  client[cs_idx].ncd_msgid := 0;

  i:=process_input(mbuf, SizeOf(mbuf), cfg^.cmaxidle);
  if ( i>0 ) then
    begin
    if( mbuf[2] <> MSG_CLIENT_2_SERVER_LOGIN ) then
      begin
      cs_debug('expected MSG_CLIENT_2_SERVER_LOGIN ( mod 02X), received mod 02X',
      MSG_CLIENT_2_SERVER_LOGIN, mbuf[2]);
      if(req) then
        begin
        free(req);
        req:=0;
         end;
      cs_exit(0);
       end;
    usr:=mbuf+5;
    pwd:=usr+strlen((Char )usr)+1;
    //cs_debug("usr=%s,pwd=%s", usr, pwd);
     end;
  else
    begin
    cs_debug('bad client login request');
    if(req) then
      begin
      free(req);
      req:=0;
       end;
    cs_exit(0);
     end;

  for (ok:=0, account=cfg^.account; (usr) and (account) and ( not ok); account=account^.next)
    begin
    cs_debug('account^.usr:= mod s', account^.usr);
    if (StrComp((Char )usr, account^.usr) = 0) then
      begin
      passwdcrypt := (uint8*)__md5_crypt(account->pwd, "$1$abcdefgh$");
      cs_debug('account^.pwd:= mod s', passwdcrypt);
if (StrComp((Char )pwd, ( Char )passwdcrypt) = 0) then
        begin
        client[cs_idx].crypted:=1;
        cs_auth_client(account, 0);
        cs_log('user mod s authenticated successfully (using client mod 02X mod 02X)', mbuf: array[0..0-1] of usr,, mbuf[1]);
        ok := 1;
        break;
         end;
      else
        begin
        cs_log('user mod s is providing a wrong password (using client mod 02X mod 02X)', mbuf: array[0..0-1] of usr,, mbuf[1]);
         end;
       end;
     end;
   
  if ( not ok and not account) then
    begin
    cs_log('user mod s is trying to connect but doesnt exist not (using client mod 02X mod 02X)', mbuf: array[0..0-1] of usr,, mbuf[1]);
    usr := 0;
     end;

  if (ok) then
    begin
    au := client[cs_idx].au;
    if (au <> -1) then
      begin
      if (cfg^.ncd_ptab.ports[client[cs_idx].port_idx].ftab.filts[0].caid <> reader[au].caid[0] then
        and cfg^.ncd_ptab.ports[client[cs_idx].port_idx].ftab.filts[0].caid <> reader[au].ftab.filts[0].caid)
        begin
        cs_log('AU wont be used on this port ^. disable AU');
        au := -1;
         end;
      else if (reader[au].card_system <= 0 and not (reader[au].typ and R_IS_CASCADING)) then
        begin
        // Init for AU enabled card not finished, reject Client
        ok:=0;
        au := -2; // Flag zur Logausgabe
         end;
      else
        begin
        cs_log('AU mod d for user mod s',au,usr);
         end;
       end;
    else
      begin
      cs_log('AU disabled for user mod s',usr);
       end;
     end;

  network_cmd_no_data_send(client[cs_idx].udp_fd, and client[cs_idx].ncd_msgid,
       (ok)?MSG_CLIENT_2_SERVER_LOGIN_ACK:MSG_CLIENT_2_SERVER_LOGIN_NAK,
       client[cs_idx].ncd_skey, COMMTYPE_SERVER);

  // we need to add a test to make sure all card reader are ready before allowing more interaction with the user.
  // cfg->ncd_ptab.ports[client[cs_idx].port_idx].ftab.filts[0].caid old the CAID for this port
  // we need to check all ready for a match and check if they are ready
  // if they arent ready, disconnect the user.
  // it will reconnect in a few second.
 
  if (ok) then
    begin
    FILTER pufilt_noau := ( 0 );
    FILTER *pufilt := 0;

    key := des_login_key_get(cfg^.ncd_key, passwdcrypt, strlen((Char )passwdcrypt));
    memcpy(client[cs_idx].ncd_skey, key, 16);

    i:=process_input(mbuf, SizeOf(mbuf), cfg^.cmaxidle);
    if( i>0 ) then
      begin
      integer j,len:=15;
      if( mbuf[2] <> MSG_CARD_DATA_REQ) then
        begin
        cs_debug('expected MSG_CARD_DATA_REQ ( mod 02X), received mod 02X',
             MSG_CARD_DATA_REQ, mbuf[2]);
        if(req) then
          begin
          free(req); req:=0;
           end;
        cs_exit(0);
         end;

      client[cs_idx].ftab.filts[0] := mk_user_ftab();
      pufilt := and client[cs_idx].ftab.filts[0];
     
      if (au <> -1) then
        begin
        Byte equal := 1;

        // remember user filter
        memcpy( and pufilt_noau, pufilt, SizeOf(FILTER));

        client[cs_idx].ftab.filts[0] := mk_user_au_ftab(au);
        pufilt := and client[cs_idx].ftab.filts[0];

        // check if user filter CAID and PROVID is the same as CAID and PROVID of the AU reader
     
        if ((pufilt^.caid <> pufilt_noau.caid)) then
          begin
          // cs_log("CAID server: %04X, CAID card: %04X, not equal, AU disabled",pufilt_noau.caid,pufilt->caid);
          // equal = 0;
           end;
     
        for( j:=0; equal and j          begin
          if (pufilt^.prids[j] <> pufilt_noau.prids[j]) then
            begin
            // cs_log("PROVID%d server: %04X, PROVID%d card: %04X, not equal, AU disabled",j,pufilt_noau.prids[j],j,pufilt->prids[j]);
            //weird// equal = 0;
             end;
           end;
       
        if ( not equal) then
          begin
          // Not equal -> AU must set to disabled -> set back to user filter
          memcpy(pufilt, and pufilt_noau, SizeOf(FILTER));
          au := -1;
           end;
         end;

      client[cs_idx].ftab.nfilts := 1;
      mbuf[0] := MSG_CARD_DATA;
      mbuf[1] := $00;
      mbuf[2] := $00;

      // AU always set to true because some clients cannot handle "non-AU"
      // For security reason don't send the real hexserial (see below)
      // if a non-AU-client sends an EMM-request it will be thrown away
      // (see function "newcamd_process_emm")
      //mbuf[3] = 1;
      if( au <> -1 ) then
        mbuf[3] := 1;
      else
        mbuf[3] := cs_idx+10; // Unique user number

      mbuf[4] := (uchar((pufilt^.caid shr 8);
      mbuf[5] := (uchar((pufilt^.caid);
      mbuf[6] := $00;
      mbuf[7] := $00;

      if (au <> -1) then
        begin
        if (((pufilt^.caid shr 8) = $17) or ((pufilt^.caid shr 8) = $06))  // Betacrypt or 1rd3t0
          begin
          // only 4 Bytes Hexserial for newcamd clients (Hex Base + Hex Serial)
          // first 2 Byte always 00
          mbuf[8]:=$00; //serial only 4 bytes
          mbuf[9]:=$00; //serial only 4 bytes
          // 1 Byte Hex Base (see reader-1rd3t0.c how this is stored in "reader[au].hexserial")
          mbuf[10]:=reader[au].hexserial[3];
          // 3 Bytes Hex Serial (see reader-1rd3t0.c how this is stored in "reader[au].hexserial")
          mbuf[11]:=reader[au].hexserial[0];
          mbuf[12]:=reader[au].hexserial[1];
          mbuf[13]:=reader[au].hexserial[2];
           end;
        else if (((pufilt^.caid shr 8) = $05) or ((pufilt^.caid shr 8) = $0D))
          begin
          mbuf[8] := $00;
          mbuf[9] := reader[au].hexserial[0];
          mbuf[10] := reader[au].hexserial[1];
          mbuf[11] := reader[au].hexserial[2];
          mbuf[12] := reader[au].hexserial[3];
          mbuf[13] := reader[au].hexserial[4];
           end;
        else
          begin
          mbuf[8] := reader[au].hexserial[0];
          mbuf[9] := reader[au].hexserial[1];
          mbuf[10] := reader[au].hexserial[2];
          mbuf[11] := reader[au].hexserial[3];
          mbuf[12] := reader[au].hexserial[4];
          mbuf[13] := reader[au].hexserial[5];
           end;
         end;
      else
        begin
        client[cs_idx].au := -1;
        mbuf[8] := $00;
        mbuf[9] := $00;
        mbuf[10] := $00;
        mbuf[11] := $00;
        mbuf[12] := $00;
        mbuf[13] := $00;
        // send "faked" Hexserial to client
        (*
        if (((pufilt^.caid >= $1700) and (pufilt^.caid <= $1799)) or // Betacrypt
        ((pufilt^.caid >= $0600) and (pufilt^.caid <= $0699)))  // 1rd3t0
          begin
          mbuf[6] := $00;
          mbuf[7] := $00;
          mbuf[8] := $00;
          mbuf[9] := $00;
          mbuf[10] := fast_rnd();
          mbuf[11] := fast_rnd();
          mbuf[12] := fast_rnd();
          mbuf[13] := fast_rnd();
           end;
         else
          begin
          mbuf[6] := fast_rnd();
          mbuf[7] := fast_rnd();
          mbuf[8] := fast_rnd();
          mbuf[9] := fast_rnd();
          mbuf[10] := fast_rnd();
          mbuf[11] := fast_rnd();
          mbuf[12] := fast_rnd();
          mbuf[13] := fast_rnd();
           end;
        *)
         end;

      mbuf[14] := pufilt^.nprids;
      for( j:=0; j        begin
        if ((pufilt^.caid >= $0600) and (pufilt^.caid <= $0699))  // 1rd3t0
          begin
          mbuf[15+11*j] := 0;
          mbuf[16+11*j] := 0;
          mbuf[17+11*j] := j;
           end;
        else
          begin
          mbuf[15+11*j] := (uchar((pufilt^.prids[j] shr 16);
          mbuf[16+11*j] := (uchar((pufilt^.prids[j] shr 8);
          mbuf[17+11*j] := (uchar((pufilt^.prids[j]);
           end;
        mbuf[18+11*j] := $00;
        mbuf[19+11*j] := $00;
        mbuf[20+11*j] := $00;
        mbuf[21+11*j] := $00;
        if( au <> -1 ) then
          begin // check if user provid from IDENT exists on card
          integer k, found;
          ulong rprid;
          found:=0;
          if( pufilt^.caid = reader[au].caid[0] ) then
            begin
            for( k:=0; (k              begin
              rprid:=b2i(3, and reader[au].prid[k][1]);
              if( rprid = pufilt^.prids[j] ) then
                begin
                if ((pufilt^.caid >= $0600) and (pufilt^.caid <= $0699))  // 1rd3t0
                  begin
                  mbuf[22+11*j] := reader[au].prid[k][0];
                  mbuf[23+11*j] := reader[au].prid[k][1];
                  mbuf[24+11*j] := reader[au].prid[k][2];
                  mbuf[25+11*j] := reader[au].prid[k][3];
                   end;
                else
                  begin
                  mbuf[22+11*j] := reader[au].sa[k][0];
                  mbuf[23+11*j] := reader[au].sa[k][1];
                  mbuf[24+11*j] := reader[au].sa[k][2];
                  mbuf[25+11*j] := reader[au].sa[k][3];
                   end;
                found:=1;
                break;
                 end;
               end;
             end;
          if( not found ) then
            begin
            mbuf[22+11*j] := $00;
            mbuf[23+11*j] := $00;
            mbuf[24+11*j] := $00;
            mbuf[25+11*j] := $00;
             end;
           end;
        else
          begin
          if ((pufilt^.caid >= $0600) and (pufilt^.caid <= $0699))  // 1rd3t0
            begin
            mbuf[22+11*j] := $00;
            mbuf[23+11*j] := (uchar((pufilt^.prids[j] shr 16);
            mbuf[24+11*j] := (uchar((pufilt^.prids[j] shr 8);
            mbuf[25+11*j] := (uchar((pufilt^.prids[j]);
             end;
          else
            begin
            mbuf[22+11*j] := $00;
            mbuf[23+11*j] := $00;
            mbuf[24+11*j] := $00;
            mbuf[25+11*j] := $00;
             end;
           end;
        len+:=11;
         end;

      if( network_message_send(client[cs_idx].udp_fd, and client[cs_idx].ncd_msgid, mbuf, len, key, COMMTYPE_SERVER, 0 ) <0 ) then
        begin
        if(req) then
          begin
          free(req);
          req:=0;
           end;
        cs_exit(0);
         end;
       end;
     end;
  else
    begin
    if (au = -2) then
      cs_auth_client(0, 'Init for AU enabled card not finished');
    else
      cs_auth_client(0, usr ? 'login failure' : 'no such user');
    if(req) then
      begin
      free(req);
      req:=0;
       end;
    cs_exit(0);
     end;
 end;

procedure newcamd_send_dcw(var er: ECM_REQUEST)
begin
 integer len;
 ushort cl_msgid;
 
 if ( not client[cs_idx].udp_fd) then begin
  cs_debug('ncd_send_dcw: error: client[cs_idx].udp_fd:= mod d', client[cs_idx].udp_fd);
  Exit;
  end;
 memcpy( and cl_msgid, req+(er^.cpti*REQ_SIZE), 2);   // get client ncd_msgid + 0x8x
 mbuf[0] := er^.ecm[0];
 if( client[cs_idx].ftab.filts[0].nprids = 0 or er^.rc>3 (*not found*)) then
 begin
  len:=3;
  mbuf[1] := mbuf[2] = $00;
  end;
 else
 begin
  len := 19;
  mbuf[1] := mbuf[2] = $10;
  memcpy(mbuf+3, er^.cw, 16);
  end;

 cs_debug('ncd_send_dcw: er^.cpti:= mod d, cl_msgid= mod d, mod 02X', er^.cpti, cl_msgid, mbuf[0]);

 network_message_send(client[cs_idx].udp_fd, and cl_msgid, mbuf, len,
            client[cs_idx].ncd_skey, COMMTYPE_SERVER, 0);
 end;

procedure newcamd_process_ecm(var buf: uchar; l: integer)
begin
 integer pi;
 ECM_REQUEST *er;
 if ( not (er=get_ecmtask())) then begin
  Exit;
  end;
 // save client ncd_msgid
 memcpy(req+(er^.cpti*REQ_SIZE), and client[cs_idx].ncd_msgid, 2);   
 cs_debug('ncd_process_ecm: er^.cpti= mod d, cl_msgid= mod d, mod 02X", er^.cpti,
      client[cs_idx].ncd_msgid, buf[2]);
 er^.l:=buf[4]+3;
 er^.srvid := (buf[0] shl 8) or buf[1];
 er^.caid := 0;
 pi := client[cs_idx].port_idx;
 if( cfg^.ncd_ptab.nports and cfg^.ncd_ptab.nports >= pi ) then
  er^.caid:=cfg^.ncd_ptab.ports[pi].ftab.filts[0].caid;
 memcpy(er^.ecm, buf+2, er^.l);
 get_cw(er);
 end;

procedure newcamd_process_emm(var buf: uchar; l: integer)
begin
 integer au, ok:=1;
 ushort caid;

 FillChar( and epg, 0, SizeOf(epg));
 au:=client[cs_idx].au;

 // if client is not allowed to do AU just send back the OK-answer to
 // the client and do nothing else with the received data
 if ((au>=0) and (au<=CS_MAXREADER)) then
 begin
 epg.l:=buf[2]+3;
 caid := client[cs_idx].ftab.filts[0].caid;
 epg.caid[0] := (uchar((caid shr 8);
 epg.caid[1] := (uchar((caid);
(* if (caid == 0x0500)
 begin
  ushort emm_head;

  emm_head := (buf[0] shl 8) or buf[1];
  case( emm_head ) of
  begin
$8e70: // EMM-S
    memcpy(epg.hexserial+1, buf+3, 4);
    epg.hexserial[4]:=reader[au].hexserial[4];
    break;
$8870: // EMM-U
$8c70: // confidential ?
   default:
    cs_log("unsupported emm cType: mod 04X", emm_head);
    ok:=0;
   end;
  if( not ok ) cs_log("only