Beispiel #1
0
int papi_read_body (request_rec *r, char **buffer)
{
	char buf[MAX_SIZE+1];
	size_t bytes, count = 0;
	
	*buffer = apr_pstrdup (r->pool, "");
	
	if (ap_setup_client_block (r, REQUEST_CHUNKED_DECHUNK) != OK) {
		APACHE_LOG (APLOG_ERR, "Bad request body!");
		return HTTP_BAD_REQUEST;
	}
	
	if (ap_should_client_block (r)) {
		for (bytes = ap_get_client_block (r, buf, MAX_SIZE); 
			 bytes > 0;
			 bytes = ap_get_client_block (r, buf, MAX_SIZE)) {
				 (*buffer)[bytes-1] = '\0';
				 *buffer = apr_pstrcat (r->pool, *buffer, buf, NULL);
				 count += bytes;
			 }
	} else {
		APACHE_LOG (APLOG_WARNING, "No request body.");
	}
	(*buffer)[count-1] = '\0';

	return OK;
}
/*
 * Send request body (if any)
 */
static int send_request_body(request_rec *r, proxy_conn_rec *conn)
{
    if (ap_should_client_block(r)) {
        char *buf = apr_palloc(r->pool, AP_IOBUFSIZE);
        int status;
        apr_size_t readlen;

        readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE);
        while (readlen > 0) {
            status = sendall(conn, buf, readlen, r);
            if (status != OK) {
                return HTTP_SERVICE_UNAVAILABLE;
            }
            readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE);
        }
        if (readlen == -1) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "proxy: " PROXY_FUNCTION ": receiving request body "
                          "failed");
            return HTTP_INTERNAL_SERVER_ERROR;
        }
    }

    return OK;
}
Beispiel #3
0
static char* cwx_read_post(request_rec *r){
    char *data=0;
    const char *type;
    char buf[4096];
    int rc = OK;
    if(r->method_number != M_POST) return 0;

    type = (char*)apr_table_get(r->headers_in, "Content-Type");
    if(strcasecmp(type, "application/x-www-form-urlencoded") != 0) return 0;

    if (ap_should_client_block(r)) {
        int rsize, len_read, rpos=0;
        long length = r->remaining;
        data = (char*)apr_pcalloc(r->pool, length + 1);
        while ((len_read =
            ap_get_client_block(r, buf, sizeof(buf))) > 0) { 
                if (rpos + len_read > length) {
                    rsize = length - rpos;
                }else {
                    rsize = len_read;
                }
                memcpy(data + rpos, buf, rsize);
                rpos += rsize;
        }
        data[rpos] = 0x00;
    }
    return data;

}
Beispiel #4
0
/**
 * Use this function to read the body from request_rec
 * Pointer to data will be set to body
 * Returns -1 if failed
 */
static int read_body(request_rec *r, char **body) {
    *body = NULL;
    int ret = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
    if(OK == ret && ap_should_client_block(r)) {
        char* buffer = apr_pcalloc(r->pool, BLOCKSIZE);
        int len;
        char *data = apr_pcalloc(r->pool, 1);
        int d_size = 0;

        data[0] = '\0';
        // Read body
        while((len=ap_get_client_block(r, buffer, BLOCKSIZE)) > 0) {
            char *tmp;

            // there is no apr_realloc
            tmp = apr_pcalloc(r->pool, d_size + len + 1);
            memcpy(tmp, data, d_size + 1);
            data = tmp;

            memcpy(&(data[d_size]), buffer, len);
            d_size += len;
            data[d_size] = '\0';
        }
        if (len == -1) {
            return -1;
        }
        *body = data;
        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "requrest_rec body[%s]", data);
        return 0;
    }
    return -1;
}
static char*
mapserver_read_post_data (request_rec *r)
{
  int   status;
  int   size;
  long  blen, rsize, rpos = 0;
  char *buffer = NULL;
  char  buf [512];

  if ((status = ap_setup_client_block (r, REQUEST_CHUNKED_ERROR)) != OK)
    return NULL;

  if (!ap_should_client_block (r))
    return NULL;

  buffer = (char*) apr_palloc (r->pool, r->remaining + 1);
  size = r->remaining;
  buffer [size] = '\0';

  if (!buffer)
    return NULL;

  while ((blen = ap_get_client_block (r, buf, sizeof (buf))) > 0) {
    if (rpos + blen > size) {
      rsize = blen - rpos;
    } else {
      rsize = blen;
    }
    memcpy ((char*) buffer + rpos, buf, rsize);
    rpos += rsize;
  }

  return buffer;
}
Beispiel #6
0
static void
discard_data(request_rec *r)
{
#ifdef APACHE2
	(void) ap_discard_request_body(r);
#else
	/*
	 * This is taken from ap_discard_request_body().  The reason we can't
	 * just use it in Apache 1.3 is that it does various timeout things we
	 * don't want it to do.  Apache 2.0 doesn't do that, so we can safely
	 * use the normal function.
	 */
	if (r->read_chunked || r->remaining > 0) {
		char dumpbuf[HUGE_STRING_LEN];
		int i;

		do {
			i = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN);
#ifdef DEBUG
			dump_buffer(stderr, "discarded", dumpbuf, i);
#endif
		} while (i > 0);
	}
