Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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);
}