int quick_send_pkg(T_Connect *connect,T_NetHead *nethead) { int i,ch; char *p=NULL; if(nethead->PKG_LEN){ p=connect->SendBuffer+HEADPACKLENGTH; pack_encode(p,nethead->T_LEN,connect); nethead->PKG_CRC=ssh_crc32((const unsigned char *)p, nethead->T_LEN); ch=*p; } i=NetHeadPack(connect->SendBuffer,nethead,connect->family[29]); if(p) *p=ch; i=SendNet(connect->Socket,connect->SendBuffer, HEADPACKLENGTH+nethead->T_LEN,connect->MTU); //ShowLog(5,"SendPack:SendbBuffer=%s,i=%d,CRC=%08X", // connect->SendBuffer,i,nethead->PKG_CRC); if(connect->SendLen>32768) { free(connect->SendBuffer); connect->SendBuffer=0; connect->SendLen=0; } if(i<HEADPACKLENGTH+nethead->T_LEN) return i<0?SYSERR:LENGERR; else return 0; }
void enigma2_init(ENIGMA2 *ep,const char *bin_key,int len) { char rk[ROTORSZ]; if(!ep||!bin_key) return; if(len<=0) len=strlen(bin_key); enigma_init(ep->t,bin_key,len); if(len>ROTORSZ) len=ROTORSZ; memcpy(rk,bin_key,len); b_revers(rk,len); enigma_encrypt(ep->t,rk,len); enigma_init(ep->r,rk,len); ep->crc=0X7FFFFFFF & ssh_crc32((unsigned char *)ep->t,sizeof(ep->t)<<1); //ShowLog(5,"%s:crc=%d,len=%d",__FUNCTION__,ep->crc,len); return; }
/* XXX: realloc() is not checked! */ void sipwatch_add(const char *str, int len) { char *ext; lock_get(&siplua_watch->lock); ext = shm_malloc(len + 1); if (ext) { memcpy(ext, str, len); ext[len] = '\0'; siplua_watch->ext = shm_realloc(siplua_watch->ext, (siplua_watch->nb + 1) * sizeof(struct siplua_watch_ext)); siplua_watch->ext[siplua_watch->nb].str = ext; siplua_watch->ext[siplua_watch->nb].crc = ssh_crc32((unsigned char *)str, len); ++siplua_watch->nb; } lock_release(&siplua_watch->lock); }
static int sipwatch_getFlagFromExtension(const char *str, int len) { int i; u_int32_t crc; int flag = 0; crc = ssh_crc32((unsigned char *)str, len); lock_get(&siplua_watch->lock); for (i = 0; i < siplua_watch->nb; ++i) { if (siplua_watch->ext[i].crc == crc) { flag = 1; break; } } lock_release(&siplua_watch->lock); return flag; }
char *decodeprepare(char *dblabel) { char *p; DWS dw; int ret; /******************************************************************** * 用户口令解密准备 ********************************************************************/ p=getenv("KEYFILE"); if(!p||!*p) { ShowLog(1,"缺少环境变量 KEYFILE"); ret=-1; } else { ret=initdw(p,&dw); if(ret) { ShowLog(1,"Init dw %s error %d",p,ret); } } if(dblabel && *dblabel) p=dblabel; else { p=getenv("DBLABEL"); if(!p||!*p) { p=NULL; ret=-1; } } if(!ret) { unsigned crc; char *cp; crc=ssh_crc32((const unsigned char *)p,strlen(p)); cp=getdw(crc,&dw); if(!cp) { freedw(&dw); ShowLog(1,"%s:无效的 KEYID %s",__FUNCTION__,p); } else { strcpy(keyid,cp); encryptproc=encryptpass; } freedw(&dw); } return p; }
void sipwatch_delete(const char *str, int len) { int i; u_int32_t crc; crc = ssh_crc32((unsigned char *)str, len); lock_get(&siplua_watch->lock); for (i = 0; i < siplua_watch->nb; ++i) { if (siplua_watch->ext[i].crc == crc) { memmove(&siplua_watch->ext[i], &siplua_watch->ext[i + 1], siplua_watch->nb - i - 1); siplua_watch->ext = shm_realloc(siplua_watch->ext, (siplua_watch->nb - 1) * sizeof(struct siplua_watch_ext)); --siplua_watch->nb; --i; } } lock_release(&siplua_watch->lock); }
int quick_send_pkg(T_Connect *connect,T_NetHead *nethead) { int i; char *p=NULL; if(nethead->PKG_LEN){ p=connect->SendBuffer+HEADPACKLENGTH; pack_encode(p,nethead->T_LEN,connect); nethead->PKG_CRC=ssh_crc32((const unsigned char *)p, nethead->T_LEN); } i=NetHeadPack(connect->SendBuffer,nethead,connect->family[29]); if(connect->CryptFlg & DO_CRYPT) enigma2_encrypt(&connect->t,connect->SendBuffer,HEADPACKLENGTH); i=SendNet(connect->Socket,connect->SendBuffer, HEADPACKLENGTH+nethead->T_LEN,connect->MTU); if(connect->SendLen>32768) { free(connect->SendBuffer); connect->SendBuffer=0; connect->SendLen=0; } if(i<HEADPACKLENGTH+nethead->T_LEN) return i<0?SYSERR:LENGERR; else return 0; }
int RecvPack(T_Connect *connect,T_NetHead *nethead) { char headbuf[HEADPACKLENGTH+1],addr[16]; int i,n; u_int crc; char *zbuf; memset(nethead->para,0,sizeof(nethead->para)); nethead->data=NULL; peeraddr(connect->Socket,addr); i=RecvNet(connect->Socket,headbuf,HEADPACKLENGTH,connect->timeout); if(i<HEADPACKLENGTH){ if(i==TIMEOUTERR) { ShowLog(1,"%s:head TIMEOUT %d second's",__FUNCTION__, connect->timeout); return i; } ShowLog(1,"RecvPack Head LENERR i=%d,err=%d,%s",i,errno,strerror(errno)); return LENGERR; } if(connect->CryptFlg & DO_CRYPT) enigma2_decrypt(&connect->t,headbuf,HEADPACKLENGTH); i=NetHeadDispack(nethead,headbuf,connect->family[29]); if(i!=0) { ShowLog(1,"aft NetHeadDispack len=%d,PKGERR %s",i, addr); showpack(1,headbuf,HEADPACKLENGTH); return(FORMATERR); } if(!nethead->T_LEN) return 0; if(connect->CryptFlg&UNDO_ZIP) { i=nethead->T_LEN+1; } else { i=nethead->PKG_LEN+1; if(nethead->T_LEN <nethead->PKG_LEN) i+=nethead->T_LEN+1; } n=connect->RecvLen-i; if(!connect->RecvBuffer || n<0 || n>32768){ if(connect->RecvBuffer) { free(connect->RecvBuffer); connect->RecvBuffer=0; } connect->RecvLen=0; connect->RecvBuffer=malloc(i); if(!connect->RecvBuffer) return MEMERR; connect->RecvLen=i; } if(!(connect->CryptFlg&UNDO_ZIP) && nethead->T_LEN != nethead->PKG_LEN) { zbuf=connect->RecvBuffer+nethead->PKG_LEN+1; } else zbuf=connect->RecvBuffer; i=RecvNet(connect->Socket,zbuf,nethead->T_LEN,5); if(i != (nethead->T_LEN)) { if(TIMEOUTERR == i) { ShowLog(1,"%s:recv body TIMEOUT",__FUNCTION__); return i; } ShowLog(1,"%s,Recv Body T_LEN=%d i=%d,errno=%d",__FUNCTION__, nethead->T_LEN,i,errno); free(connect->RecvBuffer); connect->RecvBuffer=0; connect->RecvLen=0; return i<0?SYSERR:LENGERR; } crc=ssh_crc32((const unsigned char *)zbuf, nethead->T_LEN); if((connect->CryptFlg & CHECK_CRC) && (crc != nethead->PKG_CRC)) { ShowLog(1,"RecvPack:PKG_CRC=%08X,crc=%08X,PKG_LEN=%d,T_LEN=%d,head=%s", nethead->PKG_CRC,crc,nethead->PKG_LEN,nethead->T_LEN,headbuf); return CRCERR; } pack_decode(zbuf, nethead->T_LEN,connect); if(zbuf != connect->RecvBuffer) { size_t sz=qlz_size_decompressed(zbuf); if(nethead->T_LEN<9 || nethead->PKG_LEN != sz) { ShowLog(1,"unzip error T_LEN=%d,sz=%ld,PKG_LEN=%d,ADDR=%s",nethead->T_LEN, sz,nethead->PKG_LEN,addr); return FORMATERR; } i=qlz_decompress(zbuf,connect->RecvBuffer); if(i!=nethead->PKG_LEN) { ShowLog(1,"RecvPack:PKG_LEN=%d,T_LEN=%d,unzip_size=%d", nethead->PKG_LEN,nethead->T_LEN,i); return LENGERR; } } //else if(connect->CryptFlg & UNDO_ZIP) // ShowLog(5,"%s:UNDO_ZIP %s,T_LEN=%d,PKG_LEN=%d,data=%s",__FUNCTION__, // *connect->Host?connect->Host:"Client",nethead->T_LEN,nethead->PKG_LEN,connect->RecvBuffer); if(!(connect->CryptFlg & UNDO_ZIP)) connect->RecvBuffer[nethead->PKG_LEN]=0; nethead->data=connect->RecvBuffer; return 0; }
int login(T_Connect *conn,T_NetHead *NetHead) { int ret,crc; char tmp[200]; char *cp,*key; char tmp1[1024],cliaddr[20]; DWS dw; struct login_s logrec; ENIGMA egm; FILE *fd; T_SRV_Var *up; GDA *gp; //u_int e[RSALEN],m[RSALEN]; up=(T_SRV_Var *)conn->Var; gp=(GDA *)up->var; StrAddr(NetHead->O_NODE,cliaddr); ShowLog(5,"%s:TCB:%d Client IP Addr=%s,Net_login %s",__FUNCTION__,up->TCB_no,cliaddr,NetHead->data); net_dispack(&logrec,NetHead->data,login_type); strcpy(gp->devid,logrec.devid); sprintf(gp->ShowID,"%s:%s:%d",logrec.devid,cliaddr,up->TCB_no); mthr_showid_add(up->tid,gp->ShowID); conn->MTU=NetHead->ERRNO1; cp=getenv("KEYFILE"); if(!cp||!*cp) { strcpy(tmp1,"缺少环境变量 KEYFILE"); errret: ShowLog(1,"%s:Error %s",__FUNCTION__,tmp1); NetHead->ERRNO1=-1; NetHead->ERRNO2=-1; NetHead->PKG_REC_NUM=0; NetHead->data=tmp1; NetHead->PKG_LEN=strlen(NetHead->data); SendPack(conn,NetHead); return 0; // fail } /* read key */ crc=0; reopen: ret=initdw(cp,&dw); if(ret) { if((errno==24)&& (++crc<5)) { sleep(15); goto reopen; } sprintf(tmp1,"Init dw error %d",ret); goto errret; } crc=ssh_crc32((unsigned char *)logrec.devid,strlen(logrec.devid)); key=getdw(crc,&dw); if(!key) { freedw(&dw); sprintf(tmp1,"无效的 DEVID"); goto errret; } //ShowLog(5,"getdw key=%s",key); enigma1_init(egm,key); /* check CA */ memset(gp->operid,0,sizeof(gp->operid)); cp=getenv("CADIR"); if(!cp||!*cp) cp="."; if(strcmp(gp->devid,"REGISTER")) { strncpy(gp->operid,logrec.uid,sizeof(gp->operid)-1); sprintf(tmp,"%s/%s.CA",cp,logrec.devid); //ShowLog(5,"CAfile=%s,key=%s",tmp,key); fd=fopen(tmp,"r"); if(!fd) { if(errno==2) { crc=strlen(logrec.CA); frenz_encode(egm,logrec.CA,crc); byte_a64(tmp1,logrec.CA,crc); //ShowLog(5,"CA=%s",tmp1); fd=fopen(tmp,"w"); if(!fd) { sprintf(tmp1,"write %s err=%d",tmp,errno); err1: freedw(&dw); goto errret; } fprintf(fd,"%s\n",tmp1); fclose(fd); } else { sprintf(tmp1,"open CAfile %s err=%d",tmp,errno); goto err1; } } else { fgets(tmp1,sizeof(logrec.CA),fd); fclose(fd); TRIM(tmp1); ret=a64_byte(tmp,tmp1); frenz_decode(egm,tmp,ret); tmp[ret]=0; if(strcmp(tmp,logrec.CA)) { sprintf(tmp1,"CA 错误"); ShowLog(1,"%s:%s CA=%s log=%s len=%d",__FUNCTION__,tmp1,tmp,logrec.CA,ret); goto err1; } } } else { //未注册客户端注册 char *p; char *keyD; /* REGISTER label|CA|devfile|CHK_Code| */ ShowLog(2,"REGISTER %s",logrec.uid); if(!*logrec.uid) { sprintf(tmp1,"REGSTER is empty!"); goto err1; } //uid=devfile crc=0xFFFF&gencrc((unsigned char *)logrec.uid,strlen(logrec.uid)); //pwd=CHK_Code sscanf(logrec.pwd,"%04X",&ret); ret &= 0xFFFF; if(ret != crc) { sprintf(tmp1,"REGISTER:devfile CHK Code error! ");//, crc,ret); goto err1; } p=stptok(logrec.uid,logrec.devid,sizeof(logrec.devid),".");//logrec.devid=准备注册的DEVID crc=ssh_crc32((unsigned char *)logrec.devid,strlen(logrec.devid)); keyD=getdw(crc,&dw); if(!keyD) { sprintf(tmp1,"注册失败,%s:没有这个设备!", logrec.devid); goto err1; } enigma1_init(egm,keyD); sprintf(tmp,"%s/%s.CA",cp,logrec.devid); ShowLog(5,"REGISTER:%s",tmp); if(0!=(fd=fopen(tmp,"r"))) { fgets(tmp1,81,fd); fclose(fd); TRIM(tmp1); ret=a64_byte(tmp,tmp1); frenz_decode(egm,tmp,ret); tmp[ret]=0; if(strcmp(tmp,logrec.CA)) { sprintf(tmp1,"注册失败,%s 已被注册,使用中。", logrec.devid); goto err1; } } else if(errno != 2) { sprintf(tmp1,"CA 错误"); goto err1; } /*把设备特征码写入文件*/ fd=fopen(tmp,"w"); if(fd) { int len=strlen(logrec.CA); frenz_encode(egm,logrec.CA,len); byte_a64(tmp1,logrec.CA,len); fprintf(fd,"%s\n",tmp1); fclose(fd); } else ShowLog(1,"net_login:REGISTER open %s for write,err=%d,%s", tmp,errno,strerror(errno)); freedw(&dw); sprintf(tmp,"%s/%s",cp,logrec.uid); fd=fopen(tmp,"r"); if(!fd) { sprintf(tmp1,"REGISTER 打不开文件 %s err=%d,%s", logrec.CA,errno,strerror(errno)); goto errret; } fgets(logrec.uid,sizeof(logrec.uid),fd); TRIM(logrec.uid); ShowLog(2,"REGISTER open %s",tmp); fclose(fd); cp=tmp1; cp+=sprintf(cp,"%s|%s|", logrec.devid,logrec.uid); cp+=sprintf(cp,"%s|",rsecstrfmt(tmp,now_sec(),YEAR_TO_SEC)); NetHead->data=tmp1; NetHead->PKG_LEN=strlen(NetHead->data); NetHead->ERRNO1=0; NetHead->ERRNO2=0; NetHead->PKG_REC_NUM=0; SendPack(conn,NetHead); return -1; } //未注册客户端注册完成 freedw(&dw); up->poolno=get_scpool_no(NetHead->D_NODE); if(up->poolno<0) { sprintf(tmp1,"非法的D_NODE %d",NetHead->D_NODE); goto errret; } ret=get_s_connect(up->TCB_no,up->poolno,&gp->server,login_finish); if(ret==0) return login_finish(conn,NetHead); else if(ret==1) return -5; sprintf(tmp1,"错误的参数"); goto errret; }
static void crc_update(u_int32_t *a, u_int32_t b) { b ^= *a; *a = ssh_crc32((u_char *)&b, sizeof(b)); }
int ssh_packet_send1(ssh_session session) { unsigned int blocksize = (session->current_crypto ? session->current_crypto->out_cipher->blocksize : 8); uint32_t currentlen = ssh_buffer_get_len(session->out_buffer) + sizeof(uint32_t); char padstring[32] = {0}; int rc = SSH_ERROR; uint32_t finallen; uint32_t crc; uint8_t padding; SSH_LOG(SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen); /* TODO FIXME #ifdef WITH_ZLIB if (session->current_crypto && session->current_crypto->do_compress_out) { if (compress_buffer(session, session->out_buffer) < 0) { goto error; } currentlen = ssh_buffer_get_len(session->out_buffer); } #endif */ padding = blocksize - (currentlen % blocksize); if (session->current_crypto) { ssh_get_random(padstring, padding, 0); } else { memset(padstring, 0, padding); } finallen = htonl(currentlen); SSH_LOG(SSH_LOG_PACKET, "%d bytes after comp + %d padding bytes = %d bytes packet", currentlen, padding, ntohl(finallen)); if (ssh_buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) { goto error; } if (ssh_buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) { goto error; } crc = ssh_crc32((char *)ssh_buffer_get(session->out_buffer) + sizeof(uint32_t), ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t)); if (ssh_buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) { goto error; } #ifdef DEBUG_CRYPTO ssh_print_hexa("Clear packet", ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); #endif /* session->out_buffer should have more than sizeof(uint32_t) bytes in it as required for ssh_packet_encrypt */ ssh_packet_encrypt(session, (unsigned char *)ssh_buffer_get(session->out_buffer) + sizeof(uint32_t), ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t)); #ifdef DEBUG_CRYPTO ssh_print_hexa("encrypted packet",ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); #endif rc=ssh_socket_write(session->socket, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); if(rc== SSH_ERROR) { goto error; } session->send_seq++; if (ssh_buffer_reinit(session->out_buffer) < 0) { rc = SSH_ERROR; } error: return rc; /* SSH_OK, AGAIN or ERROR */ }
int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user) { void *packet = NULL; int to_be_read; size_t processed=0; uint32_t padding; uint32_t crc; uint32_t len, buffer_len; ssh_session session=(ssh_session)user; switch (session->packet_state){ case PACKET_STATE_INIT: memset(&session->in_packet, 0, sizeof(PACKET)); if (session->in_buffer) { if (ssh_buffer_reinit(session->in_buffer) < 0) { goto error; } } else { session->in_buffer = ssh_buffer_new(); if (session->in_buffer == NULL) { goto error; } } /* must have at least enough bytes for size */ if(receivedlen < sizeof(uint32_t)){ return 0; } memcpy(&len,data,sizeof(uint32_t)); processed += sizeof(uint32_t); /* len is not encrypted */ len = ntohl(len); if (len > MAX_PACKET_LEN) { ssh_set_error(session, SSH_FATAL, "read_packet(): Packet len too high (%u %.8x)", len, len); goto error; } SSH_LOG(SSH_LOG_PACKET, "Reading a %d bytes packet", len); session->in_packet.len = len; session->packet_state = PACKET_STATE_SIZEREAD; /* FALL THROUGH */ case PACKET_STATE_SIZEREAD: len = session->in_packet.len; /* SSH-1 has a fixed padding lenght */ padding = 8 - (len % 8); to_be_read = len + padding; if(to_be_read + processed > receivedlen){ /* wait for rest of packet */ return processed; } /* it is _not_ possible that to_be_read be < 8. */ packet = (char *)data + processed; if (ssh_buffer_add_data(session->in_buffer,packet,to_be_read) < 0) { goto error; } processed += to_be_read; #ifdef DEBUG_CRYPTO ssh_print_hexa("read packet:", ssh_buffer_get(session->in_buffer), ssh_buffer_get_len(session->in_buffer)); #endif if (session->current_crypto) { /* * We decrypt everything, missing the lenght part (which was * previously read, unencrypted, and is not part of the buffer */ buffer_len = ssh_buffer_get_len(session->in_buffer); if (buffer_len > 0) { int rc; rc = ssh_packet_decrypt(session, ssh_buffer_get(session->in_buffer), buffer_len); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Packet decrypt error"); goto error; } } } #ifdef DEBUG_CRYPTO ssh_print_hexa("read packet decrypted:", ssh_buffer_get(session->in_buffer), ssh_buffer_get_len(session->in_buffer)); #endif SSH_LOG(SSH_LOG_PACKET, "%d bytes padding", padding); if(((len + padding) != ssh_buffer_get_len(session->in_buffer)) || ((len + padding) < sizeof(uint32_t))) { SSH_LOG(SSH_LOG_RARE, "no crc32 in packet"); ssh_set_error(session, SSH_FATAL, "no crc32 in packet"); goto error; } memcpy(&crc, (unsigned char *)ssh_buffer_get(session->in_buffer) + (len+padding) - sizeof(uint32_t), sizeof(uint32_t)); ssh_buffer_pass_bytes_end(session->in_buffer, sizeof(uint32_t)); crc = ntohl(crc); if (ssh_crc32(ssh_buffer_get(session->in_buffer), (len + padding) - sizeof(uint32_t)) != crc) { #ifdef DEBUG_CRYPTO ssh_print_hexa("crc32 on",ssh_buffer_get(session->in_buffer), len + padding - sizeof(uint32_t)); #endif SSH_LOG(SSH_LOG_RARE, "Invalid crc32"); ssh_set_error(session, SSH_FATAL, "Invalid crc32: expected %.8x, got %.8x", crc, ssh_crc32(ssh_buffer_get(session->in_buffer), len + padding - sizeof(uint32_t))); goto error; } /* pass the padding */ ssh_buffer_pass_bytes(session->in_buffer, padding); SSH_LOG(SSH_LOG_PACKET, "The packet is valid"); /* TODO FIXME #ifdef WITH_ZLIB if(session->current_crypto && session->current_crypto->do_compress_in){ decompress_buffer(session,session->in_buffer); } #endif */ session->recv_seq++; /* We don't want to rewrite a new packet while still executing the packet callbacks */ session->packet_state = PACKET_STATE_PROCESSING; ssh_packet_parse_type(session); /* execute callbacks */ ssh_packet_process(session, session->in_packet.type); session->packet_state = PACKET_STATE_INIT; if(processed < receivedlen){ int rc; /* Handle a potential packet left in socket buffer */ SSH_LOG(SSH_LOG_PACKET,"Processing %" PRIdS " bytes left in socket buffer", receivedlen-processed); rc = ssh_packet_socket_callback1((char *)data + processed, receivedlen - processed,user); processed += rc; } return processed; case PACKET_STATE_PROCESSING: SSH_LOG(SSH_LOG_PACKET, "Nested packet processing. Delaying."); return 0; } error: session->session_state=SSH_SESSION_STATE_ERROR; return processed; }
int RecvPack(T_Connect *connect,T_NetHead *nethead) { char headbuf[HEADPACKLENGTH+1],addr[16]; int i,n; u_int crc; char *zbuf; n_zero(PARANUM,nethead->para); nethead->data=0; memset(headbuf,0,sizeof(headbuf)); i=RecvNet(connect->Socket,headbuf,HEADPACKLENGTH,connect->timeout); //free SendBuffer if(i<HEADPACKLENGTH){ if(i==TIMEOUTERR) { ShowLog(1,"%s:head TIMEOUT %d second's",__FUNCTION__, connect->timeout); return i; } ShowLog(1,"RecvPack Head LENERR i=%d,err=%d,%s",i,errno,strerror(errno)); return LENGERR; } headbuf[HEADPACKLENGTH]=0; i=NetHeadDispack(nethead,headbuf,connect->family[29]); if(i!=0) { peeraddr(connect->Socket,addr); ShowLog(1,"aft NetHeadDispack len=%d,PKGERR %s:%.48s",i, addr,headbuf); showpack(1,headbuf,HEADPACKLENGTH); return(FORMATERR); } if(!nethead->T_LEN) return 0; i=((connect->CryptFlg&UNDO_ZIP)?nethead->T_LEN:nethead->PKG_LEN)+1; n=connect->RecvLen-i; if(n<0 || n>SDBC_BLKSZ){ if( connect->RecvBuffer) free(connect->RecvBuffer); connect->RecvBuffer=0; connect->RecvLen=0; connect->RecvBuffer=malloc(i); if(!connect->RecvBuffer) return MEMERR; connect->RecvLen=i; } if(!(connect->CryptFlg&UNDO_ZIP) && nethead->T_LEN != nethead->PKG_LEN) { zbuf=malloc(nethead->T_LEN); if(!zbuf) { RecvNet(connect->Socket,connect->RecvBuffer,nethead->T_LEN,3); return MEMERR; } } else zbuf=connect->RecvBuffer; i=RecvNet(connect->Socket,zbuf,nethead->T_LEN,3); if(i < (nethead->T_LEN)) { if(TIMEOUTERR == i) { ShowLog(1,"%s:recv body TIMEOUT",__FUNCTION__); return i; } if(zbuf!=connect->RecvBuffer) free(zbuf); ShowLog(1,"%s,Recv Body T_LEN=%d i=%d,errno=%d",__FUNCTION__, nethead->T_LEN,i,errno); free(connect->RecvBuffer); connect->RecvBuffer=0; connect->RecvLen=0; return i<0?SYSERR:LENGERR; } crc=ssh_crc32((const unsigned char *)zbuf, nethead->T_LEN); if((connect->CryptFlg & CHECK_CRC) && (crc != nethead->PKG_CRC)) { ShowLog(1,"RecvPack:PKG_CRC=%08X,crc=%08X,PKG_LEN=%d,T_LEN=%d,head=%s", nethead->PKG_CRC,crc,nethead->PKG_LEN,nethead->T_LEN,headbuf); return CRCERR; } pack_decode(zbuf, nethead->T_LEN,connect); if(zbuf != connect->RecvBuffer) { if(nethead->T_LEN<9 || nethead->PKG_LEN != qlz_size_decompressed(zbuf)) { ShowLog(1,"unzip error T_LEN=%d,ADDR=%s",nethead->T_LEN, addr); return FORMATERR; } i=qlz_decompress(zbuf,connect->RecvBuffer); free(zbuf); if(i!=nethead->PKG_LEN) { ShowLog(1,"RecvPack:PKG_LEN=%d,T_LEN=%d,unzip_size=%d", nethead->PKG_LEN,nethead->T_LEN,i); return LENGERR; } } connect->RecvBuffer[nethead->PKG_LEN]=0; nethead->data=connect->RecvBuffer; return 0; }
static int packet_send1(SSH_SESSION *session) { unsigned int blocksize = (session->current_crypto ? session->current_crypto->out_cipher->blocksize : 8); u32 currentlen = buffer_get_len(session->out_buffer) + sizeof(u32); char padstring[32] = {0}; int rc = SSH_ERROR; u32 finallen; u32 crc; u8 padding; enter_function(); ssh_log(session,SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen); /* TODO FIXME #if defined(HAVE_LIBZ) && defined(WITH_LIBZ) if (session->current_crypto && session->current_crypto->do_compress_out) { if (compress_buffer(session, session->out_buffer) < 0) { goto error; } currentlen = buffer_get_len(session->out_buffer); } #endif */ padding = blocksize - (currentlen % blocksize); if (session->current_crypto) { ssh_get_random(padstring, padding, 0); } else { memset(padstring, 0, padding); } finallen = htonl(currentlen); ssh_log(session, SSH_LOG_PACKET, "%d bytes after comp + %d padding bytes = %d bytes packet", currentlen, padding, ntohl(finallen)); if (buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) { goto error; } if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(u32)) < 0) { goto error; } crc = ssh_crc32(buffer_get(session->out_buffer) + sizeof(u32), buffer_get_len(session->out_buffer) - sizeof(u32)); if (buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) { goto error; } #ifdef DEBUG_CRYPTO ssh_print_hexa("Clear packet", buffer_get(session->out_buffer), buffer_get_len(session->out_buffer)); #endif packet_encrypt(session, buffer_get(session->out_buffer) + sizeof(u32), buffer_get_len(session->out_buffer) - sizeof(u32)); #ifdef DEBUG_CRYPTO ssh_print_hexa("encrypted packet",buffer_get(session->out_buffer), buffer_get_len(session->out_buffer)); #endif if (ssh_socket_write(session->socket, buffer_get(session->out_buffer), buffer_get_len(session->out_buffer)) == SSH_ERROR) { goto error; } rc = packet_flush(session, 0); session->send_seq++; if (buffer_reinit(session->out_buffer) < 0) { rc = SSH_ERROR; } error: leave_function(); return rc; /* SSH_OK, AGAIN or ERROR */ }
/* a slighty modified packet_read2() for SSH-1 protocol */ static int packet_read1(SSH_SESSION *session) { void *packet = NULL; int rc = SSH_ERROR; int to_be_read; u32 padding; u32 crc; u32 len; enter_function(); if(!session->alive) { goto error; } switch (session->packet_state){ case PACKET_STATE_INIT: memset(&session->in_packet, 0, sizeof(PACKET)); if (session->in_buffer) { if (buffer_reinit(session->in_buffer) < 0) { goto error; } } else { session->in_buffer = buffer_new(); if (session->in_buffer == NULL) { goto error; } } rc = ssh_socket_read(session->socket, &len, sizeof(u32)); if (rc != SSH_OK) { goto error; } rc = SSH_ERROR; /* len is not encrypted */ len = ntohl(len); if (len > MAX_PACKET_LEN) { ssh_set_error(session, SSH_FATAL, "read_packet(): Packet len too high (%u %.8x)", len, len); goto error; } ssh_log(session, SSH_LOG_PACKET, "Reading a %d bytes packet", len); session->in_packet.len = len; session->packet_state = PACKET_STATE_SIZEREAD; case PACKET_STATE_SIZEREAD: len = session->in_packet.len; /* SSH-1 has a fixed padding lenght */ padding = 8 - (len % 8); to_be_read = len + padding; /* it is _not_ possible that to_be_read be < 8. */ packet = malloc(to_be_read); if (packet == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); goto error; } rc = ssh_socket_read(session->socket, packet, to_be_read); if(rc != SSH_OK) { SAFE_FREE(packet); goto error; } rc = SSH_ERROR; if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) { SAFE_FREE(packet); goto error; } SAFE_FREE(packet); #ifdef DEBUG_CRYPTO ssh_print_hexa("read packet:", buffer_get(session->in_buffer), buffer_get_len(session->in_buffer)); #endif if (session->current_crypto) { /* * We decrypt everything, missing the lenght part (which was * previously read, unencrypted, and is not part of the buffer */ if (packet_decrypt(session, buffer_get(session->in_buffer), buffer_get_len(session->in_buffer)) < 0) { ssh_set_error(session, SSH_FATAL, "Packet decrypt error"); goto error; } } #ifdef DEBUG_CRYPTO ssh_print_hexa("read packet decrypted:", buffer_get(session->in_buffer), buffer_get_len(session->in_buffer)); #endif ssh_log(session, SSH_LOG_PACKET, "%d bytes padding", padding); if(((len + padding) != buffer_get_rest_len(session->in_buffer)) || ((len + padding) < sizeof(u32))) { ssh_log(session, SSH_LOG_RARE, "no crc32 in packet"); ssh_set_error(session, SSH_FATAL, "no crc32 in packet"); goto error; } memcpy(&crc, buffer_get_rest(session->in_buffer) + (len+padding) - sizeof(u32), sizeof(u32)); buffer_pass_bytes_end(session->in_buffer, sizeof(u32)); crc = ntohl(crc); if (ssh_crc32(buffer_get_rest(session->in_buffer), (len + padding) - sizeof(u32)) != crc) { #ifdef DEBUG_CRYPTO ssh_print_hexa("crc32 on",buffer_get_rest(session->in_buffer), len + padding - sizeof(u32)); #endif ssh_log(session, SSH_LOG_RARE, "Invalid crc32"); ssh_set_error(session, SSH_FATAL, "Invalid crc32: expected %.8x, got %.8x", crc, ssh_crc32(buffer_get_rest(session->in_buffer), len + padding - sizeof(u32))); goto error; } /* pass the padding */ buffer_pass_bytes(session->in_buffer, padding); ssh_log(session, SSH_LOG_PACKET, "The packet is valid"); /* TODO FIXME #if defined(HAVE_LIBZ) && defined(WITH_LIBZ) if(session->current_crypto && session->current_crypto->do_compress_in){ decompress_buffer(session,session->in_buffer); } #endif */ session->recv_seq++; session->packet_state=PACKET_STATE_INIT; leave_function(); return SSH_OK; } /* switch */ ssh_set_error(session, SSH_FATAL, "Invalid state into packet_read1(): %d", session->packet_state); error: leave_function(); return rc; }
/* Insert padding. Initialized to zero in packet_start1() */ padding = 8 - len % 8; if (!send_context.plaintext) { cp = buffer_ptr(&outgoing_packet); for (i = 0; i < padding; i++) { if (i % 4 == 0) rnd = arc4random(); cp[7 - i] = rnd & 0xff; rnd >>= 8; } } buffer_consume(&outgoing_packet, 8 - padding); /* Add check bytes. */ checksum = ssh_crc32(buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet)); put_u32(buf, checksum); buffer_append(&outgoing_packet, buf, 4); #ifdef PACKET_DEBUG fprintf(stderr, "packet_send plain: "); buffer_dump(&outgoing_packet); #endif /* Append to output. */ put_u32(buf, len); buffer_append(&output, buf, 4); cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet));
void crc_update(word32 * a, word32 b) { b ^= *a; *a = ssh_crc32((unsigned char *) &b, sizeof(b)); }