// Called by parent process.
static std::string read_pipe(apr_file_t* in, bool timeout_ok = false)
{
	char buf[256];
	unsigned char bytes_to_read;
	apr_size_t bytes_read;
	apr_status_t status = apr_file_read_full(in, &bytes_to_read, 1, &bytes_read);
	if (status != APR_SUCCESS)
	{
		if (APR_STATUS_IS_TIMEUP(status) && timeout_ok)
		{
			return "TIMEOUT";
		}
		llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
		assert(APR_STATUS_IS_EOF(status));
		return "END OF FILE";
	}
	assert(bytes_read == 1);
	status = apr_file_read_full(in, buf, bytes_to_read, &bytes_read);
	if (status != APR_SUCCESS)
	{
		llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
		assert(status == APR_SUCCESS);	// Fail
	}
	assert(bytes_read == bytes_to_read);

	std::string received(buf, bytes_read);
	llinfos << "Received: \"" << received << "\" (bytes read: " << bytes_read << ")" << llendl;
	return received;
}
Example #2
0
static void create_segments(geo_db *geo) {
    int i, j;
    unsigned char delim[3];
    unsigned char buf[GEO_SEGMENT_RECORD_LENGTH];
    apr_size_t nbytes;
    apr_off_t offset;

    geo->ctry_offset = 0;

    geo->dbtype = GEOIP_COUNTRY_EDITION;
    offset = -3l;
    apr_file_seek(geo->db, APR_END, &offset);

    for (i = 0; i < GEO_STRUCT_INFO_MAX_SIZE; i++) {

        apr_file_read_full(geo->db, &delim, 3, &nbytes);

        if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
            apr_file_read_full(geo->db, &geo->dbtype, 1, &nbytes);
            if (geo->dbtype >= 106) {
                geo->dbtype -= 105;
            }

            if (geo->dbtype == GEOIP_REGION_EDITION_REV0) {
                geo->ctry_offset = GEO_STATE_BEGIN_REV0;
            } else if (geo->dbtype == GEOIP_REGION_EDITION_REV1) {
                geo->ctry_offset = GEO_STATE_BEGIN_REV1;
            } else if (geo->dbtype == GEOIP_CITY_EDITION_REV0 ||
                                 geo->dbtype == GEOIP_CITY_EDITION_REV1 ||
                                 geo->dbtype == GEOIP_ORG_EDITION ||
                                 geo->dbtype == GEOIP_ISP_EDITION ||
                                 geo->dbtype == GEOIP_ASNUM_EDITION) {
                geo->ctry_offset = 0;
                apr_file_read_full(geo->db, &buf, GEO_SEGMENT_RECORD_LENGTH, &nbytes);
                for (j = 0; j < GEO_SEGMENT_RECORD_LENGTH; j++) {
                    geo->ctry_offset += (buf[j] << (j * 8));
                }
            }
            break;
        } else {
            offset = -4l;
            apr_file_seek(geo->db, APR_CUR, &offset);
        }
    }
    if (geo->dbtype == GEOIP_COUNTRY_EDITION ||
            geo->dbtype == GEOIP_PROXY_EDITION ||
            geo->dbtype == GEOIP_NETSPEED_EDITION) {
        geo->ctry_offset = GEO_COUNTRY_BEGIN;
    }
}
Example #3
0
static void test_fail_read_flush(CuTest *tc)
{
    apr_file_t *f;
    const char *fname = "data/testflush.dat";
    apr_status_t rv;
    char buf[2];

    apr_file_remove(fname, p);

    apr_assert_success(tc, "open test file",
                       apr_file_open(&f, fname,
                                     APR_CREATE|APR_READ|APR_BUFFERED,
                                     APR_UREAD|APR_UWRITE, p));

    /* this write should be buffered. */
    apr_assert_success(tc, "buffered write should succeed",
                       apr_file_puts("hello", f));

    /* Now, trying a read should fail since the write must be flushed,
     * and should fail with something other than EOF since the file is
     * opened read-only. */
    rv = apr_file_read_full(f, buf, 2, NULL);

    CuAssert(tc, "read should flush buffered write and fail",
             rv != APR_SUCCESS && rv != APR_EOF);

    /* Likewise for gets */
    rv = apr_file_gets(buf, 2, f);

    CuAssert(tc, "gets should flush buffered write and fail",
             rv != APR_SUCCESS && rv != APR_EOF);

    apr_file_close(f);
    apr_file_remove(fname, p);
}
Example #4
0
apr_status_t procmgr_fetch_cmd(fcgid_command * command,
                              server_rec * main_server)
{
    apr_status_t rv;

    /* Sanity check */
    if (!g_pm_read_pipe)
        return APR_EPIPE;

    /* Wait for next command */
#if APR_MAJOR_VERSION < 2
    rv = apr_wait_for_io_or_timeout(g_pm_read_pipe, NULL, FOR_READ);
#else
    rv = apr_file_pipe_wait(g_pm_read_pipe, APR_WAIT_READ);
#endif

    /* Log any unexpect result */
    if (rv != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(rv)) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, main_server,
                     "mod_fcgid: error while waiting for message from pipe");
        return rv;
    }

    /* Timeout */
    if (rv != APR_SUCCESS)
        return rv;

    return apr_file_read_full(g_pm_read_pipe, command, sizeof(*command),
                              NULL);
}
Example #5
0
/* These two functions get and put state information into the data
 * file for an ap_cache_el, this state information will be read
 * and written transparent to clients of this module
 */
