# gbox module patch against svn trunk # by mostly.harmless@azet.sk Index: module-gbox.c =================================================================== --- module-gbox.c (revision 5961) +++ module-gbox.c (working copy) @@ -5,6 +5,8 @@ #include #include +#define LOVER 0x1b + #include "module-datastruct-llist.h" #include "algo/minilzo.h" @@ -46,7 +48,7 @@ uchar key[4]; uchar ver; uchar type; - int32_t ecm_idx; + uint16_t exp_seq; // hello seq int32_t hello_expired; int32_t hello_initial; uchar cws[16]; @@ -70,127 +72,127 @@ uchar checksums[14]; }; -static const uchar sbox[] = { - 0x25, 0x38, 0xd4, 0xcd, 0x17, 0x7a, 0x5e, 0x6c, - 0x52, 0x42, 0xfe, 0x68, 0xab, 0x3f, 0xf7, 0xbe, - 0x47, 0x57, 0x71, 0xb0, 0x23, 0xc1, 0x26, 0x6c, - 0x41, 0xce, 0x94, 0x37, 0x45, 0x04, 0xa2, 0xea, - 0x07, 0x58, 0x35, 0x55, 0x08, 0x2a, 0x0f, 0xe7, - 0xac, 0x76, 0xf0, 0xc1, 0xe6, 0x09, 0x10, 0xdd, - 0xc5, 0x8d, 0x2e, 0xd9, 0x03, 0x9c, 0x3d, 0x2c, - 0x4d, 0x41, 0x0c, 0x5e, 0xde, 0xe4, 0x90, 0xae -}; - #pragma GCC diagnostic ignored "-Wunused-parameter" -static void gbox_encrypt_stage1(uchar *buf, int32_t l, uchar *key) -{ - int32_t i; - for (i = 31; i >= 0; i--) { - uchar tmp; +//////////////////////////////////////////////////////////////////////////////// +// GBOX BUFFER ENCRYPTION/DECRYPTION (thanks to dvbcrypt@gmail.com) +//////////////////////////////////////////////////////////////////////////////// - tmp = key[3]; - int32_t j; - for (j = 3; j > 0; j--) - key[j] = (key[j - 1] << 7) + (key[j] >> 1); - key[0] = (tmp << 7) + (key[0] >> 1); +unsigned char Lookup_Table[0x40] = { + 0x25,0x38,0xD4,0xCD,0x17,0x7A,0x5E,0x6C,0x52,0x42,0xFE,0x68,0xAB,0x3F,0xF7,0xBE, + 0x47,0x57,0x71,0xB0,0x23,0xC1,0x26,0x6C,0x41,0xCE,0x94,0x37,0x45,0x04,0xA2,0xEA, + 0x07,0x58,0x35,0x55,0x08,0x2A,0x0F,0xE7,0xAC,0x76,0xF0,0xC1,0xE6,0x09,0x10,0xDD, + 0xC5,0x8D,0x2E,0xD9,0x03,0x9C,0x3D,0x2C,0x4D,0x41,0x0C,0x5E,0xDE,0xE4,0x90,0xAE + }; - buf[i + 1 - ((i + 1) & 0xf8)] += sbox[((key[i + 1 - ((i + 1) & 0xfc)] ^ buf[i - (i & 0xf8)]) >> 2) & 0x3f] * 2; - buf[i + 1 - ((i + 1) & 0xf8)] ^= sbox[(buf[i - (i & 0xf8)] - key[i + 1 - ((i + 1) & 0xfc)]) & 0x3f]; - buf[i + 1 - ((i + 1) & 0xf8)] += key[i - (i & 0xfc)]; - } -} -static void gbox_encrypt_stage2(uchar *buf, int32_t l, uchar *key) +void gbox_encrypt8(unsigned char *buffer, unsigned char *pass) { - int32_t i, j; + int passcounter; + int bufcounter; + unsigned char temp; - for (i = 0; i < 4; i++) - for (j = 7; j >= 0; j--) { - uchar tmp; - - tmp = key[3]; - int32_t k; - for (k = 3; k > 0; k--) - key[k] = (key[k - 1] << 7) + (key[k] >> 1); - key[0] = (tmp << 7) + (key[0] >> 1); - - buf[(j + 1) & 7] -= sbox[(buf[j] >> 2) & 0x3f]; - buf[(j + 1) & 7] ^= sbox[(buf[j] - key[(j + 1) & 3]) & 0x3f]; - buf[(j + 1) & 7] -= key[j & 3]; + for(passcounter=0; passcounter<4; passcounter++) + for(bufcounter=7; bufcounter>=0; bufcounter--) + { + temp = ( buffer[bufcounter]>>2); + temp = pass[3]; + pass[3] = (pass[3]/2)+(pass[2]&1)*0x80; + pass[2] = (pass[2]/2)+(pass[1]&1)*0x80; + pass[1] = (pass[1]/2)+(pass[0]&1)*0x80; + pass[0] = (pass[0]/2)+(temp &1)*0x80; + buffer[(bufcounter+1) & 7] = buffer[ (bufcounter+1) & 7 ] - Lookup_Table[ (buffer[bufcounter]>>2) & 0x3F ]; + buffer[(bufcounter+1) & 7] = Lookup_Table[ ( buffer[bufcounter] - pass[(bufcounter+1) & 3] ) & 0x3F ] ^ buffer[ (bufcounter+1) & 7 ]; + buffer[(bufcounter+1) & 7] = buffer[ (bufcounter+1) & 7 ] - pass[(bufcounter & 3)]; } } -static void gbox_decrypt_stage1(uchar *buf, int32_t l, uchar *key) +void gbox_decrypt8(unsigned char *buffer,unsigned char *pass) { - int32_t i; + unsigned char temp; + int bufcounter; + int passcounter; + for( passcounter=3; passcounter>=0; passcounter--) + for( bufcounter=0; bufcounter<=7; bufcounter++) { + buffer[(bufcounter+1)&7] = pass[bufcounter&3] + buffer[(bufcounter+1)&7]; + temp = buffer[bufcounter] - pass[(bufcounter+1)&3]; + buffer[(bufcounter+1)&7] = Lookup_Table[temp &0x3F] ^ buffer[(bufcounter+1)&7]; + temp = buffer[bufcounter] >> 2; + buffer[(bufcounter+1)&7] = Lookup_Table[temp & 0x3F] + buffer[(bufcounter+1)&7]; - for (i = 0; i < 32; i++) { - uchar tmp; + temp = pass[0] & 0x80; + pass[0] = ( (pass[1]&0x80)>>7 ) + (pass[0]<<1); + pass[1] = ( (pass[2]&0x80)>>7 ) + (pass[1]<<1); + pass[2] = ( (pass[3]&0x80)>>7 ) + (pass[2]<<1); + pass[3] = ( temp>>7 ) + (pass[3]<<1); + } - buf[i + 1 - ((i + 1) & 0xf8)] -= key[i - (i & 0xfc)]; - buf[i + 1 - ((i + 1) & 0xf8)] ^= sbox[(buf[i - (i & 0xf8)] - key[i + 1 - ((i + 1) & 0xfc)]) & 0x3f]; - buf[i + 1 - ((i + 1) & 0xf8)] -= sbox[((key[i + 1 - ((i + 1) & 0xfc)] ^ buf[i - (i & 0xf8)]) >> 2) & 0x3f] * 2; +} - tmp = key[0]; - int32_t j; - for (j = 0; j < 3; j++) - key[j] = ((key[j + 1] & 0x80) >> 7) + (key[j] * 2); - key[3] = ((tmp & 0x80) >> 7) + (key[3] * 2); - } +void gbox_decryptB(unsigned char *buffer, int bufsize, uchar *localkey) +{ + int counter; + gbox_encrypt8(&buffer[bufsize-9], localkey); + gbox_decrypt8(buffer, localkey); + for (counter=bufsize-2; counter>=0; counter--) + buffer[counter] = buffer[counter+1] ^ buffer[counter]; } -static void gbox_decrypt_stage2(uchar *buf, int32_t l, uchar *key) +void gbox_encryptB(unsigned char *buffer, int bufsize, uchar *key) { - int32_t i, j; + int counter; + for (counter=0; counter<(bufsize-1); counter++) + buffer[counter] = buffer[counter+1] ^ buffer[counter]; + gbox_encrypt8(buffer, key); + gbox_decrypt8(&buffer[bufsize-9], key); +} - for (i = 3; i >= 0; i--) - for (j = 0; j < 8; j++) { - uchar tmp; - - buf[(j + 1) & 7] += key[j & 3]; - buf[(j + 1) & 7] ^= sbox[(buf[j] - key[(j + 1) & 3]) & 0x3f]; - buf[(j + 1) & 7] += sbox[(buf[j] >> 2) & 0x3f]; - - tmp = key[0]; - int32_t k; - for (k = 0; k < 3; k++) - key[k] = ((key[k + 1] & 0x80) >> 7) + (key[k] * 2); - key[3] = ((tmp & 0x80) >> 7) + (key[3] * 2); - } +void gbox_encryptA(unsigned char *buffer, unsigned char *pass) +{ + int counter; + unsigned char temp; + for (counter=0x1F; counter>=0; counter--) { + temp = pass[3]&1; + pass[3] = ((pass[2]&1)<<7) + (pass[3]>>1); + pass[2] = ((pass[1]&1)<<7) + (pass[2]>>1); + pass[1] = ((pass[0]&1)<<7) + (pass[1]>>1); + pass[0] = (temp<<7) + (pass[0]>>1); + temp = ( pass[(counter+1)&3] ^ buffer[counter&7] ) >> 2; + buffer[(counter+1)&7] = Lookup_Table[temp & 0x3F]*2 + buffer[ (counter+1) & 7 ]; + temp = buffer[counter&7] - pass[(counter+1) & 3]; + buffer[(counter+1)&7] = Lookup_Table[temp & 0x3F] ^ buffer[(counter+1)&7]; + buffer[(counter+1)&7] = pass[counter&3] + buffer[(counter+1)&7]; + } } -static void gbox_encrypt(uchar *buf, int32_t l, uchar *key) +void gbox_decryptA(unsigned char *buffer, unsigned char *pass) { - int32_t i; - uchar tmp_key[4]; - - memcpy(tmp_key, key, 4); - - gbox_encrypt_stage1(buf, l, tmp_key); - - for (i = 0; i < l - 2; i++) - buf[i] ^= buf[i + 1]; - - gbox_encrypt_stage2(buf, l, tmp_key); - gbox_decrypt_stage2(buf + l - 9, 9, tmp_key); + int counter; + unsigned char temp; + for (counter=0; counter<=0x1F; counter++) { + buffer[(counter+1)&7] = buffer[(counter+1)&7] - pass[counter&3]; + temp = buffer[counter&7] - pass[(counter+1)&3]; + buffer[(counter+1)&7] = Lookup_Table[temp&0x3F] ^ buffer[(counter+1)&7]; + temp = ( pass[ (counter+1) & 3] ^ buffer[counter & 7] ) >> 2; + buffer[(counter+1) & 7] = buffer[(counter+1)&7] - Lookup_Table[temp & 0x3F]*2; + temp = pass[0]&0x80; + pass[0] = ((pass[1]&0x80)>>7) + (pass[0]<<1); + pass[1] = ((pass[2]&0x80)>>7) + (pass[1]<<1); + pass[2] = ((pass[3]&0x80)>>7) + (pass[2]<<1); + pass[3] = (temp>>7) + (pass[3]<<1); + } } -static void gbox_decrypt(uchar *buf, int32_t l, uchar *key) +void gbox_encrypt(uchar *buffer, int bufsize, uchar *key) { - uchar tmp_key[4]; - - memcpy(tmp_key, key, 4); - - gbox_encrypt_stage2(buf + l - 9, 9, tmp_key); - gbox_decrypt_stage2(buf, l, tmp_key); - - int32_t i; - for (i = l - 2; i >= 0; i--) { - buf[i] ^= buf[i + 1]; + gbox_encryptA(buffer, key); + gbox_encryptB(buffer, bufsize, key); } - gbox_decrypt_stage1(buf, l, tmp_key); +void gbox_decrypt(uchar *buffer, int bufsize, uchar *localkey) +{ + gbox_decryptB(buffer, bufsize, localkey); + gbox_decryptA(buffer, localkey); } static void gbox_compress(struct gbox_data *gbox, uchar *buf, int32_t unpacked_len, int32_t *packed_len) @@ -208,7 +210,8 @@ lzo_init(); - lzo_voidp wrkmem = NULL; + char work[16384]; + lzo_voidp wrkmem = &work; if(!cs_malloc(&tmp2,unpacked_len * 0x1000, -1)){ free(tmp); free(tmp2); @@ -224,23 +227,26 @@ free(tmp); free(tmp2); - free(wrkmem); *packed_len = pl; } static void gbox_decompress(struct gbox_data *gbox, uchar *buf, int32_t *unpacked_len) { - uchar tmp[2048]; + uchar *tmp; - int32_t len = buf[12] - 13; + if(!cs_malloc(&tmp,0x40000, -1)) return; + int err; + int len = *unpacked_len - 12; lzo_init(); - if (lzo1x_decompress(buf + 12, len, tmp, (lzo_uint *)unpacked_len, NULL) != LZO_E_OK) - cs_debug_mask(D_READER, "gbox: decompression failed!"); + cs_debug_mask(D_READER, "decompressing %d bytes",len); + if ((err=lzo1x_decompress_safe(buf + 12, len, tmp, (lzo_uint *)unpacked_len, NULL)) != LZO_E_OK) + cs_debug_mask(D_READER, "gbox: decompression failed! errno=%d", err); memcpy(buf + 12, tmp, *unpacked_len); *unpacked_len += 12; + free(tmp); } static int32_t gbox_decode_cmd(uchar *buf) @@ -384,8 +390,8 @@ cs_ddump_mask(D_READER, gbox->key, 4, "gbox: key after encrypt:"); cs_ddump_mask(D_READER, buf, l, "gbox: encrypted data sent (%d bytes):", l); - pthread_t t; - pthread_create(&t, NULL, (void *)gbox_wait_for_response, cli); +// pthread_t t; +// pthread_create(&t, NULL, (void *)gbox_wait_for_response, cli); } static void gbox_send_boxinfo(struct s_client *cli) @@ -406,10 +412,10 @@ len = 12 + hostname_len; - // TODO fix this! gbox_send(cli, buf, len); + gbox_send(cli, buf, 11); } -/* + static void gbox_send_goodbye(struct s_client *cli) { struct gbox_data *gbox = cli->gbox; @@ -420,10 +426,8 @@ memcpy(buf + 2, gbox->peer.key, 4); memcpy(buf + 6, gbox->key, 4); - cs_debug_mask(D_READER, "gbox: send goodbye:", cs_hexdump(0, buf, 10, tmp, sizeof(tmp))); - gbox_send(cli, buf, 11); -}*/ +} static void gbox_send_hello(struct s_client *cli) { @@ -562,10 +566,11 @@ switch (gbox_decode_cmd(data)) { case MSG_HELLO: { - static int32_t exp_seq = 0; - int32_t ip_clien_gbox = cs_inet_addr(cli->reader->device); cli->ip = ip_clien_gbox; + if (!gbox->peer.online) { + gbox_send_boxinfo(cli); + } gbox->peer.online = 1; int32_t payload_len = n; @@ -573,21 +578,24 @@ gbox_decompress(gbox, data, &payload_len); cs_ddump_mask(D_READER, data, payload_len, "gbox: decompressed data (%d bytes):", payload_len); - if (!data[10]) + if (!data[10]) { + gbox->exp_seq = 0; gbox->hello_expired = 1; + } int32_t seqno = data[11] & 0x7f; int32_t final = data[11] & 0x80; int32_t ncards_in_msg = 0; - if (seqno != exp_seq) return -1; + if (seqno != gbox->exp_seq) return -1; int32_t orig_card_count = ll_count(gbox->peer.cards); if (seqno == 0) { - exp_seq++; + gbox->exp_seq++; + if (gbox->peer.cards) ll_destroy_data(gbox->peer.cards); gbox->peer.cards = ll_create("peer.cards"); @@ -634,6 +642,7 @@ } memcpy(gbox->peer.hostname, data + payload_len - 1 - hostname_len, hostname_len); gbox->peer.hostname[hostname_len] = '\0'; + cs_debug_mask(D_READER, " peer hostname: %s", gbox->peer.hostname); memcpy(gbox->peer.checkcode, data + payload_len - footer_len - checkcode_len - 1, checkcode_len); gbox->peer.ver = data[payload_len - footer_len - 1]; @@ -669,7 +678,7 @@ } } - if (final) exp_seq = 0; + if (final) gbox->exp_seq = 0; // write_sahre_info() // TODO cs_log("gbox: received hello %d%s, %d providers from %s, version=2.%02X, checkcode=%s", @@ -689,7 +698,6 @@ pthread_t t; pthread_create(&t, NULL, (void *)gbox_expire_hello, cli); } - gbox_send_boxinfo(cli); } } break; @@ -697,10 +705,6 @@ gbox_send_hello(cli); break; case MSG_CW: - memcpy(gbox->cws, data + 14, 16); - - cs_debug_mask(D_READER, "gbox: received cws=%s, peer=%04x, ecm_pid=%d, sid=%d", - cs_hexdump(0, gbox->cws, 16, tmp, sizeof(tmp)), data[10] << 8 | data[11], data[6] << 8 | data[7], data[8] << 8 | data[9]); break; case MSG_CHECKCODE: memcpy(gbox->peer.checkcode, data + 10, 7); @@ -822,7 +826,7 @@ } if (strlen(cfg.gbox_key) != 8) { - cs_log("gbox: error, no/invalid password configured in oscam.conf!"); + cs_log("gbox: error, no/invalid password '%s' configured in oscam.conf!", cfg.gbox_key); return -1; } @@ -857,7 +861,7 @@ gbox->peer.id = (gbox->peer.key[0] ^ gbox->peer.key[2]) << 8 | (gbox->peer.key[1] ^ gbox->peer.key[3]); gbox->id = (gbox->key[0] ^ gbox->key[2]) << 8 | (gbox->key[1] ^ gbox->key[3]); - gbox->ver = 0x30; + gbox->ver = 0x99; gbox->type = 0x32; struct sockaddr_in loc_sa; @@ -916,16 +920,25 @@ return 0; } -static int32_t gbox_recv_chk(struct s_client *cli, uchar *dcw, int32_t *rc, uchar *buf, int32_t UNUSED(n)) +static int32_t gbox_recv_chk(struct s_client *cli, uchar *dcw, int32_t *rc, uchar *data, int32_t UNUSED(n)) { struct gbox_data *gbox = cli->gbox; + char tmp[512]; + if (gbox_decode_cmd(data) == MSG_CW) { + int i, n; + *rc = 1; + memcpy(dcw, data + 14, 16); + uint32_t crc = data[30] << 24 | data[31] << 16 | data[32] << 8 | data[33]; - if (gbox_decode_cmd(buf) == MSG_CW) { - *rc = 1; + cs_debug_mask(D_READER, "gbox: received cws=%s, peer=%04x, ecm_pid=%d, sid=%d, crc=%08x", + cs_hexdump(0, dcw, 16, tmp, sizeof(tmp)), data[10] << 8 | data[11], data[6] << 8 | data[7], data[8] << 8 | data[9], crc); - memcpy(dcw, gbox->cws, 16); - - return gbox->ecm_idx; + for (i=0, n=0; iecmtask[i].gbox_crc==crc) { + return cli->ecmtask[i].idx; + } + } + cs_debug_mask(D_READER, "gbox: no task found for crc=%08x",crc); } return -1; @@ -954,12 +967,22 @@ return 0; } + uint16_t ercaid = er->caid; + uint32_t erprid = er->prid; + + /* TODO: gbox encodes provids differently for several providers, hardcode some sort of mangle table in here? */ + switch (ercaid >> 8) { + // cryptoworks + case 0x0d: + erprid = erprid << 8; + break; + } + uchar send_buf[0x2048], *ptr; if (!er->l) return -1; + er->gbox_crc = gbox_get_ecmchecksum(er); - gbox->ecm_idx = er->idx; - memset(send_buf, 0, sizeof(send_buf)); gbox_code_cmd(send_buf, MSG_ECM); @@ -969,9 +992,12 @@ send_buf[11] = er->pid; send_buf[12] = er->srvid >> 8; send_buf[13] = er->srvid; -/* send_buf[14] = er->prid >> 16; - send_buf[15] = er->prid >> 8; - send_buf[17] = er->prid;*/ + +/* send_buf[14] = er->idx>>8; + send_buf[15] = er->idx; + send_buf[16] = 0; // number of cards + send_buf[17] = 0; // distance */ + memcpy(send_buf + 18, er->ecm, er->l); ptr = send_buf + 18 + er->l; *(ptr) = gbox->id >> 8; @@ -979,17 +1005,17 @@ *(++ptr) = gbox->ver; ptr++; *(++ptr) = gbox->type; - *(++ptr) = er->caid >> 8; - *(++ptr) = er->prid >> 16; - *(++ptr) = er->prid >> 8; - *(++ptr) = er->prid; + *(++ptr) = ercaid >> 8; + *(++ptr) = erprid >> 16; + *(++ptr) = erprid >> 8; + *(++ptr) = erprid; ptr++; LL_ITER it = ll_iter_create(gbox->peer.cards); struct gbox_card *card; while ((card = ll_iter_next(&it))) { - //if (card->caid == er->caid && card->provid == er->prid) { - if (card->provid >> 24 == er->caid >> 8 && (card->provid & 0xffffff) == er->prid) { + //if (card->caid == ercaid && card->provid == er->prid) { + if (card->provid >> 16 == (ercaid) && (card->provid & 0xffff) == erprid) { *(++ptr) = card->peer_id >> 8; *(++ptr) = card->peer_id; *(++ptr) = card->slot; @@ -998,7 +1024,7 @@ } if (!send_buf[16]) { - cs_debug_mask(D_READER, "gbox: %s no suitable card found, discarding ecm", cli->reader->label); + cs_debug_mask(D_READER, "gbox: %s no suitable card found for %04x:%08x, discarding ecm", cli->reader->label, ercaid, erprid); write_ecm_answer(cli->reader, er, E_NOTFOUND, 0x27, NULL, NULL); return 0; Index: oscam.c =================================================================== --- oscam.c (revision 5961) +++ oscam.c (working copy) @@ -1035,6 +1035,7 @@ int32_t ov=1, timeout, is_udp, i; char ptxt[2][32]; struct sockaddr_in sad; /* structure to hold server's address */ + cs_log("Starting listener %d", port_idx); ptxt[0][0]=ptxt[1][0]='\0'; if (!ph->ptab->ports[port_idx].s_port) @@ -1278,6 +1279,7 @@ static void init_cardreader() { + cs_debug_mask(D_TRACE, "cardreader: Initializing"); cs_writelock(&system_lock); struct s_reader *rdr; @@ -1585,6 +1587,7 @@ c=((ea->cw[i]+ea->cw[i+1]+ea->cw[i+2]) & 0xff); if (ea->cw[i+3]!=c) { if (reader->dropbadcws) { + cs_debug_mask(D_TRACE, "dropping wrong dcw"); ea->rc = E_NOTFOUND; ea->rcEx = E2_WRONG_CHKSUM; break; @@ -3208,10 +3211,16 @@ pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP; } } - //reader (only connected tcp proxy reader) + //reader: + //TCP: + // - TCP socket must be connected + // - no active init thread + //UDP: + // - connection status ignored + // - no active init thread rdr = cl->reader; if (rdr && cl->typ=='p' && cl->init_done) { - if (cl->pfd && !cl->thread_active && rdr->tcp_connected) { + if (cl->pfd && !cl->thread_active && ((rdr->tcp_connected && rdr->ph.type==MOD_CONN_TCP)||(rdr->ph.type==MOD_CONN_UDP))) { cl_list[pfdcount] = cl; pfd[pfdcount].fd = cl->pfd; pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP; Index: oscam-config.h =================================================================== --- oscam-config.h (revision 5961) +++ oscam-config.h (working copy) @@ -54,7 +54,7 @@ #endif #ifndef IPV6SUPPORT -//#define IPV6SUPPORT +#define IPV6SUPPORT #endif // @@ -152,7 +152,7 @@ #endif #ifndef CS_LOGHISTORY -#define CS_LOGHISTORY +//#define CS_LOGHISTORY #endif Index: globals.h =================================================================== --- globals.h (revision 5961) +++ globals.h (working copy) @@ -688,6 +688,10 @@ void *origin_card; // CCcam preferred card! #endif +#if defined MODULE_GBOX + uint32_t gbox_crc; // rcrc for gbox, used to identify ECM task in peer responses +#endif + void *src_data; struct ecm_request_t *ecmcacheptr; // Pointer to ecm-cw-rc-cache! char msglog[MSGLOGSIZE]; @@ -1312,7 +1316,7 @@ uint8_t cc_fixed_nodeid[8]; #endif char gbox_hostname[128]; - char gbox_key[9]; + char gbox_key[10]; char gbox_gsms_path[200]; int32_t gbox_port; struct s_ip *rad_allowed;