#endif
}
Beispiel #7
0
const char * ws::apache2request::body() {
  if(_body != 0) {
    return _body;
  }
  if(ap_setup_client_block(__rr, REQUEST_CHUNKED_ERROR)) {
    return _body;
  }
  if(!ap_should_client_block(__rr)) {
    return _body;
  }
  apr_off_t length = __rr->remaining;

  apr_off_t len_read, rsize, rpos = 0;
  char argsbuffer[HUGE_STRING_LEN];
  _body = (char*) apr_pcalloc(__rr->pool, (apr_size_t) (length + 1));
  while((len_read = ap_get_client_block(__rr, argsbuffer, sizeof(argsbuffer))) > 0) {
    if((rpos + len_read) > length) {
      rsize = length - rpos;
    } else {
      rsize = len_read;
    }
    memcpy(_body + rpos, argsbuffer, (size_t) rsize);
    rpos += rsize;
  }
  return _body;
}
Beispiel #8
0
static int util_read(request_rec *r, char **rbuf, apr_off_t *size) {
    int rc = OK;
    *size = 0;
    if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
        return (rc);
    }

    if (ap_should_client_block(r)) {
        char argsbuffer[WEBGFARM_BUFFER_SIZE];
        apr_off_t rsize, len_read, rpos = 0;

        apr_off_t length = r->remaining;

        *rbuf = (char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1));
        *size = length;
        while ((len_read = ap_get_client_block(r, argsbuffer, sizeof (argsbuffer))) > 0) {
            if ((rpos + len_read) > length) {
                rsize = length - rpos;
            } else {
                rsize = len_read;
            }

            memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize);
            rpos += rsize;
        }
    }
    return (rc);
}
Beispiel #9
0
/**
 * Read s bytes into buffer b from request r
 * @param void * b a pre-allocated buffer
 * @param size_t s the amount of bytes to read
 * @param request_rec r The 
 * @return int the amount of bytes read or -1 in case of an error
 **/
int mod_parrot_read(void * b, size_t s, request_rec * r) {
    apr_off_t count = r->read_length;
    if (ap_get_client_block(r, b, s) > 0) {
        return r->read_length - count;
    } 
    return -1;
}
Beispiel #10
0
/**
 * gets content if this is notification.
 */
static int content_read(request_rec *r, char **rbuf)
{
    int rc;
    int rsize, len_read, rpos = 0;

    if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
	return -1;
    }

    if (ap_should_client_block(r)) {
	char argsbuffer[HUGE_STRING_LEN];
	long length = r->remaining;
	*rbuf = ap_pcalloc(r->pool, length+1);
	ap_hard_timeout("content_read", r);

	while ((len_read = ap_get_client_block(r, argsbuffer,
	    sizeof(argsbuffer))) > 0)
	{
	    ap_reset_timeout(r);

	    if ((rpos + len_read) > length) {
		rsize = length -rpos;
	    } else {
		rsize = len_read;
	    }

	    memcpy((char*) *rbuf + rpos, argsbuffer, rsize);
	    rpos = rpos + rsize;
	}

	ap_kill_timeout(r);
    }
    am_web_log_debug("in content_read: rpos=%d", rpos);
    return rpos;
}
/**
 * handles a client request
 */