static int file_cache_recall_mydata(apr_file_t *fd, cache_info *info,
                                    disk_cache_object_t *dobj, request_rec *r)
{
    apr_status_t rv;
    char *urlbuff;
    disk_cache_info_t disk_info;
    apr_size_t len;

    /* read the data from the cache file */
    len = sizeof(disk_cache_info_t);
    rv = apr_file_read_full(fd, &disk_info, len, &len);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    /* Store it away so we can get it later. */
    dobj->disk_info = disk_info;

    info->status = disk_info.status;
    info->date = disk_info.date;
    info->expire = disk_info.expire;
    info->request_time = disk_info.request_time;
    info->response_time = disk_info.response_time;

    /* Note that we could optimize this by conditionally doing the palloc
     * depending upon the size. */
    urlbuff = apr_palloc(r->pool, disk_info.name_len + 1);
    len = disk_info.name_len;
    rv = apr_file_read_full(fd, urlbuff, len, &len);
    if (rv != APR_SUCCESS) {
        return rv;
    }
    urlbuff[disk_info.name_len] = '\0';

    /* check that we have the same URL */
    /* Would strncmp be correct? */
    if (strcmp(urlbuff, dobj->name) != 0) {
        return APR_EGENERAL;
    }

    return APR_SUCCESS;
}
int get_password(struct passwd_ctx *ctx)
{
    char buf[MAX_STRING_LEN + 1];
    if (ctx->passwd_src == PW_STDIN) {
        apr_file_t *file_stdin;
        apr_size_t nread;
        if (apr_file_open_stdin(&file_stdin, ctx->pool) != APR_SUCCESS) {
            ctx->errstr = "Unable to read from stdin.";
            return ERR_GENERAL;
        }
        if (apr_file_read_full(file_stdin, buf, sizeof(buf) - 1,
                               &nread) != APR_EOF
            || nread == sizeof(buf) - 1) {
            goto err_too_long;
        }
        buf[nread] = '\0';
        if (nread >= 1 && buf[nread-1] == '\n') {
            buf[nread-1] = '\0';
            if (nread >= 2 && buf[nread-2] == '\r')
                buf[nread-2] = '\0';
        }
        apr_file_close(file_stdin);
        ctx->passwd = apr_pstrdup(ctx->pool, buf);
    }
    else if (ctx->passwd_src == PW_PROMPT_VERIFY) {
        apr_size_t bufsize = sizeof(buf);
        if (apr_password_get("Enter password: "******"New password: "******"Re-type new password: "******"password verification error";
            memset(ctx->passwd, '\0', strlen(ctx->passwd));
            memset(buf, '\0', sizeof(buf));
            return ERR_PWMISMATCH;
        }
    }
    memset(buf, '\0', sizeof(buf));
    return 0;

err_too_long:
    ctx->errstr = apr_psprintf(ctx->pool,
                               "password too long (>%" APR_SIZE_T_FMT ")",
                               ctx->out_len - 1);
    return ERR_OVERFLOW;
}
Example #7
0
static void test_xthread(abts_case *tc, void *data)
{
    apr_file_t *f;
    const char *fname = "data/testxthread.dat";
    apr_status_t rv;
    apr_int32_t flags = APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_APPEND|APR_FOPEN_XTHREAD;
    char buf[128] = { 0 };

    /* Test for bug 38438, opening file with append + xthread and seeking to
       the end of the file resulted in writes going to the beginning not the
       end. */

    apr_file_remove(fname, p);

    APR_ASSERT_SUCCESS(tc, "open test file",
                       apr_file_open(&f, fname, flags,
                                     APR_UREAD|APR_UWRITE, p));

    APR_ASSERT_SUCCESS(tc, "write should succeed",
                       apr_file_puts("hello", f));

    apr_file_close(f);

    APR_ASSERT_SUCCESS(tc, "open test file",
                       apr_file_open(&f, fname, flags,
                                     APR_UREAD|APR_UWRITE, p));

    /* Seek to the end. */
    {
        apr_off_t offset = 0;

        rv = apr_file_seek(f, APR_END, &offset);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    }

    APR_ASSERT_SUCCESS(tc, "more writes should succeed",
                       apr_file_puts("world", f));

    /* Back to the beginning. */
    {
        apr_off_t offset = 0;

        rv = apr_file_seek(f, APR_SET, &offset);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    }

    apr_file_read_full(f, buf, sizeof(buf), NULL);

    ABTS_STR_EQUAL(tc, "helloworld", buf);

    apr_file_close(f);
}
Example #8
0
/* Compare two open files. The file positions may change. */
static svn_error_t *
compare_files(apr_file_t *f1, apr_file_t *f2, int dump_files)
{
  static char file_buffer_1[10240];
  static char file_buffer_2[10240];

  char *c1, *c2;
  apr_off_t pos = 0;
  apr_size_t len1, len2;

  rewind_file(f1);
  rewind_file(f2);

  if (dump_files)
    dump_file_contents(f2);

  do
    {
      apr_file_read_full(f1, file_buffer_1, sizeof file_buffer_1, &len1);
      apr_file_read_full(f2, file_buffer_2, sizeof file_buffer_2, &len2);

      for (c1 = file_buffer_1, c2 = file_buffer_2;
           c1 < file_buffer_1 + len1 && c2 < file_buffer_2 + len2;
           ++c1, ++c2, ++pos)
        {
          if (*c1 != *c2)
            return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                                     "mismatch at position %"APR_OFF_T_FMT,
                                     pos);
        }

      if (len1 != len2)
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                                 "unequal file sizes at position"
                                 " %"APR_OFF_T_FMT, pos);
    }
  while (len1 == sizeof file_buffer_1);
  return SVN_NO_ERROR;
}
Example #9
0
static void
dump_file_contents(apr_file_t *fp)
{
  static char file_buffer[10240];
  apr_size_t length = sizeof file_buffer;
  fputs("--------\n", stdout);
  do
    {
      apr_file_read_full(fp, file_buffer, sizeof file_buffer, &length);
      fwrite(file_buffer, 1, length, stdout);
    }
  while (length == sizeof file_buffer);
  putc('\n', stdout);
  rewind_file(fp);
}
Example #10
0
static void test_xthread(CuTest *tc)
{
    apr_file_t *f;
    const char *fname = "data/testxthread.dat";
    apr_status_t rv;
    apr_int32_t flags = APR_CREATE|APR_READ|APR_WRITE|APR_APPEND|APR_XTHREAD;
    char buf[128] = { 0 };

    /* Test for bug 38438, opening file with append + xthread and seeking to 
       the end of the file resulted in writes going to the beginning not the
       end. */

    apr_file_remove(fname, p);

    rv = apr_file_open(&f, fname, flags, APR_UREAD|APR_UWRITE, p);
    CuAssert(tc, "open test file", rv == APR_SUCCESS);

    rv = apr_file_puts("hello", f);
    CuAssert(tc, "write should succeed", rv == APR_SUCCESS);

    apr_file_close(f);
    
    rv = apr_file_open(&f, fname, flags, APR_UREAD|APR_UWRITE, p);
    CuAssert(tc, "open test file", rv == APR_SUCCESS);

    /* Seek to the end. */
    {
        apr_off_t offset = 0;

        rv = apr_file_seek(f, APR_END, &offset);
    }

    rv = apr_file_puts("world", f);
    CuAssert(tc, "more writes should succeed", rv == APR_SUCCESS);

    /* Back to the beginning. */
    {
        apr_off_t offset = 0;
        
        rv = apr_file_seek(f, APR_SET, &offset);
    }
    
    apr_file_read_full(f, buf, sizeof(buf), NULL);

    CuAssertStrEquals(tc, "helloworld", buf);

    apr_file_close(f);
}
Example #11
0
static
apr_status_t
FileRead(
    void *opaque,
    apr_byte_t *buffer,
    apr_size_t bytesToRead,
    apr_size_t *bytesRead
    )
{
    apr_file_t *file = opaque;

    ASSERT(opaque != NULL);
    ASSERT(buffer != NULL);

    return apr_file_read_full(file, buffer, bytesToRead, bytesRead);
}
Example #12
0
AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename,
                                     pid_t *mypid)
{
    const apr_size_t BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */
    apr_file_t *pid_file = NULL;
    apr_status_t rv;
    const char *fname;
    char *buf, *endptr;
    apr_size_t bytes_read;

    if (!filename) {
        return APR_EGENERAL;
    }

    fname = ap_server_root_relative(p, filename);
    if (!fname) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH,
                     NULL, "Invalid PID file path %s, ignoring.", filename);
        return APR_EGENERAL;
    }

    rv = apr_file_open(&pid_file, fname, APR_READ, APR_OS_DEFAULT, p);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    buf = apr_palloc(p, BUFFER_SIZE);

    rv = apr_file_read_full(pid_file, buf, BUFFER_SIZE - 1, &bytes_read);
    if (rv != APR_SUCCESS && rv != APR_EOF) {
        return rv;
    }

    /* If we fill the buffer, we're probably reading a corrupt pid file.
     * To be nice, let's also ensure the first char is a digit. */
    if (bytes_read == 0 || bytes_read == BUFFER_SIZE - 1 || !apr_isdigit(*buf)) {
        return APR_EGENERAL;
    }

    buf[bytes_read] = '\0';
    *mypid = strtol(buf, &endptr, 10);

    apr_file_close(pid_file);
    return APR_SUCCESS;
}
Example #13
0
File: avro.c Project: jivega/avro
char *
avro_util_file_read_full (apr_pool_t * pool, const char *fname,
			  apr_size_t * len)
{
  apr_status_t status;
  apr_finfo_t finfo;
  apr_file_t *file;
  char *rval;
  apr_size_t bytes_read;

  /* open the file */
  status = apr_file_open (&file, fname, APR_READ, 0, pool);
  if (status != APR_SUCCESS)
    {
      return NULL;
    }

  /* get the file length */
  status = apr_file_info_get (&finfo, APR_FINFO_SIZE, file);
  if (status != APR_SUCCESS)
    {
      return NULL;
    }

  /* alloc space for the data */
  rval = apr_palloc (pool, finfo.size + 1);
  if (!rval)
    {
      return NULL;
    }

  /* read in the data */
  status = apr_file_read_full (file, rval, finfo.size, &bytes_read);
  if (status != APR_SUCCESS)
    {
      return NULL;
    }
  rval[finfo.size] = '\0';

  if (len)
    {
      *len = bytes_read;
    }
  return rval;
}
Example #14
0
static void test_fail_read_flush(abts_case *tc, void *data)
{
    apr_file_t *f;
    const char *fname = "data/testflush.dat";
    apr_status_t rv;
    char buf[2];

    apr_file_remove(fname, p);

    APR_ASSERT_SUCCESS(tc, "open test file",
                       apr_file_open(&f, fname,
                                     APR_CREATE|APR_READ|APR_BUFFERED,
                                     APR_UREAD|APR_UWRITE, p));

    /* this write should be buffered. */
    APR_ASSERT_SUCCESS(tc, "buffered write should succeed",
                       apr_file_puts("hello", f));

    /* Now, trying a read should fail since the write must be flushed,
     * and should fail with something other than EOF since the file is
     * opened read-only. */
    rv = apr_file_read_full(f, buf, 2, NULL);

    ABTS_ASSERT(tc, "read should flush buffered write and fail",
                rv != APR_SUCCESS && rv != APR_EOF);

    /* Likewise for gets */
    rv = apr_file_gets(buf, 2, f);

    ABTS_ASSERT(tc, "gets should flush buffered write and fail",
                rv != APR_SUCCESS && rv != APR_EOF);

    /* Likewise for seek. */
    {
        apr_off_t offset = 0;

        rv = apr_file_seek(f, APR_SET, &offset);
    }

    ABTS_ASSERT(tc, "seek should flush buffered write and fail",
                rv != APR_SUCCESS && rv != APR_EOF);

    apr_file_close(f);
}
Example #15
0
/* Test that the contents of file FNAME are equal to data EXPECT of
 * length EXPECTLEN. */
