void process_incoming_link (struct context *c) { struct gc_arena gc = gc_new (); bool decrypt_status; struct link_socket_info *lsi = get_link_socket_info (c); const uint8_t *orig_buf = c->c2.buf.data; perf_push (PERF_PROC_IN_LINK); if (c->c2.buf.len > 0) { c->c2.link_read_bytes += c->c2.buf.len; link_read_bytes_global += c->c2.buf.len; #ifdef ENABLE_MEMSTATS if (mmap_stats) mmap_stats->link_read_bytes = link_read_bytes_global; #endif c->c2.original_recv_size = c->c2.buf.len; #ifdef ENABLE_MANAGEMENT if (management) { management_bytes_in (management, c->c2.buf.len); #ifdef MANAGEMENT_DEF_AUTH management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); #endif } #endif } else c->c2.original_recv_size = 0; #ifdef ENABLE_DEBUG /* take action to corrupt packet if we are in gremlin test mode */ if (c->options.gremlin) { if (!ask_gremlin (c->options.gremlin)) c->c2.buf.len = 0; corrupt_gremlin (&c->c2.buf, c->options.gremlin); } #endif /* log incoming packet */ #ifdef LOG_RW if (c->c2.log_rw && c->c2.buf.len > 0) fprintf (stderr, "R"); #endif msg (D_LINK_RW, "%s READ [%d] from %s: %s", proto2ascii (lsi->proto, true), BLEN (&c->c2.buf), print_link_socket_actual (&c->c2.from, &gc), PROTO_DUMP (&c->c2.buf, &gc)); /* * Good, non-zero length packet received. * Commence multi-stage processing of packet, * such as authenticate, decrypt, decompress. * If any stage fails, it sets buf.len to 0 or -1, * telling downstream stages to ignore the packet. */ if (c->c2.buf.len > 0) { if (!link_socket_verify_incoming_addr (&c->c2.buf, lsi, &c->c2.from)) link_socket_bad_incoming_addr (&c->c2.buf, lsi, &c->c2.from); #ifdef ENABLE_CRYPTO #ifdef ENABLE_SSL if (c->c2.tls_multi) { /* * If tls_pre_decrypt returns true, it means the incoming * packet was a good TLS control channel packet. If so, TLS code * will deal with the packet and set buf.len to 0 so downstream * stages ignore it. * * If the packet is a data channel packet, tls_pre_decrypt * will load crypto_options with the correct encryption key * and return false. */ if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options)) { interval_action (&c->c2.tmp_int); /* reset packet received timer if TLS packet */ if (c->options.ping_rec_timeout) event_timeout_reset (&c->c2.ping_rec_interval); } } #if P2MP_SERVER /* * Drop non-TLS packet if client-connect script/plugin has not * yet succeeded. */ if (c->c2.context_auth != CAS_SUCCEEDED) c->c2.buf.len = 0; #endif #endif /* ENABLE_SSL */ /* authenticate and decrypt the incoming packet */ decrypt_status = openvpn_decrypt (&c->c2.buf, c->c2.buffers->decrypt_buf, &c->c2.crypto_options, &c->c2.frame); if (!decrypt_status && link_socket_connection_oriented (c->c2.link_socket)) { /* decryption errors are fatal in TCP mode */ register_signal (c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */ msg (D_STREAM_ERRORS, "Fatal decryption error (process_incoming_link), restarting"); goto done; } #endif /* ENABLE_CRYPTO */ #ifdef ENABLE_FRAGMENT if (c->c2.fragment) fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); #endif #ifdef ENABLE_LZO /* decompress the incoming packet */ if (lzo_defined (&c->c2.lzo_compwork)) lzo_decompress (&c->c2.buf, c->c2.buffers->lzo_decompress_buf, &c->c2.lzo_compwork, &c->c2.frame); #endif #ifdef PACKET_TRUNCATION_CHECK /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ ipv4_packet_size_verify (BPTR (&c->c2.buf), BLEN (&c->c2.buf), TUNNEL_TYPE (c->c1.tuntap), "POST_DECRYPT", &c->c2.n_trunc_post_decrypt); #endif /* * Set our "official" outgoing address, since * if buf.len is non-zero, we know the packet * authenticated. In TLS mode we do nothing * because TLS mode takes care of source address * authentication. * * Also, update the persisted version of our packet-id. */ if (!TLS_MODE (c)) link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.from, NULL, c->c2.es); /* reset packet received timer */ if (c->options.ping_rec_timeout && c->c2.buf.len > 0) event_timeout_reset (&c->c2.ping_rec_interval); /* increment authenticated receive byte count */ if (c->c2.buf.len > 0) { c->c2.link_read_bytes_auth += c->c2.buf.len; c->c2.max_recv_size_local = max_int (c->c2.original_recv_size, c->c2.max_recv_size_local); } /* Did we just receive an openvpn ping packet? */ if (is_ping_msg (&c->c2.buf)) { dmsg (D_PING, "RECEIVED PING PACKET"); c->c2.buf.len = 0; /* drop packet */ } #ifdef ENABLE_OCC /* Did we just receive an OCC packet? */ if (is_occ_msg (&c->c2.buf)) process_received_occ_msg (c); #endif buffer_turnover (orig_buf, &c->c2.to_tun, &c->c2.buf, &c->c2.buffers->read_link_buf); /* to_tun defined + unopened tuntap can cause deadlock */ if (!tuntap_defined (c->c1.tuntap)) c->c2.to_tun.len = 0; } else { buf_reset (&c->c2.to_tun); } done: perf_pop (); gc_free (&gc); }
lzo_bool x_decompress(file_t *fip, file_t *fop, const header_t *h, lzo_bool skip) { lzo_bool ok = 0; if (!x_enter(h)) e_memory(); if (skip) { assert(opt_cmd != CMD_TEST); assert(fop->fd < 0); if (opt_cmd == CMD_DECOMPRESS && opt_verbose > 0) fprintf(con_term,"skipping %s [%s]", fip->name, fop->name); fflush(con_term); set_err_nl(1); } else if (opt_cmd == CMD_DECOMPRESS && opt_verbose > 1) { if (opt_unlink) fprintf(con_term,"restoring %s into %s", fip->name, fop->name); else fprintf(con_term,"decompressing %s into %s", fip->name, fop->name); fflush(con_term); set_err_nl(1); } else if (opt_cmd == CMD_TEST && opt_verbose > 0) { /* note: gzip is quiet by default when testing, lzop is not */ if (opt_verbose > 2) fprintf(con_term,"testing %s [%s]", fip->name, fop->name); else fprintf(con_term,"testing %s", fip->name); fflush(con_term); set_err_nl(1); } fip->bytes_processed = fop->bytes_processed = 0; switch (h->method) { #if defined(WITH_LZO) case M_LZO1X_1: case M_LZO1X_1_15: case M_LZO1X_999: ok = lzo_decompress(fip,fop,h,skip); break; #endif #if defined(WITH_NRV) case M_NRV1A: case M_NRV1B: case M_NRV2A: case M_NRV2B: ok = nrv_decompress(fip,fop,h,skip); break; #endif #if defined(WITH_ZLIB) case M_ZLIB: ok = zlib_decompress(fip,fop,h,skip); break; #endif default: fatal(fip,"Internal error"); ok = 0; break; } if (skip && opt_cmd == CMD_DECOMPRESS && opt_verbose > 0) { fprintf(con_term, ok ? "\n" : " FAILED\n"); fflush(con_term); } else if (opt_cmd == CMD_DECOMPRESS && opt_verbose > 1) { fprintf(con_term, ok ? "\n" : " FAILED\n"); fflush(con_term); } else if (opt_cmd == CMD_TEST && opt_verbose > 0) { fprintf(con_term, ok ? " OK\n" : " FAILED\n"); fflush(con_term); } set_err_nl(0); if (ok && opt_cmd == CMD_TEST) do_test(h,fop->bytes_processed,fip->bytes_processed); if (ok && opt_cmd == CMD_LIST) do_list(h,fop->bytes_processed,fip->bytes_processed); if (ok && opt_cmd == CMD_LS) do_ls(h,fop->bytes_processed,fip->bytes_processed); if (ok && opt_cmd == CMD_INFO) do_info(h,fop->bytes_processed,fip->bytes_processed); x_leave(h); return ok; }
void file_update_block(const char *blockdata, unsigned long long blocknr, unsigned int offsetblock, unsigned long long size, unsigned long long inode, unsigned char *chksum, off_t offset) { DBT *data = NULL; DBT *decrypted = NULL; DBT *cachedata; unsigned char *dbdata; INOBNO inobno; compr *uncompdata; BLKCACHE *blk; unsigned char *dtiger; INUSE *inuse; bool compressed = 1; QDTA *dta; #ifndef SHA3 word64 res[3]; #endif FUNC; LDEBUG ("file_update_block : inode %llu blocknr %llu offsetblock %llu, size %llu", inode, blocknr, (unsigned long long) offsetblock, (unsigned long long) size); inobno.inode = inode; inobno.blocknr = blocknr; dbdata = (unsigned char *) s_malloc(BLKSIZE); memset(dbdata, 0, BLKSIZE); data = try_block_cache(inode, blocknr, 0); if (NULL != data) { LDEBUG("try_block_cache : HIT"); memcpy(dbdata, data->data, data->size); memcpy(dbdata + offsetblock, blockdata, size); add_blk_to_cache(inode, blocknr, offsetblock + size, dbdata, offset); update_filesize(inode, size, offsetblock, blocknr, 0, 0, 0); free(dbdata); DBTfree(data); return; } else LDEBUG("%s: block not found in cache.", __FUNCTION__); // We don't need the old blockdata when we overwrite it completely anyway. if (offsetblock > 0 || size < BLKSIZE) { get_moddb_lock(); // First read the cache decrypted = search_memhash(dbdtaq, chksum, config->hashlen); if (NULL == decrypted) { LDEBUG("%s: Not in dbdtaq", __FUNCTION__); data = file_tgr_read_data(chksum); if (NULL == data) { LDEBUG("%s: Not found", __FUNCTION__); cachedata = search_memhash(blkcache, &inobno.inode, sizeof(unsigned long long)); if (NULL != cachedata) { blk = (BLKCACHE *) cachedata->data; #ifdef SHA3 dtiger=sha_binhash(blk->blockdata, BLKSIZE); #else binhash(blk->blockdata, BLKSIZE, res); dtiger=(unsigned char *)&res; #endif if (0 == memcmp(dtiger, chksum, config->hashlen)) { LDEBUG("%s: data alloc here", __FUNCTION__); data = s_malloc(sizeof(DBT)); data->data = s_malloc(BLKSIZE); data->size = BLKSIZE; memcpy(data->data, blk->blockdata, BLKSIZE); DBTfree(cachedata); compressed = 0; } else { LDEBUG ("updateBlock : Not in dbcache, out of luck."); loghash("updateBlock : No data found to read ", chksum); die_dataerr ("file_update_block : No data found to read - this should never happen: inode :%llu: blocknr :%llu", inode, blocknr); } #ifdef SHA3 free(dtiger); #endif } else { log_fatal_hash("file_update_block : No data found to read ", chksum); die_dataerr ("file_update_block : No data found to read, this should never happen: inode :%llu: blocknr :%llu", inode, blocknr); } } } else { data = s_malloc(sizeof(DBT)); dta = (QDTA *) decrypted->data; data->data = s_malloc(dta->size); memcpy(data->data, dta->data, dta->size); data->size = dta->size; DBTfree(decrypted); LDEBUG("data->size = %lu", data->size); } release_moddb_lock(); if (compressed && data->size < BLKSIZE) { #ifdef LZO uncompdata = lzo_decompress(data->data, data->size); #else uncompdata = clz_decompress(data->data, data->size); #endif memcpy(dbdata, uncompdata->data, uncompdata->size); comprfree(uncompdata); } else { memcpy(dbdata, data->data, data->size); } DBTfree(data); } memcpy(dbdata + offsetblock, blockdata, size); add_blk_to_cache(inode, blocknr, offsetblock + size, dbdata, offset); inuse = file_get_inuse(chksum); if (NULL == inuse) die_dataerr("file_update_block : hash not found"); if (inuse->inuse <= 1) { file_delete_data_cache(chksum, &inobno); put_on_freelist(inuse); delete_inuse(chksum); } else { inuse->inuse--; file_update_inuse(chksum, inuse); } free(inuse); update_filesize(inode, size, offsetblock, blocknr, 0, 0, 0); free(dbdata); EFUNC; return; }
void file_partial_truncate_block(struct stat *stbuf, unsigned long long blocknr, unsigned int offset) { unsigned char *blockdata; compr *uncompdata; INOBNO inobno; DBT *data; OFFHASH *offhash; off_t offsetfile; unsigned char *stiger; INUSE *inuse; DBT cachedata; QDTA *dta; FUNC; LDEBUG("file_partial_truncate_block : inode %llu, blocknr %llu, offset %u", stbuf->st_ino, blocknr, offset); inobno.inode = stbuf->st_ino; inobno.blocknr = blocknr; get_dbb_lock(); data = search_memhash(dbbm, &inobno, sizeof(INOBNO)); if ( NULL == data ) { data = search_dbdata(dbb, &inobno, sizeof(INOBNO)); } release_dbb_lock(); if (NULL == data) { LDEBUG("file_partial_truncate_block : deletion of non existent block."); return; } offhash = (OFFHASH *) data->data; stiger = s_malloc(data->size); loghash("file_partial_truncate_block : search tiger ", stiger); memcpy(stiger, offhash->stiger, config->hashlen); offsetfile = offhash->offset; DBTfree(data); blockdata = s_malloc(BLKSIZE); memset(blockdata, 0, BLKSIZE); // First try the cache get_moddb_lock(); data = search_memhash(dbdtaq, stiger, config->hashlen); if ( NULL != data ) die_dataerr("file_partial_truncate_block : not data in cache expected"); release_moddb_lock(); if ( NULL == data ) { data = file_tgr_read_data(stiger); if ( NULL != data ) { LDEBUG("file_partial_truncate_block : clz_decompress"); if (data->size != BLKSIZE) { #ifdef LZO uncompdata = lzo_decompress(data->data, data->size); #else uncompdata = clz_decompress(data->data, data->size); #endif memcpy(blockdata, uncompdata->data, offset); comprfree(uncompdata); } else { memcpy(blockdata, data->data, offset); } } } else { dta = (QDTA *)data->data; cachedata.data=s_malloc(dta->size); memcpy(cachedata.data, dta->data, dta->size); cachedata.size = dta->size; memcpy(blockdata, cachedata.data, offset); free(cachedata.data); } file_commit_block(blockdata, inobno, offsetfile); DBTfree(data); free(blockdata); inuse = file_get_inuse(stiger); if (NULL == inuse) die_dataerr ("file_partial_truncate_block : unexpected block not found"); if (inuse->inuse == 1) { loghash("file_partial_truncate_block : delete hash", stiger); put_on_freelist(inuse); delete_inuse(stiger); } else { if (inuse->inuse > 1) inuse->inuse--; file_update_inuse(stiger, inuse); } free(inuse); free(stiger); return; }
unsigned long long file_read_block(unsigned long long blocknr, const char *filename, char *blockdata, unsigned long long inode) { unsigned long long ret = 0; DBT *data = NULL; DBT *decrypted = NULL; DBT *cachedata; unsigned char *stiger; unsigned char *dtiger; compr *uncompdata = NULL; INOBNO inobno; BLKCACHE *blk; bool compressed = 1; QDTA *dta; #ifndef SHA3 word64 res[3]; #endif FUNC; inobno.inode = inode; inobno.blocknr = blocknr; data = try_block_cache(inode, blocknr, 0); if (NULL != data) { LDEBUG("file_read_block : block %llu - %llu found in cache", inode, blocknr); memcpy(blockdata, data->data, data->size); ret = data->size; DBTfree(data); return (ret); } data = check_block_exists(inobno); if (NULL == data) { LDEBUG("check_block_exists : Nothing found for inode %llu - %llu", inobno.inode, inobno.blocknr); LDEBUG("DONE ret = %llu",ret); return (ret); } // Not needed to copy this. stiger = s_malloc(data->size); memcpy(stiger, data->data, data->size); DBTfree(data); // First try the cache get_moddb_lock(); data = search_memhash(dbdtaq, stiger, config->hashlen); if (NULL == data) { decrypted = file_tgr_read_data(stiger); if (NULL != decrypted) { LDEBUG ("file_read_block : found inode %llu - %llu file_io", inobno.inode, inobno.blocknr); } else { cachedata = search_memhash(blkcache, &inobno.inode, sizeof(unsigned long long)); if (NULL != cachedata) { blk = (BLKCACHE *) cachedata->data; #ifdef SHA3 dtiger=sha_binhash(blk->blockdata, BLKSIZE); #else binhash(blk->blockdata, BLKSIZE,res); dtiger=(unsigned char *)&res; #endif if (0 == memcmp(dtiger, stiger, config->hashlen)) { decrypted = s_malloc(sizeof(DBT)); decrypted->data = s_malloc(BLKSIZE); decrypted->size = BLKSIZE; memcpy(decrypted->data, blk->blockdata, BLKSIZE); compressed = 0; } #ifdef SHA3 free(dtiger); #endif DBTfree(cachedata); } } } else { decrypted = s_malloc(sizeof(DBT)); dta = (QDTA *) data->data; decrypted->data = s_malloc(dta->size); memcpy(decrypted->data, dta->data, dta->size); decrypted->size = dta->size; DBTfree(data); } release_moddb_lock(); if (decrypted->size > BLKSIZE) die_dataerr("file_read_block : data has grown beyond blocksize %lu", decrypted->size); if (compressed && decrypted->size != BLKSIZE) { #ifdef LZO uncompdata = lzo_decompress(decrypted->data, decrypted->size); #else uncompdata = clz_decompress(decrypted->data, decrypted->size); #endif memcpy(blockdata, uncompdata->data, uncompdata->size); ret = uncompdata->size; comprfree(uncompdata); } else { memcpy(blockdata, decrypted->data, decrypted->size); ret = decrypted->size; } DBTfree(decrypted); free(stiger); EFUNC; return (ret); }