static int
write_request(stream_t *s, request_rec *r,
	      config_t *config, cluster_t *cluster, int *keepalive,
              int session_index, int backup_index,
              char *ip, char *session_id)
{
  int len;
  int code;
  int write_length;
  time_t new_time;
  time_t start_time = r->request_time;

  hmux_start_channel(s, 1);
  write_env(s, r, session_id);
  write_headers(s, r);
  write_added_headers(s, r);

  /* read post data */
  if (ap_should_client_block(r)) {
    char buf[BUF_LENGTH];
    int ack_size = s->cluster_srun->srun->send_buffer_size;
    int send_length = 0;

    while ((len = ap_get_client_block(r, buf, BUF_LENGTH)) > 0) {
      /* ap_reset_timeout(r); */
      cse_write_packet(s, HMUX_DATA, buf, len);

      send_length += len;
      
      if (ack_size <= send_length) {
	send_length = 0;
	cse_write_byte(s, HMUX_YIELD);
        code = send_data(s, r, HMUX_ACK, keepalive);
        if (code < 0 || code == HMUX_QUIT || code == HMUX_EXIT)
          break;
      }
    }
  }

  cse_write_byte(s, HMUX_QUIT);

  code = send_data(s, r, HMUX_QUIT, keepalive);

  if (code >= 0 || s->sent_data)
    return code;
  
  write_length = s->write_length; 
  if (cse_open_connection(s, cluster, session_index, backup_index,
                          r->request_time, r->pool)) {
    s->write_length = write_length;
    LOG(("retry connection %d\n", s->socket));
    
    return send_data(s, r, HMUX_QUIT, keepalive);
  }
  else {
    return HTTP_SERVICE_UNAVAILABLE;
  }
}
Beispiel #12
0
static void fill_buffer( mcontext *c, value buf, int *len ) {
	int pos = *len;
	while( pos < BUFSIZE ) {
		int k = ap_get_client_block(c->r,val_string(buf)+pos,BUFSIZE-pos);
		if( k == 0 )
			break;
		pos += k;
	}
	*len = pos;
}
Beispiel #13
0
static int do_stream_data( void *_c, char *buf, int size ) {
	mcontext *c = (mcontext*)_c;
	// startup
	if( size == 0 ) {
		if( !ap_should_client_block(c->r) )
			return -1;
		c->need_discard = true;
		return 0;
	}
	return ap_get_client_block(c->r,buf,size);
}
Beispiel #14
0
CAMLprim value
netcgi2_apache_request_get_client_block_buffered(value rv, value bufv,
        value ofsv, value lenv)
{
    CAMLparam4(rv, bufv, ofsv, lenv);
    request_rec *r = Request_rec_val(rv);
    int ofs = Int_val(ofsv);
    int len = Int_val(lenv);
    int i;

    i = ap_get_client_block (r, String_val(bufv) + ofs, len);
    /* Error dealt with on the Caml side. */
    CAMLreturn(Val_int(i));
}
Beispiel #15
0
static POSTDATA_T* SmartHome_handler_get_post_data(request_rec *r)
{
	int  ret = 0;
	int  pos = 0;
	ret = ap_setup_client_block(r,REQUEST_CHUNKED_ERROR);
	printf("request_rec->ap_setup_client_block() = %d\r\n",ret);	
	printf("request_rec->ap_get_client_block()\r\n");
	pos = 0;
	while((ret = ap_get_client_block(r,sys.post_data.data+pos,sizeof(ap_get_client_block)))>0){
		pos+=ret;
	}
	sys.post_data.len = pos;
	return &sys.post_data;
}
Beispiel #16
0
static mrb_value ap_mrb_get_request_body(mrb_state *mrb, mrb_value str)
{
  char *val;
  int len;
  request_rec *r = ap_mrb_get_request();
  if (r->method_number == M_POST) {
    ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
    len = r->remaining;
    val = apr_pcalloc(r->pool, len);
    ap_should_client_block(r);
    ap_get_client_block(r, val, len);
    return mrb_str_new(mrb, val, len);
  }
  return mrb_nil_value();
}
/**
 * handles a client request
 */