static void file_contents_equal(abts_case *tc,
                                const char *fname,
                                const void *expect,
                                apr_size_t expectlen)
{
    void *actual = apr_palloc(p, expectlen);
    apr_file_t *f;

    APR_ASSERT_SUCCESS(tc, "open file",
                       apr_file_open(&f, fname, APR_READ|APR_BUFFERED,
                                     0, p));
    APR_ASSERT_SUCCESS(tc, "read from file",
                       apr_file_read_full(f, actual, expectlen, NULL));
    
    ABTS_ASSERT(tc, "matched expected file contents",
                memcmp(expect, actual, expectlen) == 0);

    APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(f));
}
Example #16
0
static void pipe_consumer(toolbox_t *box)
{
    char ch;
    apr_status_t rv;
    apr_size_t nbytes;
    abts_case *tc = box->tc;
    apr_file_t *out = box->data;
    apr_uint32_t consumed = 0;

    do {
        rv = apr_thread_mutex_lock(box->mutex);
        ABTS_SUCCESS(rv);

        while (!pipe_count && !exiting) {
            rv = apr_thread_cond_wait(box->cond, box->mutex);
            ABTS_SUCCESS(rv);
        }

        if (!pipe_count && exiting) {
            rv = apr_thread_mutex_unlock(box->mutex);
            ABTS_SUCCESS(rv);
            break;
        }

        pipe_count--;
        consumed++;

        rv = apr_thread_mutex_unlock(box->mutex);
        ABTS_SUCCESS(rv);

        rv = apr_file_read_full(out, &ch, 1, &nbytes);
        ABTS_SUCCESS(rv);
        ABTS_SIZE_EQUAL(tc, 1, nbytes);
        ABTS_TRUE(tc, ch == '.');
    } while (1);

    /* naive fairness test - it would be good to introduce or solidify
     * a solid test to ensure one thread is not starved.
     * ABTS_INT_EQUAL(tc, 1, !!consumed);
     */
}
Example #17
0
static apr_file_t *
copy_tempfile(apr_file_t *fp, apr_pool_t *pool)
{
  static char file_buffer[10240];
  apr_file_t *newfp;
  apr_size_t length1, length2;

  newfp = open_tempfile("copy_XXXXXX", pool);

  rewind_file(fp);
  do
    {
      apr_file_read_full(fp, file_buffer, sizeof file_buffer, &length1);
      apr_file_write_full(newfp, file_buffer, length1, &length2);
      assert(length1 == length2);
    }
  while (length1 == sizeof file_buffer);

  rewind_file(fp);
  rewind_file(newfp);
  return newfp;
}
Example #18
0
int sha1_file(const std::string& filename, std::string& checksum, bool binary)
{
  apr_initialize();
  apr_pool_t* pool;
  apr_pool_create(&pool, NULL);
  
  apr_file_t* in;
  apr_int32_t flags = (binary ? APR_READ | APR_BINARY : APR_READ);
  apr_file_open(&in, filename.c_str(), flags, APR_OS_DEFAULT, pool);
  
  char buffer[512];
  memset(buffer, 0, sizeof(buffer));
  apr_size_t bytes_read = 0;
  apr_file_read_full(in, buffer, 512, &bytes_read);
  apr_file_close(in);
  
  unsigned char digest[APR_SHA1_DIGESTSIZE + 1];
  memset(digest, 0, APR_SHA1_DIGESTSIZE + 1);
  
  apr_sha1_ctx_t context;
  apr_sha1_init(&context);
  if(binary) apr_sha1_update_binary(&context, (const unsigned char*)buffer, bytes_read);
  else apr_sha1_update(&context, buffer, bytes_read);
  apr_sha1_final(digest, &context);
  
  std::ostringstream oss;
  for(int i = 0; i < APR_SHA1_DIGESTSIZE; i++)
  {
    unsigned short letter = digest[i];
    oss << std::hex << std::setw(2) << std::setfill('0') << letter;
  }
  
  checksum = oss.str();
  
  apr_pool_destroy(pool);
  apr_terminate();
  
  return 0;
}
Example #19
0
/* Test that the contents of file FNAME are equal to data EXPECT of
 * length EXPECTLEN. */
