void *freecc_connect_cli(struct struct_clicon *param) { uint8 buf[CC_MAXMSGSIZE]; uint8 data[16]; int i; struct cc_crypt_block sendblock; // crypto state block struct cc_crypt_block recvblock; // crypto state block char usr[64]; char pwd[255]; int sock = param->sock; uint32 ip = param->ip; free(param); memset(usr, 0, sizeof(usr)); memset(pwd, 0, sizeof(pwd)); // create & send random seed for(i=0; i<12; i++ ) data[i]=fast_rnd(); // Create Multics ID data[3] = (data[0]^'M') + data[1] + data[2]; data[7] = data[4] + (data[5]^'C') + data[6]; data[11] = data[8] + data[9] + (data[10]^'S'); //Create checksum for "O" cccam: for (i = 0; i < 4; i++) { data[12 + i] = (data[i] + data[4 + i] + data[8 + i]) & 0xff; } send_nonb(sock, data, 16, 100); //XOR init bytes with 'CCcam' cc_crypt_xor(data); //SHA1 SHA_CTX ctx; SHA1_Init(&ctx); SHA1_Update(&ctx, data, 16); SHA1_Final(buf, &ctx); //initialisate crypto states cc_crypt_init(&sendblock, buf, 20); cc_decrypt(&sendblock, data, 16); cc_crypt_init(&recvblock, data, 16); cc_decrypt(&recvblock, buf, 20); //debugdump(buf, 20, "SHA1 hash:"); memcpy(usr,buf,20); if ((i=recv_nonb(sock, buf, 20,3000)) == 20) { cc_decrypt(&recvblock, buf, 20); //debugdump(buf, 20, "Recv SHA1 hash:"); if ( memcmp(buf,usr,20)!=0 ) { //debugf(" cc_connect_cli(): wrong sha1 hash from client! (%s)\n",ip2string(ip)); close(sock); return NULL; } } else { //debugf(" cc_connect_cli(): recv sha1 timeout\n"); close(sock); return NULL; } // receive username if ((i=recv_nonb(sock, buf, 20,3000)) == 20) { cc_decrypt(&recvblock, buf, i); memcpy(usr,buf,20); //debugf(" cc_connect_cli(): username '%s'\n", usr); } else { //debugf(" cc_connect_cli(): recv user timeout\n"); close(sock); return NULL; } // Check for username pthread_mutex_lock(&prg.lockfreecccli); int found = 0; struct cc_client_data *cli = cfg.freecccam.client; while (cli) { if (!strcmp(cfg.freecccam.user,usr)) { if (cli->handle<=0) { found = 1; break; } else { if (cli->ip == ip) { // dont connect cc_disconnect_cli(cli); found = 1; break; } } } cli = cli->next; } if (!found) while (cli) { if (!strcmp(cfg.freecccam.user,usr)) { if (cli->handle>0) { // Check if we can disconnect idle state clients if (GetTickCount()-cli->lastecmtime > 100000) cc_disconnect_cli(cli); } if (cli->handle<=0) { found = 1; break; } } cli = cli->next; } pthread_mutex_unlock(&prg.lockfreecccli); if (!found) { debugf(" FreeCCcam: Failed to connect new client(%s)\n",ip2string(ip)); close(sock); return NULL; } // receive passwd / 'CCcam' strcpy( pwd, cfg.freecccam.pass); cc_decrypt(&recvblock, (uint8*)pwd, strlen(pwd)); if ((i=recv_nonb(sock, buf, 6,3000)) == 6) { cc_decrypt(&recvblock, buf, 6); if (memcmp( buf+1, "Ccam\0",5)) { debugf(" FreeCCcam: login failed from client(%s)\n",ip2string(ip)); close(sock); return NULL; } } else { close(sock); return NULL; } // send passwd ack memset(buf, 0, 20); memcpy(buf, "CCcam\0", 6); //debugf("Server: send ack '%s'\n",buf); cc_encrypt(&sendblock, buf, 20); send_nonb(sock, buf, 20, 100); sprintf(cli->user,"%s", ip2string(ip)); //cli->ecmnb=0; //cli->ecmok=0; memcpy(&cli->sendblock,&sendblock,sizeof(sendblock)); memcpy(&cli->recvblock,&recvblock,sizeof(recvblock)); debugf(" FreeCCcam: client(%s) connected\n",ip2string(ip)); // recv cli data memset(buf, 0, sizeof(buf)); i = cc_msg_recv( sock, &cli->recvblock, buf, 3000); if (i!=97) { debug("error recv cli data\n"); close(sock); return NULL; } // Setup Client Data // pthread_mutex_lock(&prg.lockfreecccli); memcpy( cli->nodeid, buf+24, 8); memcpy( cli->version, buf+33, 32); memcpy( cli->build, buf+65, 32 ); debugf(" FreeCCcam: client(%s) running version %s build %s\n",ip2string(ip), cli->version, cli->build); // cli->nodeid,8, cli->cardsent = 0; cli->connected = GetTickCount(); cli->lastecmtime = GetTickCount(); cli->handle = sock; cli->ip = ip; cli->chkrecvtime = 0; // pthread_mutex_unlock(&prg.lockfreecccli); // send cli data ack cc_msg_send( sock, &cli->sendblock, CC_MSG_CLI_INFO, 0, NULL); //cc_msg_send( sock, &cli->sendblock, CC_MSG_BAD_ECM, 0, NULL); int sendversion = ( (cli->version[28]=='W')&&(cli->version[29]='H')&&(cli->version[30]='O') ); cc_sendinfo_cli(cli, sendversion); //cc_msg_send( sock, &cli->sendblock, CC_MSG_BAD_ECM, 0, NULL); cli->cardsent = 1; usleep(10000); frcc_sendcards_cli(cli); pipe_wakeup( srvsocks[1] ); return cli; }
/////////////////////////////////////////////////////////////////////////////// // Connect to a server. // Return // 0: no error int cc_connect_srv(struct cs_server_data *srv, int fd) { int n; uint8 data[20]; uint8 hash[SHA_DIGEST_LENGTH]; uint8 buf[CC_MAXMSGSIZE]; char pwd[64]; // if (fd < 0) return -1; // INIT srv->progname = NULL; memset( srv->version, 0, sizeof(srv->version) ); // get init seed(random) from server if((n = recv_nonb(fd, data, 16,3000)) != 16) { static char msg[]= "Server does not return init sequence"; srv->statmsg = msg; //debugf("Client: Server (%s:%d) does not return 16 bytes\n", srv->host->name,srv->port); close(fd); return -2; } if (flag_debugnet) { debugf(" CCcam: receive server init seed (%d)\n",n); debughex(data,n); } // Check newbox int isnewbox = 0; uchar a = (data[0]^'M') + data[1] + data[2]; uchar b = data[4] + (data[5]^'C') + data[6]; uchar c = data[8] + data[9] + (data[10]^'S'); if ( (a==data[3])&&(b==data[7])&&(c==data[11]) ) isnewbox = 1; cc_crypt_xor(data); // XOR init bytes with 'CCcam' SHA_CTX ctx; SHA1_Init(&ctx); SHA1_Update(&ctx, data, 16); SHA1_Final(hash, &ctx); //debugdump(hash, sizeof(hash), "CCcam: sha1 hash:"); //initialisate crypto states cc_crypt_init(&srv->recvblock, hash, 20); cc_decrypt(&srv->recvblock, data, 16); cc_crypt_init(&srv->sendblock, data, 16); cc_decrypt(&srv->sendblock, hash, 20); cc_msg_send( fd, &srv->sendblock, CC_MSG_NO_HEADER, 20,hash); // send crypted hash to server memset(buf, 0, sizeof(buf)); memcpy(buf, srv->user, 20); //debugf(" CCcam: username '%s'\n",srv->username); cc_msg_send( fd, &srv->sendblock, CC_MSG_NO_HEADER, 20, buf); // send usr '0' padded -> 20 bytes memset(buf, 0, sizeof(buf)); memset(pwd, 0, sizeof(pwd)); //debugf("CCcam: 'CCcam' xor\n"); memcpy(buf, "CCcam", 5); strncpy(pwd, srv->pass, 63); cc_encrypt(&srv->sendblock, (uint8 *)pwd, strlen(pwd)); cc_msg_send( fd, &srv->sendblock, CC_MSG_NO_HEADER, 6, buf); // send 'CCcam' xor w/ pwd if ((n = recv_nonb(fd, data, 20,3000)) != 20) { static char msg[]= "Password ACK not received"; srv->statmsg = msg; debugf(" CCcam: login failed to Server (%s:%d), pwd ack not received (n = %d)\n",srv->host->name,srv->port, n); return -2; } cc_decrypt(&srv->recvblock, data, 20); //hexdump(data, 20, "CCcam: pwd ack received:"); if (memcmp(data, buf, 5)) { // check server response static char msg[]= "Invalid user/pass"; srv->statmsg = msg; debugf(" CCcam: login failed to Server (%s:%d), usr/pwd invalid\n",srv->host->name,srv->port); return -2; }// else debugf(" CCcam: login succeeded to Server (%s:%d)\n",srv->host->name,srv->port); srv->handle = fd; if (!cc_sendinfo_srv(srv,isnewbox)) { srv->handle = -1; static char msg[]= "Error sending client data"; srv->statmsg = msg; debugf(" CCcam: login failed to Server (%s:%d), could not send client data\n",srv->host->name,srv->port); return -3; } static char msg[]= "Connected"; srv->statmsg = msg; srv->keepalivesent = 0; srv->keepalivetime = GetTickCount(); srv->connected = GetTickCount(); srv->busy = 0; srv->lastecmoktime = 0; srv->lastecmtime = 0; srv->lastdcwtime = 0; srv->chkrecvtime = 0; memset(srv->version,0,32); pipe_wakeup( srvsocks[1] ); return 0; }