static int
write_request(stream_t *s, request_rec *r, config_t *config,
	      int session_index, int backup_index)
{
  int len;
  int code = -1;

  write_env(s, r);
  write_headers(s, r);
  write_added_headers(s, r);

  /* read post data */
  if (ap_should_client_block(r)) {
    char buf[BUF_LENGTH];
    int ack_size = s->cluster_srun->srun->send_buffer_size;
    int send_length = 0;

    while ((len = ap_get_client_block(r, buf, BUF_LENGTH)) > 0) {
      LOG(("%s:%d:write-request(): w-D %d\n", __FILE__, __LINE__, len));
      
      if (ack_size <= send_length + len && send_length > 0) {
        LOG(("%s:%d:write-request(): w-Y send_length=%d ack_size=%d\n",
             __FILE__, __LINE__, send_length, ack_size));
        
	send_length = 0;
	cse_write_byte(s, HMUX_YIELD);
        code = send_data(s, r);
        if (code != HMUX_ACK)
          break;
      }

      cse_write_packet(s, HMUX_DATA, buf, len);

      send_length += len;
    }
  }

  LOG(("%s:%d:write-request(): w-Q\n", __FILE__, __LINE__));

  cse_write_byte(s, HMUX_QUIT);
  code = send_data(s, r);

  LOG(("%s:%d:write_request(): return code %c\n", __FILE__, __LINE__, code));

  return code;
}
Beispiel #18
0
static void readPostData(request_rec* r) {
	int rc;
	if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
		ap_rprintf(r, "readPostData\trc\t[%d]<br>", rc);
	} else {
		if (ap_should_client_block(r)) {
			char data[HUGE_STRING_LEN];
			int rsize, len_read, rpos=0;
			long length = r->remaining;
			while ((len_read = ap_get_client_block(r, data, sizeof(data))) > 0) {
				ap_rprintf(r, "Read Data : <br>[%s]<br>", data);
			}
		} else {
			ap_rprintf(r, "readPostData\t[NULL]<br>");
		}
	}
}
Beispiel #19
0
void ssl_io_suck(request_rec *r, SSL *ssl)
{
    int rc;
    int len;
    char *buf;
    int buflen;
    char c;
    int sucked;

    if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) == OK) {
        if (ap_should_client_block(r)) {

            /* read client request block through Apache API */
            buflen = HUGE_STRING_LEN;
            buf = ap_palloc(r->pool, buflen);
            ap_hard_timeout("SSL I/O request body pre-sucking", r);
            sucked = 0;
            ssl_io_suck_start(r);
            while ((len = ap_get_client_block(r, buf, buflen)) > 0) {
                ssl_io_suck_record(r, buf, len);
                sucked += len;
                ap_reset_timeout(r);
            }
            ssl_io_suck_end(r);
            ap_kill_timeout(r);

            /* suck trailing data (usually CR LF) which 
               is still in the Apache BUFF layer */
            ap_hard_timeout("SSL I/O request trailing data pre-sucking", r);
            while (ap_bpeekc(r->connection->client) != EOF) {
                c = ap_bgetc(r->connection->client);
                ssl_io_suck_record(r, &c, 1);
                sucked++;
            }
            ap_kill_timeout(r);

            ssl_log(r->server, SSL_LOG_TRACE, 
                    "I/O: sucked %d bytes of input data from SSL/TLS I/O layer "
                    "for delayed injection into Apache I/O layer", sucked);
        }
    }
    return;
}
Beispiel #20
0
/*
** Binding to ap_get_client_block.
** Uses the request_rec defined as an upvalue.
** Receives a number of bytes to read.
** Returns a string or nil if EOS.
*/
static int req_get_client_block (lua_State *L)
{
  request_rec *r = CHECK_REQUEST_OBJECT(1);
  char buffer[ML_POST_BUFFER_SIZE + 1];
  int bytesleft = luaL_optint (L, 2, ML_POST_BUFFER_SIZE);
  int status, n;
  int count = 0;
  if (bytesleft < 0)
  {
    luaL_error (L, "block size must be positive");
    return 0;
  }
  while (bytesleft)
  {
    n = (bytesleft > ML_POST_BUFFER_SIZE) ? ML_POST_BUFFER_SIZE : bytesleft;
    status = ap_get_client_block (r, buffer, n);
    if (status == 0)   /* end-of-body */
    {
      if (r->remaining > 0)
        continue; /* still has something to read */
      else
        break; /* end-of-stream */
    }
    else if (status == -1)     /* error or premature chunk end */
    {
      lua_pushnil (L);
      lua_pushstring (L, "error getting client block");
      return 2;
    }
    else
    {
      bytesleft -= status;
      lua_pushlstring (L, buffer, status);
      count++;
    }
  }
  /* is this necessary? */
  if (count)
    lua_concat (L, count);
  else
    lua_pushnil (L);
  return 1;
}
Beispiel #21
0
static int read_chars (lua_State *L, request_rec* r, size_t n)
{
  size_t len;
  char tmpbuf[HUGE_STRING_LEN];

  len = HUGE_STRING_LEN;  /* try to read that much each time */

  if (len > n)  len = n;

  if ( (len = ap_get_client_block(r, tmpbuf, len)) > 0)
  {
    lua_pushlstring(L, tmpbuf, len);
    return 1;
  }
  else
    ap_discard_request_body(r);

  return 0;
}
Beispiel #22
0
  int request_parser::read_body(char*& rbuf, std::size_t& rbufLen) const
  {
    /*~~~~~~~~*/
      int rc = OK;
      /*~~~~~~~~*/

      if((rc = ap_setup_client_block(m_r, REQUEST_CHUNKED_ERROR))) {
          return(rc);
      }

      if(ap_should_client_block(m_r)) {

          /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
          char         argsbuffer[HUGE_STRING_LEN];
          apr_off_t    rsize, len_read, rpos = 0;
          apr_off_t length = m_r->remaining;
          /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

          rbuf = static_cast<char*>(apr_pcalloc(m_r->pool, (apr_size_t) (length + 1)));
          rbufLen = length;
          
          // We will not read body greater than limit 
          if (static_cast<grader::request_parser::size_type>(length) > grader::request_parser::MAX_BODY_LENGTH)
            return (HTTP_REQUEST_ENTITY_TOO_LARGE);
          
          while((len_read = ap_get_client_block(m_r, argsbuffer, sizeof(argsbuffer))) > 0) 
          {
              if((rpos + len_read) > length) 
              {
                  rsize = length - rpos;
              }
              else 
              {
                  rsize = len_read;
              }

              memcpy(rbuf + rpos, argsbuffer, (size_t) rsize);
              rpos += rsize;
          }
      }
      return(rc);
  }