static void file_contents_equal(CuTest *tc,
                                const char *fname,
                                const void *expect,
                                apr_size_t expectlen)
{
    void *actual = apr_palloc(p, expectlen);
    apr_file_t *f;
    apr_status_t rv;
    int rc;
    
    rv = apr_file_open(&f, fname, APR_READ|APR_BUFFERED, 0, p);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_file_read_full(f, actual, expectlen, NULL);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rc = memcmp(expect, actual, expectlen);
    CuAssertIntEquals(tc, 0, rc);

    rv = apr_file_close(f);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
}
Example #20
0
static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
{
    apr_uint32_t format;
    apr_size_t len;
    const char *nkey;
    apr_status_t rc;
    static int error_logged = 0;
    disk_cache_conf *conf = ap_get_module_config(r->server->module_config,
                                                 &disk_cache_module);
    apr_finfo_t finfo;
    cache_object_t *obj;
    cache_info *info;
    disk_cache_object_t *dobj;
    int flags;

    h->cache_obj = NULL;

    /* Look up entity keyed to 'url' */
    if (conf->cache_root == NULL) {
        if (!error_logged) {
            error_logged = 1;
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                         "disk_cache: Cannot cache files to disk without a CacheRoot specified.");
        }
        return DECLINED;
    }

    /* Create and init the cache object */
    h->cache_obj = obj = apr_pcalloc(r->pool, sizeof(cache_object_t));
    obj->vobj = dobj = apr_pcalloc(r->pool, sizeof(disk_cache_object_t));

    info = &(obj->info);

    /* Open the headers file */
    dobj->prefix = NULL;

    /* Save the cache root */
    dobj->root = apr_pstrndup(r->pool, conf->cache_root, conf->cache_root_len);
    dobj->root_len = conf->cache_root_len;

    dobj->hdrsfile = header_file(r->pool, conf, dobj, key);
    flags = APR_READ|APR_BINARY|APR_BUFFERED;
    rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool);
    if (rc != APR_SUCCESS) {
        return DECLINED;
    }

    /* read the format from the cache file */
    len = sizeof(format);
    apr_file_read_full(dobj->hfd, &format, len, &len);

    if (format == VARY_FORMAT_VERSION) {
        apr_array_header_t* varray;
        apr_time_t expire;

        len = sizeof(expire);
        apr_file_read_full(dobj->hfd, &expire, len, &len);

        varray = apr_array_make(r->pool, 5, sizeof(char*));
        rc = read_array(r, varray, dobj->hfd);
        if (rc != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
                         "disk_cache: Cannot parse vary header file: %s",
                         dobj->hdrsfile);
            return DECLINED;
        }
        apr_file_close(dobj->hfd);

        nkey = regen_key(r->pool, r->headers_in, varray, key);

        dobj->hashfile = NULL;
        dobj->prefix = dobj->hdrsfile;
        dobj->hdrsfile = header_file(r->pool, conf, dobj, nkey);

        flags = APR_READ|APR_BINARY|APR_BUFFERED;
        rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool);
        if (rc != APR_SUCCESS) {
            return DECLINED;
        }
    }
    else if (format != DISK_FORMAT_VERSION) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                     "cache_disk: File '%s' has a version mismatch. File had version: %d.",
                     dobj->hdrsfile, format);
        return DECLINED;
    }
    else {
        apr_off_t offset = 0;
        /* This wasn't a Vary Format file, so we must seek to the
         * start of the file again, so that later reads work.
         */
        apr_file_seek(dobj->hfd, APR_SET, &offset);
        nkey = key;
    }

    obj->key = nkey;
    dobj->key = nkey;
    dobj->name = key;
    dobj->datafile = data_file(r->pool, conf, dobj, nkey);
    dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL);

    /* Open the data file */
    flags = APR_READ|APR_BINARY;
#ifdef APR_SENDFILE_ENABLED
    flags |= APR_SENDFILE_ENABLED;
#endif
    rc = apr_file_open(&dobj->fd, dobj->datafile, flags, 0, r->pool);
    if (rc != APR_SUCCESS) {
        /* XXX: Log message */
        return DECLINED;
    }

    rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, dobj->fd);
    if (rc == APR_SUCCESS) {
        dobj->file_size = finfo.size;
    }

    /* Read the bytes to setup the cache_info fields */
    rc = file_cache_recall_mydata(dobj->hfd, info, dobj, r);
    if (rc != APR_SUCCESS) {
        /* XXX log message */
        return DECLINED;
    }

    /* Initialize the cache_handle callback functions */
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                 "disk_cache: Recalled cached URL info header %s",  dobj->name);
    return OK;
}
Example #21
0
/**
 * Sets the policy file to use from the configuration.
 *
 * @param parms the command directive parameters.
 * @param userdata NULL, not used.
 * @param arg the string argument to the command directive (the file with
 *           the cross-domain policy to serve as content).
 *
 * @return NULL on success, otherwise an error string to display.
 */
static const char* fsp_set_policy_file(
   cmd_parms* parms, void* userdata, const char* arg)
{
   const char* rval = NULL;

   apr_pool_t* pool = (apr_pool_t*)parms->pool;
   fsp_config* cfg = ap_get_module_config(
      parms->server->module_config, &fsp_module);

   // ensure command is in the correct context
   rval = ap_check_cmd_context(parms, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
   if(rval == NULL)
   {
      // get canonical file name
      char* fname = ap_server_root_relative(pool, arg);
      if(fname == NULL)
      {
         rval = (const char*)apr_psprintf(
            pool, "%s: Invalid policy file '%s'",
            parms->cmd->name, arg);
      }
      else
      {
         // try to open the file
         apr_status_t rv;
         apr_file_t* fd;
         apr_finfo_t finfo;
         rv = apr_file_open(&fd, fname, APR_READ, APR_OS_DEFAULT, pool);
         if(rv == APR_SUCCESS)
         {
            // stat file
            rv = apr_file_info_get(&finfo, APR_FINFO_NORM, fd);
            if(rv == APR_SUCCESS)
            {
               // ensure file is not empty
               apr_size_t length = (apr_size_t)finfo.size;
               if(length <= 0)
               {
                  rval = (const char*)apr_psprintf(
                     pool, "%s: policy file '%s' is empty",
                     parms->cmd->name, fname);
               }
               // read file
               else
               {
                  char* buf = (char*)apr_palloc(pool, length + 1);
                  buf[length] = '\0';
                  rv = apr_file_read_full(fd, buf, length, NULL);
                  if(rv == APR_SUCCESS)
                  {
                     // TODO: validate file
                     // save policy string
                     cfg->policy = buf;
                     cfg->policy_length = length + 1;
                  }
               }

               // close the file
               apr_file_close(fd);
            }
         }

         // handle error case
         if(rv != APR_SUCCESS)
         {
            char errmsg[120];
            rval = (const char*)apr_psprintf(
               pool, "%s: Invalid policy file '%s' (%s)",
               parms->cmd->name, fname,
               apr_strerror(rv, errmsg, sizeof(errmsg)));
         }
      }
   }

   return rval;
}
Example #22
0
/*
 * walk the cache directory tree
 */
static int process_dir(char *path, apr_pool_t *pool)
{
    apr_dir_t *dir;
    apr_pool_t *p;
    apr_hash_t *h;
    apr_hash_index_t *i;
    apr_file_t *fd;
    apr_status_t status;
    apr_finfo_t info;
    apr_size_t len;
    apr_time_t current, deviation;
    char *nextpath, *base, *ext, *orig_basename;
    APR_RING_ENTRY(_direntry) anchor;
    DIRENTRY *d, *t, *n;
    ENTRY *e;
    int skip, retries;
    disk_cache_info_t disk_info;

    APR_RING_INIT(&anchor, _direntry, link);
    apr_pool_create(&p, pool);
    h = apr_hash_make(p);
    fd = NULL;
    skip = 0;
    deviation = MAXDEVIATION * APR_USEC_PER_SEC;

    if (apr_dir_open(&dir, path, p) != APR_SUCCESS) {
        return 1;
    }

    while (apr_dir_read(&info, 0, dir) == APR_SUCCESS && !interrupted) {
        if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) {
            continue;
        }
        d = apr_pcalloc(p, sizeof(DIRENTRY));
        d->basename = apr_pstrcat(p, path, "/", info.name, NULL);
        APR_RING_INSERT_TAIL(&anchor, d, _direntry, link);
    }

    apr_dir_close(dir);

    if (interrupted) {
        return 1;
    }

    skip = baselen + 1;

    for (d = APR_RING_FIRST(&anchor);
         !interrupted && d != APR_RING_SENTINEL(&anchor, _direntry, link);
         d=n) {
        n = APR_RING_NEXT(d, link);
        base = strrchr(d->basename, '/');
        if (!base++) {
            base = d->basename;
        }
        ext = strchr(base, '.');

        /* there may be temporary files which may be gone before
         * processing, always skip these if not in realclean mode
         */
        if (!ext && !realclean) {
            if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN)
                && strlen(base) == AP_TEMPFILE_NAMELEN) {
                continue;
            }
        }

        /* this may look strange but apr_stat() may return errno which
         * is system dependent and there may be transient failures,
         * so just blindly retry for a short while
         */
        retries = STAT_ATTEMPTS;
        status = APR_SUCCESS;
        do {
            if (status != APR_SUCCESS) {
                apr_sleep(STAT_DELAY);
            }
            status = apr_stat(&info, d->basename, DIRINFO, p);
        } while (status != APR_SUCCESS && !interrupted && --retries);

        /* what may happen here is that apache did create a file which
         * we did detect but then does delete the file before we can
         * get file information, so if we don't get any file information
         * we will ignore the file in this case
         */
        if (status != APR_SUCCESS) {
            if (!realclean && !interrupted) {
                continue;
            }
            return 1;
        }

        if (info.filetype == APR_DIR) {
            /* Make a copy of the basename, as process_dir modifies it */
            orig_basename = apr_pstrdup(pool, d->basename);
            if (process_dir(d->basename, pool)) {
                return 1;
            }

            /* If asked to delete dirs, do so now. We don't care if it fails.
             * If it fails, it likely means there was something else there.
             */
            if (deldirs && !dryrun) {
                apr_dir_remove(orig_basename, pool);
            }
            continue;
        }

        if (info.filetype != APR_REG) {
            continue;
        }

        if (!ext) {
            if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN)
                && strlen(base) == AP_TEMPFILE_NAMELEN) {
                d->basename += skip;
                d->type = TEMP;
                d->dsize = info.size;
                apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d);
            }
            continue;
        }

        if (!strcasecmp(ext, CACHE_HEADER_SUFFIX)) {
            *ext = '\0';
            d->basename += skip;
            /* if a user manually creates a '.header' file */
            if (d->basename[0] == '\0') {
                continue;
            }
            t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING);
            if (t) {
                d = t;
            }
            d->type |= HEADER;
            d->htime = info.mtime;
            d->hsize = info.size;
            apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d);
            continue;
        }

        if (!strcasecmp(ext, CACHE_DATA_SUFFIX)) {
            *ext = '\0';
            d->basename += skip;
            /* if a user manually creates a '.data' file */
            if (d->basename[0] == '\0') {
                continue;
            }
            t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING);
            if (t) {
                d = t;
            }
            d->type |= DATA;
            d->dtime = info.mtime;
            d->dsize = info.size;
            apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d);
        }
    }

    if (interrupted) {
        return 1;
    }

    path[baselen] = '\0';

    for (i = apr_hash_first(p, h); i && !interrupted; i = apr_hash_next(i)) {
        void *hvalue;
        apr_uint32_t format;

        apr_hash_this(i, NULL, NULL, &hvalue);
        d = hvalue;

        switch(d->type) {
        case HEADERDATA:
            nextpath = apr_pstrcat(p, path, "/", d->basename,
                                   CACHE_HEADER_SUFFIX, NULL);
            if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY,
                              APR_OS_DEFAULT, p) == APR_SUCCESS) {
                len = sizeof(format);
                if (apr_file_read_full(fd, &format, len,
                                       &len) == APR_SUCCESS) {
                    if (format == DISK_FORMAT_VERSION) {
                        apr_off_t offset = 0;

                        apr_file_seek(fd, APR_SET, &offset);

                        len = sizeof(disk_cache_info_t);

                        if (apr_file_read_full(fd, &disk_info, len,
                                               &len) == APR_SUCCESS) {
                            apr_file_close(fd);
                            e = apr_palloc(pool, sizeof(ENTRY));
                            APR_RING_INSERT_TAIL(&root, e, _entry, link);
                            e->expire = disk_info.expire;
                            e->response_time = disk_info.response_time;
                            e->htime = d->htime;
                            e->dtime = d->dtime;
                            e->hsize = d->hsize;
                            e->dsize = d->dsize;
                            e->basename = apr_pstrdup(pool, d->basename);
                            break;
                        }
                        else {
                            apr_file_close(fd);
                        }
                    }
                    else if (format == VARY_FORMAT_VERSION) {
                        /* This must be a URL that added Vary headers later,
                         * so kill the orphaned .data file
                         */
                        apr_file_close(fd);
                        apr_file_remove(apr_pstrcat(p, path, "/", d->basename,
                                                    CACHE_DATA_SUFFIX, NULL),
                                        p);
                    }
                }
                else {
                    apr_file_close(fd);
                }

            }
            /* we have a somehow unreadable headers file which is associated
             * with a data file. this may be caused by apache currently
             * rewriting the headers file. thus we may delete the file set
             * either in realclean mode or if the headers file modification
             * timestamp is not within a specified positive or negative offset
             * to the current time.
             */
            current = apr_time_now();
            if (realclean || d->htime < current - deviation
                || d->htime > current + deviation) {
                delete_entry(path, d->basename, p);
                unsolicited += d->hsize;
                unsolicited += d->dsize;
            }
            break;

        /* single data and header files may be deleted either in realclean
         * mode or if their modification timestamp is not within a
         * specified positive or negative offset to the current time.
         * this handling is necessary due to possible race conditions
         * between apache and this process
         */
        case HEADER:
            current = apr_time_now();
            nextpath = apr_pstrcat(p, path, "/", d->basename,
                                   CACHE_HEADER_SUFFIX, NULL);
            if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY,
                              APR_OS_DEFAULT, p) == APR_SUCCESS) {
                len = sizeof(format);
                if (apr_file_read_full(fd, &format, len,
                                       &len) == APR_SUCCESS) {
                    if (format == VARY_FORMAT_VERSION) {
                        apr_time_t expires;

                        len = sizeof(expires);

                        apr_file_read_full(fd, &expires, len, &len);

                        apr_file_close(fd);

                        if (expires < current) {
                            delete_entry(path, d->basename, p);
                        }
                        break;
                    }
                }
                apr_file_close(fd);
            }

            if (realclean || d->htime < current - deviation
                || d->htime > current + deviation) {
                delete_entry(path, d->basename, p);
                unsolicited += d->hsize;
            }
            break;

        case DATA:
            current = apr_time_now();
            if (realclean || d->dtime < current - deviation
                || d->dtime > current + deviation) {
                delete_entry(path, d->basename, p);
                unsolicited += d->dsize;
            }
            break;

        /* temp files may only be deleted in realclean mode which
         * is asserted above if a tempfile is in the hash array
         */
        case TEMP:
            delete_file(path, d->basename, p);
            unsolicited += d->dsize;
            break;
        }
    }

    if (interrupted) {
        return 1;
    }

    apr_pool_destroy(p);

    if (benice) {
        apr_sleep(NICE_DELAY);
    }

    if (interrupted) {
        return 1;
    }

    return 0;
}
Example #23
0
/**
 * Perform geographical lookup on target.
 */