Beispiel #23
0
static int util_read(ApacheRequest *req, const char **rbuf)
{
    request_rec *r = req->r;
    int rc = OK;

    if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
	return rc;
    }

    if (ap_should_client_block(r)) {
	char buff[HUGE_STRING_LEN];
	int rsize, len_read, rpos=0;
	long length = r->remaining;

	if (length > req->post_max && req->post_max > 0) {
	    ap_log_rerror(REQ_ERROR, "[libapreq] entity too large (%d, max=%d)",
			  (int)length, req->post_max);
	    return HTTP_REQUEST_ENTITY_TOO_LARGE;
	}

	*rbuf = ap_pcalloc(r->pool, length + 1);

	ap_hard_timeout("[libapreq] util_read", r);

	while ((len_read =
		ap_get_client_block(r, buff, sizeof(buff))) > 0) {
	    if ((rpos + len_read) > length) {
		rsize = length - rpos;
	    }
	    else {
		rsize = len_read;
	    }
	    memcpy((char*)*rbuf + rpos, buff, rsize);
	    rpos += rsize;
	}

	ap_kill_timeout(r);
    }

    return rc;
}
static int wrap_read (void *data, char *buf, size_t len)
{
  WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
  int ret;
  int x = 0;

#if ECS_DEBUG>1
  fprintf (stderr, "wrap_read (%s, %d)\n", buf, len);
#endif
  do
  {
    ret = ap_get_client_block(wrap->r, buf + x, len - x);
    if (ret <= 0) break;
    x += ret;
  } while (x < len);
#if ECS_DEBUG>1
  fprintf (stderr, "done ap_get_client_block\n");
#endif
  if (ret < 0) return ret;
  return x;
}
Beispiel #25
0
CAMLprim value
netcgi2_apache_request_get_client_block (value rv)
{
    CAMLparam1 (rv);
    CAMLlocal1 (str);
    request_rec *r = Request_rec_val (rv);
    const int huge_string_len = 8192; /* Same as Apache's HUGE_STRING_LEN. */
    char buffer [huge_string_len];
    int i;

    str = Val_unit;
    i = ap_get_client_block (r, buffer, huge_string_len);
    if (i == -1) {
        /* FIXME: It seems there is now way to get more info about the error. */
        caml_failwith("ap_get_client_block");
    }

    str = alloc_string (i);
    memcpy (String_val (str), buffer, i);

    CAMLreturn (str);
}
/** 
gsoap function that requests the next piece of data from us
*/
static size_t
frecv(struct soap *psoap, char *pBuf, apr_size_t len)
{
    request_rec *r = NULL;
    apr_size_t nRet = 0;
    gsoapRequestConfiguration *pRqConf = getRequestConfiguration(psoap);

    if (NULL != pRqConf)
    {
        r = pRqConf->r;
        if (!pRqConf->headers_received)
        {
            apr_table_do(send_header_to_gsoap, psoap, r->headers_in, NULL);
            pRqConf->headers_received = TRUE;
        }
        /*
         * Steven Elliott <*****@*****.**>:
         * It's not obvious from Apache documentation documentation how
         * exactly ap_get_client_block() should be called in both the chunked
         * and non-chunked cases.  In the chunked case r->remaining is zero,
         * so that can't be an upper bound to the number of bytes read.
         * However, this site:
         *   http://docstore.mik.ua/orelly/apache_mod/139.htm 
         * cautions that "If you are handling non-chunked data, do not try to
         * read more than the number of bytes declared in Content-length
         * because this may cause the attempted read to block indefinitely."
         * Consequently my best guess, with regard to what is safe, is in the
         * non-chunked case continue doing as mod_gsoap has done in the past
         * and limit the upper bound to r->remaining.  In the chunked case
         * read "len", which almost certainly exceeds what was posted.
         * Hopefully if ap_get_client_block() blocks it returns no later than 
         * when the current post is complete regardless of chunking or
         * keep-alive.
         */
        nRet = ap_get_client_block(r, pBuf,
            r->read_chunked ? len : (len > r->remaining ? r->remaining : len));
    }
    return nRet;
}
Beispiel #27
0
static ssize_t
read_data(void *fd, void *buf, size_t siz)
{
	ssize_t len_read;
	request_rec *ap_r = (request_rec *)fd;

	len_read = ap_get_client_block(ap_r, buf, siz);
#ifndef APACHE2
	ap_reset_timeout(ap_r);
#endif

#ifdef DEBUG
	fprintf(stderr, "read_data(0x%8.8x, 0x%8.8x, %d): %d",
			fd, buf, siz, len_read);
	if (len_read < 0)
		fprintf(stderr, ": %s", strerror(errno));
	putc('\n', stderr);
	dump_buffer(stderr, "read_data:", buf, len_read);
#endif

	return (len_read);
}
Beispiel #28
0
BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) {
    request_rec *r = ((isapi_cid *)ConnID)->r;
    DWORD read = 0;
    int res;

    if (r->remaining < (long) *lpdwSize)
        *lpdwSize = r->remaining;

    while (read < *lpdwSize &&
           ((res = ap_get_client_block(r, (char*)lpvBuffer + read,
                                       *lpdwSize - read)) > 0)) {
        if (res < 0) {
            *lpdwSize = 0;
            if (!GetLastError())
                SetLastError(ERROR); /* XXX: Find the right error code */
            return FALSE;
        }

        read += res;
    }

    *lpdwSize = read;
    return TRUE;
}
Beispiel #29
0
int ApacheRequest_parse_multipart(ApacheRequest *req)
{
    request_rec *r = req->r;
    int rc = OK;
    const char *ct = ap_table_get(r->headers_in, "Content-Type");
    long length;
    char *boundary;
    multipart_buffer *mbuff;
    ApacheUpload *upload = NULL;

    if (!ct) {
	ap_log_rerror(REQ_ERROR, "[libapreq] no Content-type header!");
	return HTTP_INTERNAL_SERVER_ERROR;
    }

    if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
        return rc;
    }

    if (!ap_should_client_block(r)) {
	return rc;
    }

    if ((length = r->remaining) > req->post_max && req->post_max > 0) {
	ap_log_rerror(REQ_ERROR, "[libapreq] entity too large (%d, max=%d)",
		     (int)length, req->post_max);
	return HTTP_REQUEST_ENTITY_TOO_LARGE;
    }

    (void)ap_getword(r->pool, &ct, '=');
    boundary = ap_getword_conf(r->pool, &ct);

    if (!(mbuff = multipart_buffer_new(boundary, length, r))) {
	return DECLINED;
    }

    while (!multipart_buffer_eof(mbuff)) {
	table *header = multipart_buffer_headers(mbuff);
	const char *cd, *param=NULL, *filename=NULL;
	char buff[FILLUNIT];
	int blen, wlen;

	if (!header) {
#ifdef DEBUG
            ap_log_rerror(REQ_ERROR,
		      "[libapreq] silently drop remaining '%ld' bytes", r->remaining);
#endif
            ap_hard_timeout("[libapreq] parse_multipart", r);
            while ( ap_get_client_block(r, buff, sizeof(buff)) > 0 )
                /* wait for more input to ignore */ ;
            ap_kill_timeout(r);
	    return OK;
	}

	if ((cd = ap_table_get(header, "Content-Disposition"))) {
	    const char *pair;

	    while (*cd && (pair = ap_getword(r->pool, &cd, ';'))) {
		const char *key;

		while (ap_isspace(*cd)) {
		    ++cd;
		}
		if (ap_ind(pair, '=')) {
		    key = ap_getword(r->pool, &pair, '=');
		    if(strEQ(key, "name")) {
			param = ap_getword_conf(r->pool, &pair);
		    }
		    else if(strEQ(key, "filename")) {
			filename = ap_getword_conf(r->pool, &pair);
		    }
		}
	    }
	    if (!filename) {
	        char *value = multipart_buffer_read_body(mbuff);
	        ap_table_add(req->parms, param, value);
		continue;
	    }
	    if (!param) continue; /* shouldn't happen, but just in case. */

            if (req->disable_uploads) {
                ap_log_rerror(REQ_ERROR, "[libapreq] file upload forbidden");
                return HTTP_FORBIDDEN;
            }

	    ap_table_add(req->parms, param, filename);

	    if (upload) {
		upload->next = ApacheUpload_new(req);
		upload = upload->next;
	    }
	    else {
		upload = ApacheUpload_new(req);
		req->upload = upload;
	    }

	    if (! req->upload_hook && ! ApacheRequest_tmpfile(req, upload) ) {
		return HTTP_INTERNAL_SERVER_ERROR;
	    }

	    upload->info = header;
	    upload->filename = ap_pstrdup(req->r->pool, filename);
	    upload->name = ap_pstrdup(req->r->pool, param);

            /* mozilla empty-file (missing CRLF) hack */
            fill_buffer(mbuff);
            if( strEQN(mbuff->buf_begin, mbuff->boundary, 
                      strlen(mbuff->boundary)) ) {
                r->remaining -= 2;
                continue; 
            }

	    while ((blen = multipart_buffer_read(mbuff, buff, sizeof(buff)))) {
		if (req->upload_hook != NULL) {
		    wlen = req->upload_hook(req->hook_data, buff, blen, upload);
		} else {
		    wlen = fwrite(buff, 1, blen, upload->fp);
		}
		if (wlen != blen) {
		    return HTTP_INTERNAL_SERVER_ERROR;
		}
		upload->size += wlen;
	    }

	    if (upload->size > 0 && (upload->fp != NULL)) {
		fseek(upload->fp, 0, 0);
	    }
	}
    }

    return OK;
}
Beispiel #30
0
/* XXX: Is there is still an O(n^2) attack possible here?  Please detail. */
BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest,
                                   LPVOID lpvBuffer, LPDWORD lpdwSize,
                                   LPDWORD lpdwDataType) {
    isapi_cid *cid = (isapi_cid *)hConn;
    request_rec *r = cid->r;
    request_rec *subreq;

    switch (dwHSERequest) {
    case 1: /* HSE_REQ_SEND_URL_REDIRECT_RESP */
        /* Set the status to be returned when the HttpExtensionProc()
         * is done.
         * WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP
         *          and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK.
         *          They most definately are not, even in their own samples.
         */
        ap_table_set(r->headers_out, "Location", lpvBuffer);
        cid->status = cid->r->status
                    = cid->ecb->dwHttpStatusCode = HTTP_MOVED_TEMPORARILY;
        return TRUE;

    case 2: /* HSE_REQ_SEND_URL */
        /* Soak up remaining input (there should be none) */
        if (r->remaining > 0) {
            char argsbuffer[HUGE_STRING_LEN];
            while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0);
        }

        /* Reset the method to GET */
        r->method = ap_pstrdup(r->pool, "GET");
        r->method_number = M_GET;

        /* Don't let anyone think there's still data */
        ap_table_unset(r->headers_in, "Content-Length");

        /* AV fault per PR3598 - redirected path is lost! */
        (char*)lpvBuffer = ap_pstrdup(r->pool, (char*)lpvBuffer);
        ap_internal_redirect((char*)lpvBuffer, r);
        return TRUE;

    case 3: /* HSE_REQ_SEND_RESPONSE_HEADER */
    {
        /* Parse them out, or die trying */
        DWORD statlen = 0, headlen = 0;
	if (lpvBuffer)
	    statlen = strlen((char*) lpvBuffer);
	if (lpdwDataType)
	    headlen = strlen((char*) lpdwDataType);
        return SendResponseHeaderEx(cid, (char*) lpvBuffer, (char*) lpdwDataType, 
                                    statlen, headlen);
    }

    case 4: /* HSE_REQ_DONE_WITH_SESSION */
        /* Do nothing... since we don't support async I/O, they'll
         * return from HttpExtensionProc soon
         */
        return TRUE;

    case 1001: /* HSE_REQ_MAP_URL_TO_PATH */
    {
        /* Map a URL to a filename */
        char *file = (char *)lpvBuffer;
	DWORD len;
        subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, file, *lpdwSize), r);

        len = ap_cpystrn(file, subreq->filename, *lpdwSize) - file;
	
        /* IIS puts a trailing slash on directories, Apache doesn't */
        if (S_ISDIR (subreq->finfo.st_mode)) {
            if (len < *lpdwSize - 1) {
                file[len++] = '\\';
                file[len] = '\0';
            }
        }
        *lpdwSize = len;
        return TRUE;
    }

    case 1002: /* HSE_REQ_GET_SSPI_INFO */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO "
                          "is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

    case 1003: /* HSE_APPEND_LOG_PARAMETER */
        /* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field
         * This code will do for now...
         */
        ap_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer);
        if (AppendLogToQuery) {
            if (r->args)
                r->args = ap_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL);
            else
                r->args = ap_pstrdup(r->pool, (char*) lpvBuffer);
        }
        if (AppendLogToErrors)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
                          "ISAPI %s: %s", cid->r->filename,
                          (char*) lpvBuffer);
        return TRUE;

    /* We don't support all this async I/O, Microsoft-specific stuff */
    case 1005: /* HSE_REQ_IO_COMPLETION */
    case 1006: /* HSE_REQ_TRANSMIT_FILE */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI asynchronous I/O not supported: %s", 
                          r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

    case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */
        /* Since we don't override the user ID and access, we can't reset.
         */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction "
                          "HSE_REQ_REFRESH_ISAPI_ACL "
                          "is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

    case 1008: /* HSE_REQ_IS_KEEP_CONN */
        *((LPBOOL) lpvBuffer) = (r->connection->keepalive == 1);
        return TRUE;

    case 1010: /* HSE_REQ_ASYNC_READ_CLIENT */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI asynchronous I/O not supported: %s", 
                          r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

    case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN  Added in ISAPI 4.0 */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction "
                          "HSE_REQ_GET_IMPERSONATION_TOKEN "
                          "is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

#ifdef HSE_REQ_MAP_URL_TO_PATH_EX
    case 1012: /* HSE_REQ_MAP_URL_TO_PATH_EX */
    {
        /* Map a URL to a filename */
        LPHSE_URL_MAPEX_INFO info = (LPHSE_URL_MAPEX_INFO) lpdwDataType;
        char* test_uri = ap_pstrndup(r->pool, (char *)lpvBuffer, *lpdwSize);

        subreq = ap_sub_req_lookup_uri(test_uri, r);
        info->cchMatchingURL = strlen(test_uri);        
        info->cchMatchingPath = ap_cpystrn(info->lpszPath, subreq->filename, 
                                           MAX_PATH) - info->lpszPath;
        
        /* Mapping started with assuming both strings matched.
         * Now roll on the path_info as a mismatch and handle
         * terminating slashes for directory matches.
         */
        if (subreq->path_info && *subreq->path_info) {
            ap_cpystrn(info->lpszPath + info->cchMatchingPath, 
                       subreq->path_info, MAX_PATH - info->cchMatchingPath);
            info->cchMatchingURL -= strlen(subreq->path_info);
            if (S_ISDIR(subreq->finfo.st_mode)
                 && info->cchMatchingPath < MAX_PATH - 1) {
                /* roll forward over path_info's first slash */
                ++info->cchMatchingPath;
                ++info->cchMatchingURL;
            }
        }
        else if (S_ISDIR(subreq->finfo.st_mode)
                 && info->cchMatchingPath < MAX_PATH - 1) {
            /* Add a trailing slash for directory */
            info->lpszPath[info->cchMatchingPath++] = '/';
            info->lpszPath[info->cchMatchingPath] = '\0';
        }

        /* If the matched isn't a file, roll match back to the prior slash */
        if (!subreq->finfo.st_mode) {
            while (info->cchMatchingPath && info->cchMatchingURL) {
                if (info->lpszPath[info->cchMatchingPath - 1] == '/') 
                    break;
                --info->cchMatchingPath;
                --info->cchMatchingURL;
            }
        }
        
        /* Paths returned with back slashes */
        for (test_uri = info->lpszPath; *test_uri; ++test_uri)
            if (*test_uri == '/')
                *test_uri = '\\';
        
        /* is a combination of:
         * HSE_URL_FLAGS_READ         0x001 Allow read
         * HSE_URL_FLAGS_WRITE        0x002 Allow write
         * HSE_URL_FLAGS_EXECUTE      0x004 Allow execute
         * HSE_URL_FLAGS_SSL          0x008 Require SSL
         * HSE_URL_FLAGS_DONT_CACHE   0x010 Don't cache (VRoot only)
         * HSE_URL_FLAGS_NEGO_CERT    0x020 Allow client SSL cert
         * HSE_URL_FLAGS_REQUIRE_CERT 0x040 Require client SSL cert
         * HSE_URL_FLAGS_MAP_CERT     0x080 Map client SSL cert to account
         * HSE_URL_FLAGS_SSL128       0x100 Require 128-bit SSL cert
         * HSE_URL_FLAGS_SCRIPT       0x200 Allow script execution
         *
         * XxX: As everywhere, EXEC flags could use some work...
         *      and this could go further with more flags, as desired.
         */ 
        info->dwFlags = (subreq->finfo.st_mode & _S_IREAD  ? 0x001 : 0)
                      | (subreq->finfo.st_mode & _S_IWRITE ? 0x002 : 0)
                      | (subreq->finfo.st_mode & _S_IEXEC  ? 0x204 : 0);
        return TRUE;
    }