int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **error_msg)
{
    apr_sockaddr_t *addr;
    long ipnum = 0;
    char *targetip = NULL;
    geo_db *geo = msr->txcfg->geo;
    char errstr[1024];
    unsigned char buf[2* GEO_MAX_RECORD_LEN];
    const int reclen = 3; /* Algorithm needs changed if this changes */
    apr_size_t nbytes;
    unsigned int rec_val = 0;
    apr_off_t seekto = 0;
    apr_status_t ret;
    int rc;
    int country = 0;
    int level;
    double dtmp;
    int itmp;

    *error_msg = NULL;

    /* init */
    georec->country_code = geo_country_code[0];
    georec->country_code3 = geo_country_code3[0];
    georec->country_name = geo_country_name[0];
    georec->country_continent = geo_country_continent[0];
    georec->region = "";
    georec->city = "";
    georec->postal_code = "";
    georec->latitude = 0;
    georec->longitude = 0;
    georec->dma_code = 0;
    georec->area_code = 0;

    if (msr->txcfg->debuglog_level >= 9) {
        msr_log(msr, 9, "GEO: Looking up \"%s\".", log_escape(msr->mp, target));
    }

    /* NOTE: This only works with ipv4 */
    if ((rc = apr_sockaddr_info_get(&addr, target, APR_INET, 0, 0, msr->mp)) != APR_SUCCESS) {

        *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" failed: %s", log_escape(msr->mp, target), apr_strerror(rc, errstr, 1024));
        msr_log(msr, 4, "%s", *error_msg);
        return 0;
    }
    if ((rc = apr_sockaddr_ip_get(&targetip, addr)) != APR_SUCCESS) {
        *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" failed: %s", log_escape(msr->mp, target), apr_strerror(rc, errstr, 1024));
        msr_log(msr, 4, "%s", *error_msg);
        return 0;
    };

    /* Why is this in host byte order? */
    ipnum = ntohl(addr->sa.sin.sin_addr.s_addr);

    if (msr->txcfg->debuglog_level >= 9) {
        msr_log(msr, 9, "GEO: Using address \"%s\" (0x%08lx). %lu", targetip, ipnum, ipnum);
    }

    ret = apr_global_mutex_lock(msr->modsecurity->geo_lock);
    if (ret != APR_SUCCESS) {
        msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
                get_apr_error(msr->mp, ret));
    }

    for (level = 31; level >= 0; level--) {
        /* Read the record */
        seekto = 2 * reclen * rec_val;
        apr_file_seek(geo->db, APR_SET, &seekto);
        /* TODO: check rc */
        rc = apr_file_read_full(geo->db, &buf, (2 * reclen), &nbytes);

        /* NOTE: This is hard-coded for size 3 records */
        /* Left */
        if ((ipnum & (1 << level)) == 0) {
            rec_val =   (buf[3*0 + 0] << (0*8)) +
                        (buf[3*0 + 1] << (1*8)) +
                        (buf[3*0 + 2] << (2*8));
        }
        /* Right */
        else {
            rec_val =   (buf[3*1 + 0] << (0*8)) +
                        (buf[3*1 + 1] << (1*8)) +
                        (buf[3*1 + 2] << (2*8));
        }

        /* If we are past the country offset, then we are done */
        if (rec_val >= geo->ctry_offset) {
            break;
        }
    }

    if (rec_val == geo->ctry_offset) {
        *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\").", log_escape(msr->mp, target));
        msr_log(msr, 4, "%s", *error_msg);

        ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
        if (ret != APR_SUCCESS) {
            msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
                    get_apr_error(msr->mp, ret));
        }

        return 0;
    }

    if (geo->dbtype == GEO_COUNTRY_DATABASE) {
        country = rec_val;
        country -= geo->ctry_offset;
        if ((country <= 0) || (country > GEO_COUNTRY_LAST)) {
            *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\" (country %d).", log_escape(msr->mp, target), country);
            msr_log(msr, 4, "%s", *error_msg);

            ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
            if (ret != APR_SUCCESS) {
                msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
                        get_apr_error(msr->mp, ret));
            }

            return 0;
        }

        /* Country */
        georec->country_code = geo_country_code[country];
        georec->country_code3 = geo_country_code3[country];
        georec->country_name = geo_country_name[country];
        georec->country_continent = geo_country_continent[country];
    }
    else {
        int field_len = 0;
        int rec_offset = 0;
        int remaining = GEO_CITY_RECORD_LEN;
        unsigned char cbuf[GEO_CITY_RECORD_LEN];

        seekto = rec_val + (2 * reclen - 1) * geo->ctry_offset;
        apr_file_seek(geo->db, APR_SET, &seekto);
        /* TODO: check rc */
        rc = apr_file_read_full(geo->db, &cbuf, sizeof(cbuf), &nbytes);

        country = cbuf[0];
        if ((country <= 0) || (country > GEO_COUNTRY_LAST)) {
            *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\" (country %d).", log_escape(msr->mp, target), country);
            msr_log(msr, 4, "%s", *error_msg);

            ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
            if (ret != APR_SUCCESS) {
                msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
                        get_apr_error(msr->mp, ret));
            }

            return 0;
        }
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: rec=\"%s\"", log_escape_raw(msr->mp, cbuf, sizeof(cbuf)));
        }

        /* Country */
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: country=\"%.*s\"", (1*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf)));
        }
        georec->country_code = geo_country_code[country];
        georec->country_code3 = geo_country_code3[country];
        georec->country_name = geo_country_name[country];
        georec->country_continent = geo_country_continent[country];
        rec_offset++;
        remaining -= rec_offset;

        /* Region */
        field_len = field_length((const char *)cbuf+rec_offset, remaining);
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: region=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
        }
        georec->region = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining));
        rec_offset += field_len + 1;
        remaining -= field_len + 1;

        /* City */
        field_len = field_length((const char *)cbuf+rec_offset, remaining);
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: city=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
        }
        georec->city = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining));
        rec_offset += field_len + 1;
        remaining -= field_len + 1;

        /* Postal Code */
        field_len = field_length((const char *)cbuf+rec_offset, remaining);
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: postal_code=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
        }
        georec->postal_code = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining));
        rec_offset += field_len + 1;
        remaining -= field_len + 1;

        /* Latitude */
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: latitude=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
        }
        dtmp = cbuf[rec_offset] +
               (cbuf[rec_offset+1] << 8) +
               (cbuf[rec_offset+2] << 16);
        georec->latitude = dtmp/10000 - 180;
        rec_offset += 3;
        remaining -= 3;


        /* Longitude */
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: longitude=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
        }
        dtmp = cbuf[rec_offset] +
              (cbuf[rec_offset+1] << 8) +
              (cbuf[rec_offset+2] << 16);
        georec->longitude = dtmp/10000 - 180;
        rec_offset += 3;
        remaining -= 3;

        /* dma/area codes are in city rev1 and US only */
        if (msr->txcfg->debuglog_level >= 9) {
            msr_log(msr, 9, "GEO: dma/area=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4));
        }
        if (geo->dbtype == GEO_CITY_DATABASE_1
            && georec->country_code[0] == 'U'
            && georec->country_code[1] == 'S')
        {
            /* DMA Code */
            itmp = cbuf[rec_offset] +
                  (cbuf[rec_offset+1] << 8) +
                  (cbuf[rec_offset+2] << 16);
            georec->dma_code = itmp / 1000;
            georec->area_code = itmp % 1000;
            rec_offset += 6;
            remaining -= 6;
        }

    }

    *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" succeeded.", log_escape(msr->mp, target));

    ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock);
    if (ret != APR_SUCCESS) {
        msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s",
                get_apr_error(msr->mp, ret));
    }

    return 1;
}
Example #24
0
/** \brief Load GSB database
 *
 * \param dcfg Pointer to directory configuration
 * \param error_msg Error message
 *
 * \retval 1 On Success
 * \retval 0 On Fail
 */