#endif

    case 1014: /* HSE_REQ_ABORTIVE_CLOSE */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE"
                          " is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

    case 1015: /* HSE_REQ_GET_CERT_INFO_EX  Added in ISAPI 4.0 */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction "
                          "HSE_REQ_GET_CERT_INFO_EX "
                          "is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

#ifdef HSE_REQ_SEND_RESPONSE_HEADER_EX
    case 1016: /* HSE_REQ_SEND_RESPONSE_HEADER_EX  Added in ISAPI 4.0 */
    {
        LPHSE_SEND_HEADER_EX_INFO shi
                                  = (LPHSE_SEND_HEADER_EX_INFO) lpvBuffer;
        /* XXX: ignore shi->fKeepConn?  We shouldn't need the advise */
        /* r->connection->keepalive = shi->fKeepConn; */
        return SendResponseHeaderEx(cid, shi->pszStatus, shi->pszHeader,
                                         shi->cchStatus, shi->cchHeader);
    }
#endif

    case 1017: /* HSE_REQ_CLOSE_CONNECTION  Added after ISAPI 4.0 */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction "
                          "HSE_REQ_CLOSE_CONNECTION "
                          "is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;

    case 1018: /* HSE_REQ_IS_CONNECTED  Added after ISAPI 4.0 */
        /* Returns True if client is connected c.f. MSKB Q188346
         * XXX: That statement is very ambigious... assuming the 
         * identical return mechanism as HSE_REQ_IS_KEEP_CONN.
         */
        *((LPBOOL) lpvBuffer) = (r->connection->aborted == 0);
        return TRUE;

    case 1020: /* HSE_REQ_EXTENSION_TRIGGER  Added after ISAPI 4.0 */
        /*  Undocumented - defined by the Microsoft Jan '00 Platform SDK
         */
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction "
                          "HSE_REQ_EXTENSION_TRIGGER "
                          "is not supported: %s", r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;


    default:
        if (LogNotSupported)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                          "ISAPI ServerSupportFunction (%d) not supported: "
                          "%s", dwHSERequest, r->filename);
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
}