static int gsb_db_create(directory_config *dcfg, char **error_msg)
{
    char errstr[1024];
    apr_pool_t *mp = dcfg->mp;
    gsb_db *gsb = dcfg->gsb;
    apr_int32_t wanted = APR_FINFO_SIZE;
    apr_finfo_t finfo;
    apr_status_t rc;
    apr_size_t nbytes;
    char *buf = NULL, *p = NULL, *savedptr = NULL;
    char *op = NULL;

    if ((rc = apr_file_open(&gsb->db, gsb->dbfn, APR_READ, APR_OS_DEFAULT, mp)) != APR_SUCCESS) {
        *error_msg = apr_psprintf(mp, "Could not open gsb database \"%s\": %s", gsb->dbfn, apr_strerror(rc, errstr, 1024));
        return 0;
    }

    if ((rc = apr_file_info_get(&finfo, wanted, gsb->db)) != APR_SUCCESS)  {
        *error_msg = apr_psprintf(mp, "Could not cannot get gsb malware file information \"%s\": %s", gsb->dbfn, apr_strerror(rc, errstr, 1024));
        apr_file_close(gsb->db);
        return 0;
    }

    buf = (char *)malloc(finfo.size+1);

    if (buf == NULL)   {
        *error_msg = apr_psprintf(mp, "Could not alloc memory for gsb data");
        apr_file_close(gsb->db);
        return 0;
    }

    rc = apr_file_read_full(gsb->db, buf, finfo.size, &nbytes);

    gsb->gsb_table = apr_hash_make(dcfg->mp);

    if (gsb->gsb_table == NULL)   {
        *error_msg = apr_psprintf(mp, "Could not alloc memory for gsb table");
        free(buf);
        buf = NULL;
        apr_file_close(gsb->db);
        return 0;
    }

    p = apr_strtok(buf,"\t",&savedptr);

    while (p != NULL)   {

        op = strchr(p,'+');

        if(op != NULL)   {
            char *hash = ++op;
            if(strlen(hash) == 32)
            apr_hash_set(gsb->gsb_table, hash, APR_HASH_KEY_STRING, "malware");
        }

        op = strchr(p,'-');

        if(op != NULL)   {
            char *hash = ++op;
            if(strlen(hash) == 32)
            apr_hash_set(gsb->gsb_table, hash, APR_HASH_KEY_STRING, NULL);
        }

        p = apr_strtok(NULL,"\t",&savedptr);
    }

    apr_file_close(gsb->db);

    free(buf);
    buf = NULL;

    return 1;
}
Example #25
0
void nx_config_cache_read()
{
    nx_ctx_t *ctx;
    apr_off_t offset = 0;
    char *buf = NULL;
    apr_status_t rv;
    apr_size_t nbytes, bytesread, bytesleft;
    nx_value_t *version = NULL;
    apr_file_t *ccfile;
    nx_exception_t e;

    ctx = nx_ctx_get();

    if ( ctx->nocache == TRUE )
    {
	return;
    }

    log_debug("reading config cache from %s", ctx->ccfilename);
    rv = apr_file_open(&ccfile, ctx->ccfilename,
		       APR_READ, APR_OS_DEFAULT, ctx->pool);
    if ( APR_STATUS_IS_ENOENT(rv) )
    { // nothing to read
	return;
    }
    CHECKERR_MSG(rv, "couldn't open config cache '%s'", ctx->ccfilename);

    try
    {
	CHECKERR_MSG(apr_file_seek(ccfile, APR_END, &offset),
		     "couldn't seek in cache file");
	if ( offset > NX_CONFIG_CACHE_LIMIT )
	{
	    throw_msg("cache file is too large (%d bytes)", offset);
	}
	if ( offset > 0 )
	{
	    nbytes = (apr_size_t) offset;
	    
	    buf = malloc((size_t) offset);

	    // seek back to start
	    offset = 0;
	    CHECKERR_MSG(apr_file_seek(ccfile, APR_SET, &offset),
			 "couldn't seek in cache file");

	    // read cache file into memory
	    if ( (rv = apr_file_read_full(ccfile, buf, nbytes, &bytesread)) != APR_SUCCESS )
	    {
		if ( rv != APR_EOF )
		{
		    CHECKERR_MSG(rv, "failed to read config cache file");
		}
	    }
	    
	    if ( nbytes != bytesread )
	    {
		throw_msg("read %d bytes, wanted %d", (int) bytesread, (int) nbytes);
	    }
	    bytesleft = nbytes;
	    
	    version = nx_value_from_membuf(buf, nbytes, &bytesread);
	    if ( version->type != NX_VALUE_TYPE_STRING )
	    {
		throw_msg("string expected for config cache version");
	    }
	    if ( strcmp(version->string->buf, NX_CONFIG_CACHE_VERSION) != 0 )
	    {
		throw_msg("config cache version mismatch, expected %s, got %s",
			  NX_CONFIG_CACHE_VERSION, version->string->buf);
	    }
	    
	    bytesleft -= bytesread;
	    while ( bytesleft > 0 )
	    {
		_read_item(buf + (nbytes - bytesleft), bytesleft,
			   ctx->config_cache, &bytesread);
		ASSERT(bytesread <= bytesleft);
		bytesleft -= bytesread;
	    }
	}
    }
    catch(e)
    {
	apr_file_close(ccfile);
	apr_file_remove(ctx->ccfilename, NULL);
	if ( buf != NULL )
	{
	    free(buf);
	}
	if ( version != NULL )
	{
	    nx_value_free(version);
	}
	rethrow_msg(e, "failed to read config cache");
    }

    if ( buf != NULL )
    {
	free(buf);
    }
    if ( version != NULL )
    {
	nx_value_free(version);
    }
    apr_file_close(ccfile);
    //apr_file_remove(ctx->ccfilename, NULL);
}
Example #26
0
/* 初始化unicode映射表 */
apr_status_t msc_unicode_map_init(apr_pool_t *mp)
{
    char errstr[1024];
    unicode_map *u_map;
    apr_int32_t wanted = APR_FINFO_SIZE;
    apr_finfo_t finfo;
    apr_status_t rc;
    apr_size_t nbytes;
    unsigned int codepage = 0;
    char *buf = NULL, *p = NULL, *savedptr = NULL;
    char *ucode = NULL, *hmap = NULL;
    int found = 0, processing = 0;
    int Code = 0, Map = 0;

    if(unicode_map_table != NULL)   {
        free(unicode_map_table);
        unicode_map_table = NULL;
    }

    u_map = apr_pcalloc(mp, sizeof(unicode_map));
    if (u_map == NULL)  {
        return -1;
    }

    u_map->map = NULL;   
    u_map->mapfn = ap_server_root_relative(mp, DEF_UNICODEMAPFILE_VAL); 
    
    if ((rc = apr_file_open(&u_map->map, u_map->mapfn, APR_READ, APR_OS_DEFAULT, mp)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Could not open unicode map file \"%s\": %s", 
            u_map->mapfn, apr_strerror(rc, errstr, 1024));
        return -1;
    }

    if ((rc = apr_file_info_get(&finfo, wanted, u_map->map)) != APR_SUCCESS)  {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
            "Could not get unicode map file information \"%s\": %s", u_map->mapfn, 
            apr_strerror(rc, errstr, 1024));
        apr_file_close(u_map->map);
        return -1;
    }

    buf = (char *)malloc(finfo.size + 1);
    if (buf == NULL)   {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,  "Could not alloc memory for unicode map");
        apr_file_close(u_map->map);
        return -1;
    }

    rc = apr_file_read_full(u_map->map, buf, finfo.size, &nbytes);

    if (unicode_map_table != NULL)  {
        memset(unicode_map_table, -1, (sizeof(int)*65536));
    } else {
        unicode_map_table = (int *)malloc(sizeof(int) * 65536);
        if (unicode_map_table == NULL) {
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Could not alloc memory for unicode map");
            free(buf);
            buf = NULL;
            apr_file_close(u_map->map);
            return -1;
        }

        memset(unicode_map_table, -1, (sizeof(int)*65536));
    }

    /* Setting some unicode values - http://tools.ietf.org/html/rfc3490#section-3.1 */

    /* Set 0x3002 -> 0x2e */
    unicode_map_table[0x3002] = 0x2e;
    /* Set 0xFF61 -> 0x2e */
    unicode_map_table[0xff61] = 0x2e;
    /* Set 0xFF0E -> 0x2e */
    unicode_map_table[0xff0e] = 0x2e;
    /* Set 0x002E -> 0x2e */
    unicode_map_table[0x002e] = 0x2e;

    p = apr_strtok(buf, CODEPAGE_SEPARATORS, &savedptr);

    while (p != NULL) {

        codepage = atol(p);

        if (codepage == unicode_codepage) {
            found = 1;
        }

        if (found == 1 && (strchr(p,':') != NULL)) {
            char *mapping = strdup(p);
            processing = 1;

            if(mapping != NULL) {
                ucode = apr_strtok(mapping,":", &hmap);
                sscanf(ucode,"%x",&Code);
                sscanf(hmap,"%x",&Map);
                if(Code >= 0 || Code <= 65535) {
                    unicode_map_table[Code] = Map;
                }

                free(mapping);
                mapping = NULL;
            }
        }

        if (processing == 1 && (strchr(p,':') == NULL)) {
            free(buf);
            buf = NULL;
            break;
        }

        p = apr_strtok(NULL,CODEPAGE_SEPARATORS,&savedptr);
    }

    apr_file_close(u_map->map);
    free(buf);
    buf = NULL;

    apr_pool_cleanup_register(mp, (const void *)unicode_map_table, msc_unicode_map_destroy, 
        apr_pool_cleanup_null);

    return APR_SUCCESS;    
}
Example #27
0
apr_status_t sha1_file(const std::string& filename, std::string& checksum, bool binary, apr_pool_t* parentPool)
{
  apr_status_t ret = APR_SUCCESS;

  apr_pool_t* pool = NULL;
  ret = apr_pool_create(&pool, parentPool);
  if(ret == APR_SUCCESS)
  {
    apr_file_t* in = NULL;
    apr_int32_t flags = (binary ? APR_READ | APR_BINARY : APR_READ);

    ret = apr_file_open(&in, filename.c_str(), flags, APR_OS_DEFAULT, pool);
    if(ret == APR_SUCCESS)
    {
      unsigned char digest[APR_SHA1_DIGESTSIZE + 1];
      memset(digest, 0, APR_SHA1_DIGESTSIZE + 1);

      apr_sha1_ctx_t context;
      apr_sha1_init(&context);

      unsigned char buffer[512];
      memset(buffer, 0, sizeof(buffer));

      apr_size_t bytes_read = 0;
      ret = apr_file_read_full(in, buffer, sizeof(buffer) - 1, &bytes_read);

      if(ret == APR_SUCCESS || ret == APR_EOF)
      {
        if(binary) apr_sha1_update_binary(&context, buffer, bytes_read);
        else apr_sha1_update(&context, (const char*)buffer, bytes_read);
      }

      while(ret == APR_SUCCESS)
      {
        ret = apr_file_read_full(in, buffer, sizeof(buffer) - 1, &bytes_read);
        if(ret == APR_SUCCESS || ret == APR_EOF)
        {
          if(binary) apr_sha1_update_binary(&context, buffer, bytes_read);
          else apr_sha1_update(&context, (const char*)buffer, bytes_read);
        }
      }

      apr_sha1_final(digest, &context);

      if(ret == APR_EOF)
      {
        std::ostringstream oss;
        for(int i = 0; i < APR_SHA1_DIGESTSIZE; i++)
        {
          unsigned short letter = digest[i];
          oss << std::hex << std::setw(2) << std::setfill('0') << letter;
        }
        checksum = oss.str();
        ret = APR_SUCCESS;
      }
      apr_file_close(in);
    }
    apr_pool_destroy(pool);
  }
  
  return ret;
}