Ejemplo n.º 1
0
const char * generate_websocket_resp(const char * req, size_t reqlen, char * dest, size_t destlen)
{
	/* char origin[256]; */
	/* char protocol[256]; */
	/* char key1[256]; */
	/* char key2[256]; */
	char key[256];
	char upgrade[64];
	/* get_header_value(req, reqlen, "Origin", origin, sizeof(origin)); */
	/* get_header_value(req, reqlen, "Sec-WebSocket-Protocol", protocol, sizeof(protocol)); */
	get_header_value(req, reqlen, "Upgrade", upgrade, sizeof(upgrade));
	/* get_header_value(req, reqlen, "Sec-WebSocket-Key1", key1, sizeof(key1)); */
	/* get_header_value(req, reqlen, "Sec-WebSocket-Key2", key2, sizeof(key2)); */
	get_header_value(req, reqlen, "Sec-WebSocket-Key", key, sizeof(key));
	if (key[0] != '\0') {
		char key_sha1[128];
		char key_base64[128];
		SHA1Context sha;
		strcat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
		SHA1Reset(&sha);
		SHA1Input(&sha, ( const unsigned char * )key, strlen(key));
		SHA1Result(&sha);
		memset(key_sha1, 0, sizeof(key_sha1));
		memset(key_base64, 0, sizeof(key_base64));
		int i, j;
		for (i = 0; i < 5; i++) {
			for (j = 0; j < 4; j++) {
				key_sha1[i*4+j] = sha.Message_Digest[i] << (8*j) >> 24;
			}
		}
		base64_encode(key_sha1, strlen(key_sha1), key_base64, sizeof(key_base64));
		snprintf(dest, destlen, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: %s\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n", upgrade, key_base64);
		return dest;
	}
Ejemplo n.º 2
0
/*********************************************************************
 *
 * Function    :  is_imageurl
 *
 * Description :  Given a URL, decide whether it is an image or not,
 *                using either the info from a previous +image action
 *                or, #ifdef FEATURE_IMAGE_DETECT_MSIE, and the browser
 *                is MSIE and not on a Mac, tell from the browser's accept
 *                header.
 *
 * Parameters  :
 *          1  :  csp = Current client state (buffers, headers, etc...)
 *
 * Returns     :  True (nonzero) if URL is an image, false (0)
 *                otherwise
 *
 *********************************************************************/
int is_imageurl(struct client_state *csp)
{
#ifdef FEATURE_IMAGE_DETECT_MSIE
   char *tmp;

   tmp = get_header_value(csp->headers, "User-Agent:");
   if (tmp && strstr(tmp, "MSIE") && !strstr(tmp, "Mac_"))
   {
      tmp = get_header_value(csp->headers, "Accept:");
      if (tmp && strstr(tmp, "image/gif"))
      {
         /* Client will accept HTML.  If this seems counterintuitive,
          * blame Microsoft.
          */
         return(0);
      }
      else
      {
         return(1);
      }
   }
#endif /* def FEATURE_IMAGE_DETECT_MSIE */

   return ((csp->action->flags & ACTION_IMAGE) != 0);

}
    cloud_blob_properties blob_response_parsers::parse_blob_properties(const web::http::http_response& response)
    {
        cloud_blob_properties properties;

        properties.m_etag = parse_etag(response);
        properties.m_last_modified = parse_last_modified(response);
        properties.m_lease_status = parse_lease_status(response);
        properties.m_lease_state = parse_lease_state(response);
        properties.m_lease_duration = parse_lease_duration(response);
        properties.m_size = parse_blob_size(response);

        auto& headers = response.headers();
        properties.m_page_blob_sequence_number = utility::conversions::scan_string<int64_t>(get_header_value(headers, ms_header_blob_sequence_number));
        properties.m_append_blob_committed_block_count = utility::conversions::scan_string<int>(get_header_value(headers, ms_header_blob_committed_block_count));
        properties.m_cache_control = get_header_value(headers, web::http::header_names::cache_control);
        properties.m_content_disposition = get_header_value(headers, header_content_disposition);
        properties.m_content_encoding = get_header_value(headers, web::http::header_names::content_encoding);
        properties.m_content_language = get_header_value(headers, web::http::header_names::content_language);
        properties.m_content_type = get_header_value(headers, web::http::header_names::content_type);
        properties.m_type = parse_blob_type(get_header_value(headers, ms_header_blob_type));
        properties.m_content_md5 = get_header_value(headers, ms_header_blob_content_md5);
        if (properties.m_content_md5.empty())
        {
            properties.m_content_md5 = get_header_value(headers, web::http::header_names::content_md5);
        }

        properties.m_server_encrypted = response_parsers::parse_boolean(get_header_value(headers, ms_header_server_encrypted));
        properties.m_is_incremental_copy = response_parsers::parse_boolean(get_header_value(headers, ms_header_incremental_copy));

        return properties;
    }
Ejemplo n.º 4
0
/*
 * Sets into the saved_request the designated filename, according to configured base
 * directory and request data (URI, headers, etc). Also creates the base directory if it
 * doesn't exist
 */
static int set_filename(tee_saved_request *sr)
{
	apr_time_exp_t t;
	apr_time_exp_gmt(&t, sr->time_enqueued);

	// Obtaining directory name
	const char *dir;
	dir = apr_psprintf(sr->pool, "%s/%04d%02d%02d/%02d",
			sr->base_dir, 1900 + t.tm_year, t.tm_mon + 1, t.tm_mday, t.tm_hour);

	// Creating directory if needed
	apr_status_t rc = apr_dir_make_recursive(dir, APR_FPROT_OS_DEFAULT, sr->pool);
	if (rc != APR_SUCCESS) {
		ap_log_error(APLOG_MARK, APLOG_ERR, 0, sr->server, "tee: Cannot create directory %s: %s",
				dir, tee_get_error_string(rc, sr->pool));
		return 1;
	}

	// Setting file name
	unsigned long file_id = ((unsigned long) t.tm_min * 60 + t.tm_sec) * 1000000 + t.tm_usec; // usec in hour
	char b[MAX_FILENAME_LEN]; // Filename is cut in case the URI is too long
	const char *rec_id = get_header_value(sr, sr->id_header, "");
	const char *host = get_header_value(sr, "Host", "");
	apr_snprintf(b, MAX_FILENAME_LEN, "%010lu_%s_%s_%s%s", file_id, rec_id, sr->method, host, sr->uri);
	tee_replace(b, "/", '_'); // Replace the slash (invalid character in file names)
	sr->filename = apr_psprintf(sr->pool, "%s/%s_%d", dir, b, sr->status);
	return 0;
}
Ejemplo n.º 5
0
static void
set_distiller_type_generic(DistillerBuffer *mime_headers, const char *url,
                           const char *user, C_DistillerType *dtype)
{
  char *mimetype;
  int mimetype_len;
  char disttype[MAX_ARG_STRING + MAX_MIMETYPE + 1];

  /*
   *  Here if no X-Route header: use MIME type and/or username. 
   */
  mimetype = (char *)get_header_value(mime_headers,
                                      "content-type",
                                      &mimetype_len, NULL, NULL);
  if (mimetype == NULL) {
    if (user == NULL || *user == '\0')
      sprintf(disttype, "text/html");
    else
      sprintf(disttype, "%s/text/html", user);
  } else {
    if (user && *user)
      sprintf(disttype, "%s/", user);
    else
      disttype[0] = '\0';
    strncat(disttype, mimetype, mimetype_len);
  }
  SET_DISTILLER_TYPE(*dtype, disttype);
}
Ejemplo n.º 6
0
int is_websocket_header(const char * data, size_t datalen)
{
	char value[512];
	if (get_header_value(data, datalen, "Connection", value, sizeof(value)) == 0) {
		if (strstr(value, "Upgrade")) {
			if (get_header_value(data, datalen, "Upgrade", value, 512) == 0) {
				// version 13 is 'websocket'
				if (strcasestr(value, "WebSocket")) {
					return 1;
				}
				else {
					printf("Can not found websocket in %s\n", value);
				}
			}
		}
	}
	return 0;
}
Ejemplo n.º 7
0
static void
set_distiller_type(DistillerBuffer *mime_headers, const char *url,
                   const char *user, C_DistillerType *dtype)
{
  const char *route = NULL;
  int route_len;
  char *disttype;

  if ((route = get_header_value(mime_headers,
                                "x-route",&route_len,NULL,NULL))
      == NULL) {

    /* Aggregator? */

    if (strncasecmp(url, fe_agg_string, strlen(fe_agg_string)) == 0) {
      /* distiller "type" is everything up to but not incl next slash */
      char disttype_tmp[256];
      int i,j;
      for (i=0, j=strlen(fe_agg_string);
           i < strlen(url) && url[j] != '/';
           i++,j++)
        ;
      strncpy(disttype_tmp, url+strlen(fe_agg_string), i);
      disttype_tmp[i] = '\0';
      SET_DISTILLER_TYPE(*dtype, disttype_tmp);

    } else {
      /* generic transformation */
      set_distiller_type_generic(mime_headers, url, user, dtype);
    }
  } else {
    
    /* pop off next element, up to a semicolon */
    char *header_value = (char *)ALLOCA(route_len+1);
    char *semicolon;

    strncpy(header_value, route, route_len);
    header_value[route_len] = '\0';
    
    if ((semicolon = strchr(header_value, ';')) != NULL) {
      int i;
      for (i=0; i<route_len && route[i] != ';'; i++)
        ;
      disttype = (char*)ALLOCA(i+2);
      strncpy(disttype, route, i);
      disttype[i] = '\0';
      insert_header(mime_headers, "x-route", semicolon+1, 0);
    } else {
      /* no semicolon, this is the last guy in the list */
      disttype = (char *)ALLOCA(route_len+2);
      strncpy(disttype, route, route_len);
      disttype[route_len] = '\0';
    }
    delete_header(mime_headers, "x-route");
    SET_DISTILLER_TYPE(*dtype, disttype);
  }
}
Ejemplo n.º 8
0
int get_cookies(List *headers, const WSPMachine *sm)
{
	Octstr *header = NULL;
	Octstr *value = NULL;
	Cookie *cookie = NULL;
	long pos = 0;

	/* 
     * This can happen if the user aborts while the HTTP request is pending from the server.
	 * In that case, the session machine is destroyed and is not available to this function
	 * for cookie caching.
	 */

	if (sm == NULL) {
		info (0, "No session machine for cookie retrieval");
		return 0;
	}

	for (pos = 0; pos < gwlist_len(headers); pos++) {
		header = gwlist_get(headers, pos);
		/* debug ("wap.wsp.http", 0, "get_cookies: Examining header (%s)", octstr_get_cstr (header)); */
		if (strncasecmp ("set-cookie", octstr_get_cstr (header),10) == 0) {		
			debug ("wap.wsp.http", 0, "Caching cookie (%s)", octstr_get_cstr (header));

			if ((value = get_header_value (header)) == NULL) {
				error (0, "get_cookies: No value in (%s)", octstr_get_cstr(header));
				continue;
			}

			/* Parse the received cookie */
			if ((cookie = parse_cookie(value)) != NULL) {

				/* Check to see if this cookie is already present */
				if (have_cookie(sm->cookies, cookie) == 1) {
					debug("wap.wsp.http", 0, "parse_cookie: Cookie present");
					      cookie_destroy(cookie);
					continue;
				} else {
					add_cookie_to_cache(sm, cookie);
					debug("wap.wsp.http", 0, "get_cookies: Added (%s)", 
						  octstr_get_cstr(cookie -> name));
				}
			}
		}
	}

	debug("wap.wsp.http", 0, "get_cookies: End");
	return 0;
}
Ejemplo n.º 9
0
/*
 *  HTTP headers looked OK, and we were able to determine what type of
 *  distiller was needed, so go ahead and do the distillation, returning
 *  the results to the client.  If distillation fails, return the
 *  original content and headers to the client.
 *
 *  ARGS:
 *    i:  URL (BUG::shouldn't be needed - it's currently used to
 *      determine distiller type for "aggregator" virtual-site URLs )
 *    i: input to distiller (from previous "pipestage" or from server)
 *    o: output from distiller
 *    o: distiller type descriptor
 *    i: argument list for distiller
 *
 *  RETURNS:  Distiller status for the distillation
 *  REENTRANT: yes
 *  SIDE EFFECTS:
 *    If distillation succeeds, fills in new headers (for return to client)
 *      in DistillerOutput structure
 *  ASSUMTPIONS:
 *    None
 */
static DistillerStatus
do_distillation(const char *url,
                DistillerInput *dinp, DistillerOutput *doutp,
                C_DistillerType *dtype,
                ArgumentList *al)
{
  DistillerStatus result = distFatalError;
  Argument *arg;
  const char *whichuser = "******";
  const char *mime;
  int mime_len;

  /*
   *  HTTP headers look OK.  Extract the MIME type, figure out what
   *  distiller to use, and dispatch to it.
   */

  if ((arg = getArgumentFromIdInList(al, FRONT_USERID))) {
    whichuser = ARG_STRING(*arg);
  }

  /*
   *  If this is the set-prefs page, be sure the user's args get munged into it
   * REMOVED by fox since it interferes with the "mini-httpd" worker (miniserver.pl):
   * this routing is now enforced by X-Route instead
   */
  if (0 && strcasecmp(url, fe_set_prefs_url) == 0) {
    SET_DISTILLER_TYPE(*dtype, "transend/text/html");
  } else {
    set_distiller_type(&dinp->metadata,
                       (const char *)url, 
                       whichuser, dtype);
  }
  
  if ((mime = get_header_value(&dinp->metadata,
                               "content-type",
                               &mime_len, NULL, NULL)) != NULL) {
    strncpy(dinp->mimeType, mime, MIN(mime_len,MAX_MIMETYPE-1));
    dinp->mimeType[MIN(mime_len,MAX_MIMETYPE-1)] = '\0';
  } else {
    strcpy(dinp->mimeType, "text/html");
  }
  result = Distill(dtype, al->arg, al->nargs, dinp, doutp);
  return result;
}
Ejemplo n.º 10
0
int get_header_double(PyObject* header, const char* keyword, double* val,
                      double def, HeaderGetFlags flags) {
    /* nonnegative isn't currently used for doubles/floats. But if needed one
       could simply remove the assert again and implement the negative check. */
    assert(!(flags & HDR_FAIL_VAL_NEGATIVE));
    PyObject* keyval = get_header_value(header, keyword, flags);

    if (keyval == NULL) {
        *val = def;
        return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED;
    }
    double tmp = PyFloat_AsDouble(keyval);
    Py_DECREF(keyval);
    if (PyErr_Occurred()) {
        return GET_HEADER_FAILED;
    }
    *val = tmp;
    return GET_HEADER_SUCCESS;
}
Ejemplo n.º 11
0
int get_header_longlong(PyObject* header, const char* keyword, long long* val,
                        long long def, HeaderGetFlags flags) {
    PyObject* keyval = get_header_value(header, keyword, flags);

    if (keyval == NULL) {
        *val = def;
        return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED;
    }
    long long tmp = PyLong_AsLongLong(keyval);
    Py_DECREF(keyval);
    if (PyErr_Occurred()) {
        return GET_HEADER_FAILED;
    }
    if ((flags & HDR_FAIL_VAL_NEGATIVE) && (tmp < 0)) {
        PyErr_Format(PyExc_ValueError, "%s should not be negative.", keyword);
        return GET_HEADER_FAILED;
    }
    *val = tmp;
    return GET_HEADER_SUCCESS;
}
Ejemplo n.º 12
0
int get_header_string(PyObject* header, const char* keyword, char* val,
                      const char* def, HeaderGetFlags flags) {
    /* nonnegative doesn't make sense for strings*/
    assert(!(flags & HDR_FAIL_VAL_NEGATIVE));
    PyObject* keyval = get_header_value(header, keyword, flags);

    if (keyval == NULL) {
        strncpy(val, def, 72);
        return PyErr_Occurred() ? GET_HEADER_FAILED : GET_HEADER_DEFAULT_USED;
    }
    PyObject* tmp = PyUnicode_AsLatin1String(keyval);
    // FITS header values should always be ASCII, but Latin1 is on the
    // safe side
    Py_DECREF(keyval);
    if (tmp == NULL) {
        /* could always fail to allocate the memory or such like. */
        return GET_HEADER_FAILED;
    }
    strncpy(val, PyBytes_AsString(tmp), 72);
    Py_DECREF(tmp);
    return GET_HEADER_SUCCESS;
}
Ejemplo n.º 13
0
/*********************************************************************
 *
 * Function    :  trust_url FIXME: I should be called distrust_url
 *
 * Description :  Calls is_untrusted_url to determine if the URL is trusted
 *                and if not, returns a HTTP 304 response with a reject message.
 *
 * Parameters  :
 *          1  :  csp = Current client state (buffers, headers, etc...)
 *
 * Returns     :  NULL => trusted, else http_response.
 *
 *********************************************************************/
struct http_response *trust_url(struct client_state *csp)
{
   struct http_response *rsp;
   struct map * exports;
   char buf[BUFFER_SIZE];
   char *p;
   struct url_spec **tl;
   struct url_spec *t;
   jb_err err;

   /*
    * Don't bother to work on trusted URLs
    */
   if (!is_untrusted_url(csp))
   {
      return NULL;
   }

   /*
    * Else, prepare a response:
    */
   if (NULL == (rsp = alloc_http_response()))
   {
      return cgi_error_memory();
   }

   exports = default_exports(csp, NULL);
   if (exports == NULL)
   {
      free_http_response(rsp);
      return cgi_error_memory();
   }

   /*
    * Export the protocol, host, port, and referrer information
    */
   err = map(exports, "hostport", 1, csp->http->hostport, 1);
   if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1); 
   if (!err) err = map(exports, "path", 1, csp->http->path, 1);

   if (NULL != (p = get_header_value(csp->headers, "Referer:")))
   {
      if (!err) err = map(exports, "referrer", 1, html_encode(p), 0);
   }
   else
   {
      if (!err) err = map(exports, "referrer", 1, "unknown", 1);
   }

   if (err)
   {
      free_map(exports);
      free_http_response(rsp);
      return cgi_error_memory();
   }

   /*
    * Export the trust list
    */
   p = strdup("");
   for (tl = csp->config->trust_list; (t = *tl) != NULL ; tl++)
   {
      sprintf(buf, "<li>%s</li>\n", t->spec);
      string_append(&p, buf);
   }
   err = map(exports, "trusted-referrers", 1, p, 0);

   if (err)
   {
      free_map(exports);
      free_http_response(rsp);
      return cgi_error_memory();
   }

   /*
    * Export the trust info, if available
    */
   if (csp->config->trust_info->first)
   {
      struct list_entry *l;

      p = strdup("");
      for (l = csp->config->trust_info->first; l ; l = l->next)
      {
         sprintf(buf, "<li> <a href=\"%s\">%s</a><br>\n",l->str, l->str);
         string_append(&p, buf);
      }
      err = map(exports, "trust-info", 1, p, 0);
   }
   else
   {
      err = map_block_killer(exports, "have-trust-info");
   }

   if (err)
   {
      free_map(exports);
      free_http_response(rsp);
      return cgi_error_memory();
   }

   /*
    * Export the force prefix or the force conditional block killer
    */
#ifdef FEATURE_FORCE_LOAD
   err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
#else /* ifndef FEATURE_FORCE_LOAD */
   err = map_block_killer(exports, "force-support");
#endif /* ndef FEATURE_FORCE_LOAD */

   if (err)
   {
      free_map(exports);
      free_http_response(rsp);
      return cgi_error_memory();
   }

   /*
    * Build the response
    */
   err = template_fill_for_cgi(csp, "untrusted", exports, rsp);
   if (err)
   {
      free_http_response(rsp);
      return cgi_error_memory();
   }

   return finish_http_response(rsp);
}
Ejemplo n.º 14
0
HTTP_Status
server_dispatch(ArgumentList *al, task_t *tsk)
{
  int thrindex = TASK_THRINDEX(tsk);
  int agg = 0;
  int nfound;
  HTTP_Status retcode = HTTP_NO_ERR;
  Request *hp = (Request *)TASK_DATA(tsk);
#ifdef LOGGING
  struct loginfo *lo = hp->lo;
#endif

  INST_set_thread_state(thrindex, THR_CACHE);

  /*
   *  If we got here, we know the request is either GET or POST,
   *  or this is a URL in the frontend's namespace
   */

  tsk->task_age = 0;            /* no pipe stages done yet */

  /*if (*hp->url == '/' || 
      strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/
  if (is_server_url(hp->url)==gm_True) {
    /* this is a URL in the frontend's namespace, or an aggregator URL */
    const char *workerName, *val;
    int val_len, len, to_copy, already_read;
    char *orig_hdrs, *eoh, *new_hdrs, *body;
    extern Options runtime_options;

    orig_hdrs = DistillerBufferData(&hp->cli_hdrs);
    eoh = strstr(orig_hdrs, "\r\n\r\n");
    if (eoh==NULL) {
      retcode = HTTP_ERR_MALFORMED_REQUEST;
      goto DISPATCH_RETURN;
    }
    eoh += 4;

    /* clone the headers */
    DistillerBufferAlloc(&hp->svr_hdrs, eoh-orig_hdrs+1);
    new_hdrs = DistillerBufferData(&hp->svr_hdrs);
    memcpy(new_hdrs, orig_hdrs, eoh-orig_hdrs);
    *(new_hdrs+(eoh-orig_hdrs)) = '\0';
    DistillerBufferSetLength(&hp->svr_hdrs, eoh - orig_hdrs);
    DistillerBufferFreeMe(&hp->svr_hdrs, gm_True);

    /* 
     * look for the content-length field; 
     * if found, read the rest of the data and create svr_data 
     */
    if ((val = get_header_value(&hp->cli_hdrs, "content-length", &val_len,
				NULL, NULL)) != NULL) {
      len = strtoul(val, NULL, 0);
      if (len < 0) {
	retcode = HTTP_ERR_MALFORMED_REQUEST;
	goto DISPATCH_RETURN;
      }

      already_read = DistillerBufferLength(&hp->cli_hdrs) - (eoh - orig_hdrs);
      if (len <= already_read) {
	to_copy = len;
      } else {
	to_copy = already_read;
      }

      DistillerBufferAlloc(&hp->svr_data, len+1);
      body = DistillerBufferData(&hp->svr_data);
      memcpy(body, eoh, to_copy);
      
      /* get the rest of the data from the socket */
      if (to_copy < len) {
	if (readline_or_timeout(hp, len - to_copy, body+to_copy)
	    != (len-to_copy)) {
	  retcode = HTTP_ERR_MALFORMED_REQUEST;
	  goto DISPATCH_RETURN;
	}
      }

      /* add a trailing '\0' */
      *(body+len) = '\0';
      DistillerBufferSetLength(&hp->svr_data, len);
    }
    
    workerName = Options_Find(runtime_options, "frontend.myurl.dispatch");
    if (workerName==NULL) workerName = "myurl/dispatch";

    insert_header(&hp->svr_hdrs, "X-Route", workerName, 1);
    hp->svr_http_status = 200; /* everything's ok with this HTTP request */
  }
  else {
    INST_timestamp(thrindex, m_cachestart);
    if (hp->method[0] == 'g' || hp->method[0] == 'G') {
      /* handle GET */

#ifdef OLD
      /*
       *  HACK HACK HACK - this should be replaced with the real interface that
       *  does a regexp match on URL to determine if any aggregator should get
       *  dibs before the original content is fetched.
       *
       *  Any references in this function to variable 'agg' represent a place
       *  where the hack was spliced in.
       */
      if (strncasecmp(hp->url, fe_agg_string, strlen(fe_agg_string)) != 0) {
	/* not an aggregator call */
#endif
	agg = 0;
	retcode = do_get(hp, al);
	if (retcode != HTTP_NO_ERR) {
	  goto DISPATCH_RETURN;
	}
#ifdef OLD
      } else {
	/* aggregator call */
	abort();
	agg = 1;
	/* don't clone the client headers - just point to them. */
	DistillerBufferSetStatic(&hp->svr_hdrs,
				 DistillerBufferData(&hp->cli_hdrs),
				 DistillerBufferLength(&hp->cli_hdrs));
	/* since we're pointing to a copy, don't try to free */
	DistillerBufferFreeMe(&hp->svr_hdrs, gm_False);
      }
#endif
    } else {
      /* handle POST */
      retcode = do_post(hp, al);
      if (retcode != HTTP_NO_ERR) {
	/* post failed! report error to client */
	goto DISPATCH_RETURN;
      }
    }

    INST_timestamp(thrindex, m_cachedone);

    /*
     *  if there was an HTTP-level error (response code not "200"), bypass
     *  the remainder straight to client.
     */
    
    nfound = sscanf(DistillerBufferData(&hp->svr_hdrs), "%*s %lu",
		    &hp->svr_http_status);
    if (nfound < 1) {             /* no status found */
      retcode = HTTP_ERR_GET_FAILED;
      hp->svr_http_status = 0;
    } else {
      retcode = HTTP_NO_ERR;
    }
  }

#ifdef LOGGING
  lo->http_response = hp->svr_http_status;;      /* log HTTP server response */
#endif /* LOGGING */

  /*
   *  Note that HTTP_NO_ERR means "transaction to server succeeded" (ie
   *  at the transport level).  it does NOT necessarily mean that the
   *  HTTP *operation* (eg GET) succeeded -- the HTTP status code tells that.
   */

DISPATCH_RETURN:
  return retcode;
}
Ejemplo n.º 15
0
 utility::string_t parse_lease_id(const web::http::http_response& response)
 {
     return get_header_value(response, ms_header_lease_id);
 }
Ejemplo n.º 16
0
 lease_status parse_lease_status(const web::http::http_response& response)
 {
     return parse_lease_status(get_header_value(response, ms_header_lease_status));
 }
Ejemplo n.º 17
0
 utility::string_t get_header_value(const web::http::http_response& response, const utility::string_t& header)
 {
     return get_header_value(response.headers(), header);
 }
Ejemplo n.º 18
0
 utility::string_t parse_etag(const web::http::http_response& response)
 {
     return get_header_value(response, web::http::header_names::etag);
 }
Ejemplo n.º 19
0
int proxyServerLoadRequest(ProxyServer *p, const char *uniqueId,
        RequestRecord *rec) {

	reset_request_record(rec);

	char file_name[512];
	struct stat stat_buf;
	snprintf(file_name, sizeof(file_name), "%s/%s.req",
		stringAsCString(p->persistenceFolder), uniqueId);

	rec->fd = open(file_name, O_RDONLY);
	DIE(p, rec->fd, "Failed to open request file.");

	int status = fstat(rec->fd, &stat_buf);
	DIE(p, status, "Failed to get request file size.");

	rec->map.length = stat_buf.st_size; //Save the size

	//If file size is 0 then just return
	if (rec->map.length == 0) {
		return 0;
	}

	rec->map.buffer = mmap(NULL, stat_buf.st_size, PROT_READ,
		MAP_SHARED, rec->fd, 0);
	if (rec->map.buffer == MAP_FAILED) {
		DIE(p, -1, "Failed to map request file.");
	}

	//We are good to go. Start parsing.
	String *str = newString();
	int state = PARSE_METHOD;
	for (size_t i = 0; i < rec->map.length; ++i) {
		char ch = rec->map.buffer[i];

		//printf("[%c %d]", ch, state);
		if (ch == '\r') {
			continue; //Ignored
		}
		if (state == PARSE_METHOD) {
			if (ch == ' ') {
				if (strcmp("CONNECT", 
					stringAsCString(rec->method)) == 0) {
					state = PARSE_CONNECT_ADDRESS;
				} else {
					state = PARSE_PATH;
				}
				continue;
			}
			stringAppendChar(rec->method, ch);
			continue;
		}
		if (state == PARSE_PATH) {
			if (ch == '?') {
				state = PARSE_QUERY_STRING;
				continue;
			}
			if (ch == ' ') {
				state = PARSE_PROTOCOL_VERSION;
				continue;
			}
			stringAppendChar(rec->path, ch);
			continue;
		}
		if (state == PARSE_QUERY_STRING) {
			if (ch == ' ') {
				state = PARSE_PROTOCOL_VERSION;
				continue;
			}
			stringAppendChar(rec->queryString, ch);
			continue;
		}
		if (state == PARSE_PROTOCOL_VERSION) {
			if (ch == '\n') {
				state = PARSE_HEADER_NAME;
				continue;
			}
			//Don't store version
			continue;
		}
		if (state == PARSE_CONNECT_ADDRESS) {
			if (ch == ' ') {
				state = PARSE_PROTOCOL_VERSION;
				continue;
			}
			//Don't store address
			continue;
		}
		if (state == PARSE_HEADER_NAME) {
			if (ch == ':') {
				arrayAdd(rec->headerNames, 
					newStringWithString(str));
				str->length = 0;
				state = PARSE_HEADER_VALUE;
				continue;
			}
			if (ch == '\n') {
				//End of request headers
				rec->headerBuffer.buffer = 
					rec->map.buffer;
				rec->headerBuffer.length = i + 1;

				rec->bodyBuffer.buffer =
					rec->map.buffer + i + 1;
				rec->bodyBuffer.length = 
					rec->map.length - 
					rec->headerBuffer.length;
				
				//End parsing for now
				break;
			}
			stringAppendChar(str, ch);
			continue;
		}
		if (state == PARSE_HEADER_VALUE) {
			if (ch == '\n') {
				arrayAdd(rec->headerValues, 
					newStringWithString(str));
				str->length = 0;
				state = PARSE_HEADER_NAME;
				continue;
			}
			if ((str->length == 0) && ch == ' ') {
				//Skip leading space.
				continue;
			}
			stringAppendChar(str, ch);
			continue;
		}
	}
	
	deleteString(str);

	//Parse URL parameters
	parse_url_params(rec->queryString->buffer, rec->queryString->length, 
		rec->parameterNames, rec->parameterValues);

	//If form post then parse request body for parameters
	String *contentType = get_header_value(CONTENT_TYPE, rec);
	if (contentType != NULL && 
	    stringEqualsCString(contentType, FORM_ENC) &&
	    rec->bodyBuffer.length > 0) {
		parse_url_params(rec->bodyBuffer.buffer, 
			rec->bodyBuffer.length, 
			rec->parameterNames, 
			rec->parameterValues);
	}

	//It is safe to close the file now. It will 
	//closed anyway by reset method. 
	close(rec->fd);
	rec->fd = -1;

	return 0;
}
Ejemplo n.º 20
0
 lease_duration parse_lease_duration(const web::http::http_response& response)
 {
     return parse_lease_duration(get_header_value(response, ms_header_lease_duration));
 }
Ejemplo n.º 21
0
DistillerStatus
proxy_dispatch(ArgumentList *al, task_t *t)
{
  DistillerStatus status;       /* result of this pipe stage distillation */
  DistillerInput din;
  DistillerOutput dout;
  Request *hp = (Request *)TASK_DATA(t);
  C_DistillerType dtype;
  int thrindex = TASK_THRINDEX(t);
  DistillerStatus retcode;
  int redispatch = 0;
  char *static_route = NULL;
  int static_route_initialized = 0;
#ifdef LOGGING
  struct loginfo *lo = hp->lo;
#endif

  /*
   *  Initialize for *first* pipe stage.
   */

  DistillerBufferClone(&din.data, &hp->svr_data);
  DistillerBufferFreeMe(&din.data, gm_True);

  /*
   *  Make a **copy** of the server headers, because they may get
   *  overwritten when preparing headers to send to a distiller.
   */
  DistillerBufferClone(&din.metadata, &hp->svr_hdrs);
  DistillerBufferFreeMe(&din.metadata, gm_True);
  
  do {
    const char *char_tmp;
    char content_type[MIME_TYPE_MAX+1];
    int content_type_len;
    Argument *arg;
    int num_tries_left;

    /*
     *  Initialize for next pipe stage.
     */
    status = distFatalError;

#ifdef LOGGING
    /*
     *   Log original content-length
     */
    char_tmp = get_header_value(&din.metadata,
                                "content-length",
                                &content_type_len, NULL, NULL);
    if (char_tmp != NULL)
      lo->size_before = strtoul(char_tmp, NULL, 0);
    else
      lo->size_before = -1;
#endif /* LOGGING */
    char_tmp = get_header_value(&din.metadata,
                                "content-type",
                                &content_type_len, NULL, NULL);
    if (char_tmp != NULL) {
      strncpy(content_type, char_tmp, MIN(content_type_len+1, MIME_TYPE_MAX));
      content_type[MIN(content_type_len,MIME_TYPE_MAX)] = '\0';
    } else {
      content_type[0] = '\0';
    }

    /* if there are attributes after the content-type, remove them. */
    if ((char_tmp = strchr((const char *)content_type, ';')) != NULL)
      *(char *)char_tmp = '\0';
    /* chop any trailing spaces. */
    if ((char_tmp = strchr((const char *)content_type, ' ')) != NULL)
      *(char *)char_tmp = '\0';

    /*
     *  Distillation is definitely needed, so go do it.  In case of
     *  distConnectionBroken error, (re)try at most N
     *  times, where N is the value of the FRONT_RETRY_DISTILL argument,
     *  or PERF_HTTP_RETRY_DISTILL by default.  In case of any other
     *  error, or if all retries fail, bypass the original content.  In
     *  case of distOk (success), return the distilled content.
     */

    arg = getArgumentFromIdInList(al, FRONT_RETRY_DISTILL);
    num_tries_left = (arg ? ARG_INT(*arg) : PERF_HTTP_RETRY_DISTILL);
    INST_timestamp(thrindex, m_distillstart);
    /*
     *  Add a "Location:" header so distillers have a way to get the URL of
     *  this document, if they want. 
     */
    if (get_header_value(&din.metadata,
                         "location", NULL, NULL, NULL)
        == NULL) {
      insert_header(&din.metadata, "Location", hp->url, 0);
    }

    do {
      INST_set_thread_state(thrindex, THR_DISTILLER);
      status = do_distillation(hp->url, &din, &dout, &dtype, al);
    } while (status == distConnectionBroken
             && num_tries_left-- > 0);

#ifdef LOGGING
    lo->size_after = -status;     /* pessimistically assume failure for log */
#endif /* LOGGING */

    switch(status) {
    case distOk:
    case distRedispatch:
      /*
       *  The rules for redispatch are as follows.
       *  - If the response headers contain a nonempty X-Static-Route header, it
       *    is the final authority. X-Static-Route is only saved the
       *    first time it's seen.
       *  - Otherwise, if the response code is distRedispatch, use the
       *    default rules to figure out who to go to next.
       *  - Otherwise, the response is distOk --> just finish.
       */

      if (! static_route_initialized
          && DistillerBufferLength(&dout.metadata) > 0) {
        /* look for X-Static-Route */
        int tmp_len;
        const char *static_route_hdr =
          get_header_value(&dout.metadata,
                           "x-static-route", &tmp_len, NULL, NULL);
        if (static_route_hdr != NULL && tmp_len > 0) {
          static_route = ALLOCA(tmp_len+1);
          strncpy(static_route, static_route_hdr, tmp_len);
          static_route[tmp_len] = '\0';
          static_route_initialized = 1;
          delete_header(&dout.metadata, "x-static-route");
        }
      }

      if (static_route ||
          (status == distRedispatch && !static_route_initialized)) {
        /*
         *  this is a redispatch.
         *  The redispatch strategy is as follows.  Since the
         * DistillerInput pointer starts out being  a *clone* of the
         * server headers and data, it's always safe to free it.  THen move the
         *  DistillerOutput pointer (result of previous pipestage) to the
         *  DistillerInput pointer of this pipestage.  
         */

        DistillerBufferFree(&din.metadata);
        DistillerBufferFree(&din.data);
        DistillerBufferClone(&din.metadata, &dout.metadata);
        DistillerBufferClone(&din.data, &dout.data);
        DistillerBufferFree(&dout.metadata);
        DistillerBufferFree(&dout.data);

        /*
         *  Fix the content-length and content-type, if nec.
         */
        if (get_header_value(&din.metadata, "content-type",NULL,NULL,NULL)
            == NULL)
          insert_header(&din.metadata, "Content-type", din.mimeType, 1);
        if (get_header_value(&din.metadata, "content-length", NULL,NULL,NULL)
            == NULL) {
          char __tmp[12];
          snprintf(__tmp, 11, "%lu", DistillerBufferLength(&din.data));
          insert_header(&din.metadata, "Content-length", __tmp, 1);
        }
        if (static_route) {
          status = distRedispatch;
          /* add the X-Route header to this request */
          insert_header(&din.metadata, "X-Route", static_route, 1);
          /* scan forward to the next component of the path */
          while (*static_route && (*static_route != ';')) {
            static_route++;
          }
          if (*static_route == '\0') {
            static_route = NULL;
          } else {
            /* skip semicolon and any spaces */
            while (*static_route && ((*static_route == ';')
                                     || (*static_route == ' '))) {
              static_route++;
            }
            if (*static_route == '\0')
              static_route = NULL;
          }
        }
        redispatch++;
        t->task_age++; /* "time to live" of this request */
        retcode = distRedispatch;
      } else {
        /*
         *  Here if any of the following were true:
         *  - status was distOk and no static route header overrides this
         *  - status was distRedispatch, but an existing static route header
         *     indicates that we should override and finish with 
         */
#ifdef LOGGING
        lo->size_after = DistillerBufferLength(&dout.data);
#endif /* LOGGING */
        status = retcode = distOk;
      }
      break;

    default:                    /* some other distiller/ptm error */
      /*
       *  BUG::we shouldn't make this visible to the user unless the
       * "guru" argument is set
       */
      snprintf(hp->errmsg, HTTP_ERRMSG_MAX,
               (char *)FE_getDistillerStatusString(status));
      /*      retcode = HTTP_ERR_DISTILLER; XXX - XXX - XXX - */
      retcode = status;
      break;
      
    } /* switch(status) */

    /* Note that the data size is set last.  So if the data size is not zero,
       it's a reasonable indication that this is a compelte set of valid
       measurements.  (should really have a separate valid bit)
       */
    INST_set_size(thrindex, DistillerBufferLength(&dout.data));

  }  while ((status == distRedispatch)
            &&  t->task_age <= PERF_REQUEST_TTL);  /* do */
  
  /*
   *  "Copy" final output buffer to hp->pxy_hdrs/hp->pxy_data.  (Really
   *  we just copy the pointers, since the pxy_hdrs/pxy_data buffers
   *  will be freed by the caller.)
   *
   *  First generate headers to return to client.  If last-stage
   *  distiller returned
   *  some headers, use them; otherwise, replace the "content-length"
   *  and "content-type" fields of the ORIGINAL server headers with
   *  new values deduced from the distiller data.
   */
  if (status == distOk) {
    if (DistillerBufferLength(&(dout.metadata)) > 0) {
      DistillerBufferClone(&hp->pxy_hdrs, &dout.metadata);
    } else {
      /*
       *  If the server headers begin with an HTTP/x.x response code, they are
       *  headers from an origin server; OK to clone them and just replace the
       *  content-type and content-length.  Otherwise, they are probably
       *  the result of a server-mode dispatch worker, which means they
       *  actually look like request headers (not response headers), so delete them.
       */
      if (DistillerBufferLength(&hp->svr_hdrs) > 0
          && strncasecmp(DistillerBufferData(&hp->svr_hdrs), "HTTP/", 5) == 0) {
        DistillerBufferClone(&hp->pxy_hdrs, &hp->svr_hdrs);
        delete_header(&hp->pxy_hdrs,  "content-type");
        delete_header(&hp->pxy_hdrs,  "content-length");
      } else {
        char *s = "HTTP/1.0 200 OK\r\n\r\n";
        int l = strlen(s);
        DistillerBufferAlloc(&hp->pxy_hdrs, 1+l);
        strcpy((char *)(hp->pxy_hdrs.data), s);
        DistillerBufferSetLength(&hp->pxy_hdrs,l);
      }
    }
  
    /*
   *  Replace the "Content-length" and "Content-type"
   *  headers with the correct info.  Leave other headers
   *  alone.
   */
    if (get_header_value(&hp->pxy_hdrs, "content-type", NULL,NULL,NULL) 
	== NULL) {
      insert_header(&hp->pxy_hdrs, "Content-type", dout.mimeType, 1);
    }
    
    if (get_header_value(&hp->pxy_hdrs,"content-length",NULL,NULL,NULL)
	== NULL) {
      char __tmp[12];
      snprintf(__tmp, 11, "%lu", DistillerBufferLength(&dout.data));
      insert_header(&hp->pxy_hdrs, "Content-length", __tmp, 1);
    }

    DistillerBufferClone(&hp->pxy_data, &dout.data);
  }

  if ((status == distOk) || (status == distRedispatch)) {
    DistillerBufferFree(&dout.data);
    DistillerBufferFree(&dout.metadata);
  }

  /* Always free this */
  DistillerBufferFree(&din.data);
  DistillerBufferFree(&din.metadata);
  
  /* BUG::must do Clib_Put here??? */
  return (retcode);
}
Ejemplo n.º 22
0
void compose_request_buffer(http_request* request)
{
	char *buffer = calloc(1, REQUEST_BUFFER_SIZE * sizeof(char));
	ASSERT_ALLOCATE(buffer);

	size_t offset = 0;
	
	/* Start line */
	int bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s ", get_method_name(request->method));
	offset += bytes;

	/* Path, querystring, fragment */
	if (strlen(request->path) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s", request->path);
		offset += bytes;
	}

	if (strlen(request->querystring) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "?%s", request->querystring);
		offset += bytes;
	}

	if (strlen(request->fragment) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "#%s ", request->fragment);
		offset += bytes;
	}

	bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, " %s\r\n", HTTP_1_1);
	offset += bytes;
	/* Start line ends here */
	bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Accept: */*\r\n");
	offset += bytes;

	/* Host */ 
	if (is_match_pattern(request->host, REGEX_IPV4) != 0 && strcasecmp(request->host, "localhost") != 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Host: %s\r\n", request->host);
		offset += bytes;
	} else {
		char host[256] = {'\0'};
		get_header_value("Host", request->additional_header, host);
		if (strlen(host) == 0) {
			if (request->port == PORT_HTTP) {
				bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Host: %s\r\n", request->host);
				offset += bytes;
			} else { 
				bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Host: %s:%d\r\n", request->host, request->port);
				offset += bytes;
			}
		}
	}

	if (request->http_keep_alive == HTTP_KEEP_ALIVE) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Connection: keep-alive\r\n");
		offset += bytes;
	}
	
	if (strlen(request->bodydata) != 0 && request->file_upload != NULL) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
		offset += bytes;
	} else if (strlen(request->content_type) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Type: %s\r\n", request->content_type);
		offset += bytes;
	}

	if (request->additional_header != NULL) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s\r\n", request->additional_header);
		offset += bytes;
	}

	if (!(strlen(request->bodydata) != 0 && request->file_upload != NULL)) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Length: %d\r\n", request->content_length);
		offset += bytes;

		/* Header ends here */
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "\r\n");
		offset += bytes;

		SCREEN(SCREEN_BLUE, stdout, "Http request header:\n");
		SCREEN(SCREEN_GREEN, stdout, "%s", buffer);

		if (request->file_upload != NULL) {
			int fd = open(request->file_upload, O_RDONLY);
			if (fd < 0) {
				perror("open(2)");
				exit(EXIT_FAILURE);
			}

			bytes = read(fd, buffer + offset, request->content_length);
			if (bytes != request->content_length) {
				SCREEN(SCREEN_RED, stderr, "Cannot read your input file: %s.\n", request->file_upload);
				exit(EXIT_FAILURE);
			}
			offset += bytes;
		} else if (strlen(request->bodydata) != 0) {
			bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s", request->bodydata);
			offset += bytes;
		} 

	} else {
		/* Two multi-part */
		/* We need to caculate Content-Length again */
		char *extrabuffer = (char *) calloc(1, (REQUEST_BUFFER_SIZE) * sizeof(char));
		ASSERT_ALLOCATE(extrabuffer);

		int bodyoffset = 0;
		bytes = snprintf(extrabuffer + bodyoffset, REQUEST_BUFFER_SIZE - bodyoffset, "%s\r\nContent-Disposition: form-data; name=\"img\", filename=\"%s\"\r\nContent-Type: image/jpeg\r\n\r\n", 
				boundary, basename(request->file_upload));
		bodyoffset += bytes;
		int fd = open(request->file_upload, O_RDONLY);
		if (fd < 0) {
			perror("open(2)");
			exit(EXIT_FAILURE);
		}

		bytes = read(fd, extrabuffer + bodyoffset, request->file_size);
		if (bytes != request->file_size) {
			SCREEN(SCREEN_RED, stderr, "Cannot read your input file: %s.\n", request->file_upload);
			exit(EXIT_FAILURE);
		}
		bodyoffset += request->file_size;

		bytes = snprintf(extrabuffer + bodyoffset, REQUEST_BUFFER_SIZE - bodyoffset, "\r\n%s\r\nContent-Disposition: form-data; name=\"json\"\r\n\r\n%s\r\n%s\r\n",  boundary, request->bodydata, boundary); 
		bodyoffset += bytes;

		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Length: %d\r\n", bodyoffset);
		offset += bytes;

		/* Header ends here */
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "\r\n");
		offset += bytes;

		SCREEN(SCREEN_BLUE, stdout, "Http request header:\n");
		SCREEN(SCREEN_GREEN, stdout, "%s", buffer);

		memmove(buffer + offset, extrabuffer, bodyoffset);
		offset += bodyoffset;
	} 


	request->send_buffer = buffer;
	request->total_length = offset;

	return;
}
Ejemplo n.º 23
0
/*********************************************************************
 *
 * Function    :  is_untrusted_url
 *
 * Description :  Should we "distrust" this URL (and block it)?
 *
 *                Yes if it matches a line in the trustfile, or if the
 *                    referrer matches a line starting with "+" in the
 *                    trustfile.
 *                No  otherwise.
 *
 * Parameters  :
 *          1  :  csp = Current client state (buffers, headers, etc...)
 *
 * Returns     :  0 => trusted, 1 => untrusted
 *
 *********************************************************************/
int is_untrusted_url(struct client_state *csp)
{
   struct file_list *fl;
   struct block_spec *b;
   struct url_spec **trusted_url;
   struct http_request rhttp[1];
   const char * referer;
   jb_err err;

   /*
    * If we don't have a trustlist, we trust everybody
    */
   if (((fl = csp->tlist) == NULL) || ((b  = fl->f) == NULL))
   {
      return 0;
   }

   memset(rhttp, '\0', sizeof(*rhttp));

   /*
    * Do we trust the request URL itself?
    */
   for (b = b->next; b ; b = b->next)
   {
      if (url_match(b->url, csp->http))
      {
         return b->reject;
      }
   }

   if (NULL == (referer = get_header_value(csp->headers, "Referer:")))
   {
      /* no referrer was supplied */
      return 1;
   }


   /*
    * If not, do we maybe trust its referrer?
    */
   err = parse_http_url(referer, rhttp, csp);
   if (err)
   {
      return 1;
   }

   for (trusted_url = csp->config->trust_list; *trusted_url != NULL; trusted_url++)
   {
      if (url_match(*trusted_url, rhttp))
      {
         /* if the URL's referrer is from a trusted referrer, then
          * add the target spec to the trustfile as an unblocked
          * domain and return NULL (which means it's OK).
          */

         FILE *fp;

         if (NULL != (fp = fopen(csp->config->trustfile, "a")))
         {
            char * path;
            char * path_end;
            char * new_entry = strdup("~");

            string_append(&new_entry, csp->http->hostport);

            path = csp->http->path;
            if ( (path[0] == '/')
              && (path[1] == '~')
              && ((path_end = strchr(path + 2, '/')) != NULL))
            {
               /* since this path points into a user's home space
                * be sure to include this spec in the trustfile.
                */
               int path_len = path_end - path; /* save offset */
               path = strdup(path); /* Copy string */
               if (path != NULL)
               {
                  path_end = path + path_len; /* regenerate ptr to new buffer */
                  *(path_end + 1) = '\0'; /* Truncate path after '/' */
               }
               string_join(&new_entry, path);
            }

            if (new_entry != NULL)
            {
               fprintf(fp, "%s\n", new_entry);
               free(new_entry);
            }
            else
            {
               /* FIXME: No way to handle out-of memory, so mostly ignoring it */
               log_error(LOG_LEVEL_ERROR, "Out of memory adding pattern to trust file");
            }

            fclose(fp);
         }
         return 0;
      }
   }
   return 1;
}
Ejemplo n.º 24
0
int
http_transfer(UrlResource *rsrc)
{
        FILE *out 		= NULL;
        Url *u			= NULL;
        Url *proxy_url		= NULL;
        Url *redir_u		= NULL;
        char *request		= NULL;
        char *raw_header	= NULL;
        HttpHeader *header	= NULL;
        char *len_string 	= NULL;
        char *new_location	= NULL;
        char buf[BUFSIZE];
        int sock 		= 0;
        ssize_t bytes_read	= 0;
        int retval		= 0;
        int i;

        /* make sure we haven't recursed too much */

        if( redirect_count > REDIRECT_MAX ) {
                report(ERR, "redirection max count exceeded " 
                      "(looping redirect?)");
                redirect_count = 0;
                return 0;
        }


        /* make sure everything's initialized to something useful */
        u = rsrc->url;
     
        if( ! *(u->host) ) {
                report(ERR, "no host specified");
                return 0;
        }

        /* fill in proxyness */
        if( !rsrc->proxy ) {
                rsrc->proxy = get_proxy("HTTP_PROXY");
        }

        if( !rsrc->outfile ) {
                if( u->file ) 
                        rsrc->outfile = strdup(u->file);
                else
                        rsrc->outfile = strdup("index.html");
        }

        if( !u->path )
                u->path = strdup("/");

        if( !u->file )
                u->file = strdup("");  /* funny looking */

        if( !u->port )
                u->port = 80;

        rsrc->options |= default_opts;
                
        /* send the request to either the proxy or the remote host */
        if( rsrc->proxy ) {
                proxy_url = url_new();
                url_init(proxy_url, rsrc->proxy);
                
                if( !proxy_url->port ) 
                        proxy_url->port = 80;

                if( !proxy_url->host ) {
                        report(ERR, "bad proxy `%s'", rsrc->proxy);
                        return 0;
                }

                if( proxy_url->username )
                        rsrc->proxy_username = strdup(proxy_url->username);

                if( proxy_url->password )
                        rsrc->proxy_password = strdup(proxy_url->password);

                /* Prompt for proxy password if not specified */
                if( proxy_url->username && !proxy_url->password ) {
                        char *prompt = NULL;
                        prompt = strconcat("Password for proxy ",
                                           proxy_url->username, "@",
                                           proxy_url->host, ": ", NULL);
                        proxy_url->password = strdup(getpass(prompt));
                        free(prompt);
                }

                if( ! (sock = tcp_connect(proxy_url->host, proxy_url->port)) )
                        return 0;


                u->path = strdup("");
                u->file = strdup(u->full_url);
                request = get_request(rsrc);

                write(sock, request, strlen(request));

        } else /* no proxy */ {

                if( ! (sock = tcp_connect(u->host, u->port)) )
                        return 0;

                request = get_request(rsrc);
                write(sock, request, strlen(request));
        }

        
        out = open_outfile(rsrc);
        if( !out ) {
                report(ERR, "opening %s: %s", rsrc->outfile, strerror(errno));
                return 0;
        }

        /* check to see if it returned a HTTP 1.x response */
        memset(buf, '\0', 5);

        bytes_read = read(sock, buf, 8);

        if( bytes_read == 0 ) {
                close(sock);
                return 0;
        }

        if( ! (buf[0] == 'H' && buf[1] == 'T' 
               && buf[2] == 'T' && buf[3] == 'P') ) {
                if ((rsrc->options & OPT_RESUME) && 
                    rsrc->outfile_offset) {
                        report(WARN,
                               "server does not support resume, "
                               "try again"
                               " with -n (no resume)");
                        retval = 0;
                        goto cleanup;
                }
                write(fileno(out), buf, bytes_read);
        } else {
                /* skip the header */
                buf[bytes_read] = '\0';
                raw_header = get_raw_header(sock);
                raw_header = strconcat(buf, raw_header, NULL);
                header = make_http_header(raw_header);

                if (rsrc->options & OPT_VERBOSE) {
                        fwrite(raw_header, 1, strlen(raw_header), stderr);
                }


                /* check for redirects */
                new_location = get_header_value("location", header);

                if (raw_header[9] == '3' && new_location ) {
                        redir_u = url_new();
                        
                        /* make sure we still send user/password along */
                        redir_u->username = safe_strdup(u->username);
                        redir_u->password = safe_strdup(u->password);

                        url_init(redir_u, new_location);
                        rsrc->url = redir_u;
                        redirect_count++;
                        retval = transfer(rsrc);
                        goto cleanup;
                }

                if (raw_header[9] == '4' || raw_header[9] == '5') {
                        for(i = 0; raw_header[i] && raw_header[i] != '\n'; i++);
                        raw_header[i] = '\0';
                        report(ERR, "HTTP error from server: %s", raw_header);
                        retval = 0;
                        goto cleanup;
                }
                        
                len_string = get_header_value("content-length", header);

                if (len_string)
                        rsrc->outfile_size = (off_t )atoi(len_string);

                if (get_header_value("content-range", header))
                        rsrc->outfile_size += rsrc->outfile_offset;

                if( (!rsrc->outfile_size) && 
                    (rsrc->options & OPT_RESUME) && 
                    !(rsrc->options & OPT_NORESUME)
                    && rsrc->outfile_offset ) {
                        report(WARN,
                             "unable to determine remote file size, try again"
                             " with -n (no resume)");
                        retval = 0;
                        goto cleanup;
                }
        }

        if( ! dump_data(rsrc, sock, out) )
                retval = 0;
        else
                retval = 1;
                        
 cleanup:
        free_http_header(header);
        close(sock); fclose(out);
        return retval;

}
Ejemplo n.º 25
0
/*********************************************************************
 *
 * Function    :  block_url
 *
 * Description :  Called from `chat'.  Check to see if we need to block this.
 *
 * Parameters  :
 *          1  :  csp = Current client state (buffers, headers, etc...)
 *
 * Returns     :  NULL => unblocked, else HTTP block response
 *
 *********************************************************************/
struct http_response *block_url(struct client_state *csp)
{
#ifdef FEATURE_IMAGE_BLOCKING
   char *p;
#endif /* def FEATURE_IMAGE_BLOCKING */
   struct http_response *rsp;

   /*
    * If it's not blocked, don't block it ;-)
    */
   if ((csp->action->flags & ACTION_BLOCK) == 0)
   {
      return NULL;
   }

   /*
    * Else, prepare a response
    */
   if (NULL == (rsp = alloc_http_response()))
   {
      return cgi_error_memory();
   }

   /*
    * If it's an image-url, send back an image or redirect
    * as specified by the relevant +image action
    */
#ifdef FEATURE_IMAGE_BLOCKING
   if (((csp->action->flags & ACTION_IMAGE_BLOCKER) != 0)
        && is_imageurl(csp))
   {
      /* determine HOW images should be blocked */
      p = csp->action->string[ACTION_STRING_IMAGE_BLOCKER];

#if 1 /* Two alternative strategies, use this one for now: */

      /* and handle accordingly: */
      if ((p == NULL) || (0 == strcmpic(p, "pattern")))
      {
         rsp->body = bindup(image_pattern_data, image_pattern_length);
         if (rsp->body == NULL)
         {
            free_http_response(rsp);
            return cgi_error_memory();
         }
         rsp->content_length = image_pattern_length;

         if (enlist_unique_header(rsp->headers, "Content-Type", BUILTIN_IMAGE_MIMETYPE))
         {
            free_http_response(rsp);
            return cgi_error_memory();
         }
      }

      else if (0 == strcmpic(p, "blank"))
      {
         rsp->body = bindup(image_blank_data, image_blank_length);
         if (rsp->body == NULL)
         {
            free_http_response(rsp);
            return cgi_error_memory();
         }
         rsp->content_length = image_blank_length;

         if (enlist_unique_header(rsp->headers, "Content-Type", BUILTIN_IMAGE_MIMETYPE))
         {
            free_http_response(rsp);
            return cgi_error_memory();
         }
      }

      else
      {
         rsp->status = strdup("302 Local Redirect from Privoxy");
         if (rsp->status == NULL)
         {
            free_http_response(rsp);
            return cgi_error_memory();
         }

         if (enlist_unique_header(rsp->headers, "Location", p))
         {
            free_http_response(rsp);
            return cgi_error_memory();
         }
      }

#else /* Following code is disabled for now */

      /* and handle accordingly: */
      if ((p == NULL) || (0 == strcmpic(p, "pattern")))
      {
         p = CGI_PREFIX "send-banner?type=pattern";
      }
      else if (0 == strcmpic(p, "blank"))
      {
         p = CGI_PREFIX "send-banner?type=blank";
      }
      rsp->status = strdup("302 Local Redirect from Privoxy");
      if (rsp->status == NULL)
      {
         free_http_response(rsp);
         return cgi_error_memory();
      }

      if (enlist_unique_header(rsp->headers, "Location", p))
      {
         free_http_response(rsp);
         return cgi_error_memory();
      }
#endif /* Preceeding code is disabled for now */
   }
   else
#endif /* def FEATURE_IMAGE_BLOCKING */

   /*
    * Else, generate an HTML "blocked" message:
    */
   {
      jb_err err;
      struct map * exports;

      /*
       * Workaround for stupid Netscape bug which prevents
       * pages from being displayed if loading a referenced
       * JavaScript or style sheet fails. So make it appear
       * as if it succeeded.
       */
      if ( NULL != (p = get_header_value(csp->headers, "User-Agent:"))
           && !strncmpic(p, "mozilla", 7) /* Catch Netscape but */
           && !strstr(p, "Gecko")         /* save Mozilla, */
           && !strstr(p, "compatible")    /* MSIE */
           && !strstr(p, "Opera"))        /* and Opera. */
      {
         rsp->status = strdup("200 Request for blocked URL");
      }
      else
      {
         rsp->status = strdup("404 Request for blocked URL");
      }

      if (rsp->status == NULL)
      {
         free_http_response(rsp);
         return cgi_error_memory();
      }

      exports = default_exports(csp, NULL);
      if (exports == NULL)
      {
         free_http_response(rsp);
         return cgi_error_memory();
      }

#ifdef FEATURE_FORCE_LOAD
      err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
      if (csp->http->ssl != 0)
#endif /* ndef FEATURE_FORCE_LOAD */
      {
         err = map_block_killer(exports, "force-support");
      }

      if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1);
      if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0);
      if (!err) err = map(exports, "path", 1, html_encode(csp->http->path), 0);
      if (!err) err = map(exports, "path-ue", 1, url_encode(csp->http->path), 0);

      if (err)
      {
         free_map(exports);
         free_http_response(rsp);
         return cgi_error_memory();
      }

      err = template_fill_for_cgi(csp, "blocked", exports, rsp);
      if (err)
      {
         free_http_response(rsp);
         return cgi_error_memory();
      }
   }

   return finish_http_response(rsp);

}
Ejemplo n.º 26
0
int http_transfer(UrlResource *rsrc, libnet_callback notify)
{
	FILE *out 		= NULL;
	Url *u			= NULL;
	Url *proxy_url		= NULL;
	Url *redir_u		= NULL;
	char *request		= NULL;
	//char *raw_header	= NULL;
	HttpHeader *header	= NULL;
	//char *len_string 	= NULL;
	//char *new_location	= NULL;
    char *tmp_string    = NULL;
	//char buf[BUFSIZE];
	int sock 		= -1;
	ssize_t bytes_read	= 0;
    int msg_code    = 0;
	int retval		= 0;
	int i;

    char *buf = MALLOC(BUFSIZE);
    if (!buf)
    {
        LIBNET_DEBUG("No enough memory!\n");
        return 0;
    }
	/* make sure we haven't recursed too much */
	if ( redirect_count > REDIRECT_MAX )
	{
		LIBNET_DEBUG("redirection max count exceeded (looping redirect?)");
		redirect_count = 0;
        msg_code = -NET_ERR_CONNECT_FAILED;
        goto cleanup;
	}


	/* make sure everything's initialized to something useful */
	u = rsrc->url;
	if ( !u->host )
	{
		LIBNET_DEBUG("no host specified");
        msg_code = -NET_ERR_CONNECT_FAILED;
        goto cleanup;
	}

	/* fill in proxyness */
	if ( !rsrc->proxy )
	{
		rsrc->proxy = get_proxy("HTTP_PROXY");
	}

	if (( NULL == rsrc->outfile ) && (NULL == rsrc->buffer))
	{
		if ( u->file )
			rsrc->outfile = strdup(u->file);
		else
			rsrc->outfile = strdup("index.html");
	}

	if ( !u->path )
		u->path = strdup("/");

	if ( !u->file )
		u->file = strdup("");  /* funny looking */

	if ( !u->port )
		u->port = 80;

	rsrc->options |= default_opts;

	/* send the request to either the proxy or the remote host */
	if ( rsrc->proxy )
	{
		proxy_url = url_new();
		url_init(proxy_url, rsrc->proxy);

		if ( !proxy_url->port )
			proxy_url->port = 80;

		if ( !proxy_url->host )
		{
			LIBNET_DEBUG( "bad proxy `%s'", rsrc->proxy);
            msg_code = -NET_ERR_CONNECT_FAILED;
            goto cleanup;
		}

		if ( proxy_url->username )
			rsrc->proxy_username = strdup(proxy_url->username);
		if ( proxy_url->password )
			rsrc->proxy_password = strdup(proxy_url->password);

#ifdef LIB_W5300
		sock = w5300_tcp_connect(proxy_url->host, proxy_url->port, rsrc->srcip, rsrc->srcport);		
#else
		sock = util_tcp_connect(proxy_url->host, proxy_url->port);
#endif
		if (sock < 0)
		{
            msg_code = -NET_ERR_CONNECT_FAILED;
            goto cleanup;            
		}

		safe_free(u->path);
		safe_free(u->file);
		u->path = strdup("");
		u->file = strdup(u->full_url);
		request = get_request(rsrc);
        LIBNET_DEBUG("sending request:\n%s", request);
		S_WRITE(sock, request, STRLEN(request));

		FREE(request);
	}
	else /* no proxy */
	{
#ifdef LIB_W5300
		sock = w5300_tcp_connect(u->host, u->port, rsrc->srcip, rsrc->srcport);		
#else
		sock = util_tcp_connect(u->host, u->port);
#endif
		if (sock < 0)
		{
            msg_code = -NET_ERR_CONNECT_FAILED;
            goto cleanup;            
		}
		request = get_request(rsrc);
        LIBNET_DEBUG("sending request:\n%s", request);
		S_WRITE(sock, request, STRLEN(request));

		FREE(request);
	}

	if (rsrc->outfile)
	{
		if ((get_file_size(rsrc->outfile) > 0) && (rsrc->options & OPT_RESUME))
			out = fopen(rsrc->outfile, "rb+");
		else
			out = fopen(rsrc->outfile, "wb");

		if ( !out )
		{
			LIBNET_DEBUG( "opening %s: %s", rsrc->outfile, "");			
            msg_code = -NET_ERR_FILE_SAVE_ERROR;
            goto cleanup;
			
		}
	}

	/* check to see if it returned a HTTP 1.x response */
	MEMSET(buf, '\0', 5);

#ifdef LIB_W5300
	bytes_read = S_READ(sock, buf, BUFSIZE);
    buf[bytes_read] = '\0';
    LIBNET_DEBUG("receive respond:(%d)\n%s", bytes_read, buf);
#else
	bytes_read = S_READ(sock, buf, 8);
#endif

	if ( bytes_read <= 0 )
	{
        msg_code = -NET_ERR_HTTP_SERVER_ERROR;
        goto cleanup;
	}

	if ( ! (buf[0] == 'H' && buf[1] == 'T'
			&& buf[2] == 'T' && buf[3] == 'P') )
	{
		if((rsrc->options & OPT_RESUME) &&	rsrc->outfile_offset)
		{
			LIBNET_DEBUG("server does not support resume!");
            msg_code = -NET_ERR_OPERATION_NOT_PERMIT;
			goto cleanup;
		}
		//fwrite(buf, bytes_read, 1,out);
	}
	else
	{
		/* skip the header */
#ifdef LIB_W5300
        buf[bytes_read] = '\0';
#else
		char *raw_header1 = NULL;
		buf[bytes_read] = '\0';
		raw_header1 = get_raw_header(sock);
		strconcat2(buf, raw_header1, NULL);
		FREE(raw_header1);
        LIBNET_DEBUG("receive respond:(%d)\n%s", bytes_read, buf);
#endif
		header = make_http_header(buf);

		/* check for redirects */
		tmp_string = get_header_value("location", header);

		if (buf[9] == '3' && tmp_string )
		{
#if 1			//diable redirec function
			redir_u = url_new();

			/* make sure we still send user/password along */
			redir_u->username = safe_strdup(u->username);
			redir_u->password = safe_strdup(u->password);

			url_init(redir_u, tmp_string);
			rsrc->url = redir_u;
			redirect_count++;
			//retval = transfer(rsrc, notify);
			transfer((UINT32)rsrc, (UINT32)notify);
			rsrc->url =u;
			redirect_count--;
			if(redirect_count<0) redirect_count=0;
			if (redir_u)
			{
				url_destroy(redir_u);
				FREE(redir_u);
			}
#endif			
            FREE(tmp_string);
            tmp_string = NULL;
            //msg_code = -NET_ERR_OPERATION_NOT_PERMIT;//we can support redirect now, remove this line.
			goto cleanup;
		}
        if (tmp_string)
        {
            FREE(tmp_string);
            tmp_string = NULL;
        }

		if (buf[9] == '4' || buf[9] == '5')
		{
			for (i = 0; buf[i] && buf[i] != '\n'; i++);
			buf[i] = '\0';
			LIBNET_DEBUG("HTTP error from server: %s\n", buf);

			if( buf[9] == '4' && buf[10] == '0' && buf[11] == '4') 
				msg_code = -NET_ERR_FILE_NOT_FOUND;
			else
				msg_code = -NET_ERR_HTTP_SERVER_ERROR;
			
			goto cleanup;
		}

		tmp_string = get_header_value("content-length", header);

		if (tmp_string)
		{
			rsrc->outfile_size = (off_t )ATOI(tmp_string);
	            FREE(tmp_string);
	            tmp_string = NULL;		
			if(rsrc->use_pecache ==0)
			{
				if ((rsrc->buffer) && (rsrc->buffer_len < rsrc->outfile_size))
				{
					LIBNET_DEBUG("the buffer length less than the file fize (%d < %d)\n", rsrc->buffer, (int)rsrc->outfile_size);
				    msg_code = -NET_ERR_FILE_SAVE_ERROR;
					goto cleanup;
				}
			}				
		}

        tmp_string = get_header_value("content-range", header);
		if (tmp_string)
		{
            FREE(tmp_string);
            tmp_string = NULL;
			rsrc->outfile_size += rsrc->outfile_offset;
		}

		if ((!rsrc->outfile_size) &&
				(rsrc->options & OPT_RESUME) &&
				!(rsrc->options & OPT_NORESUME)
				&& rsrc->outfile_offset )
		{
			LIBNET_DEBUG("unable to determine remote file size");
            msg_code = -NET_ERR_FILE_SAVE_ERROR;
			goto cleanup;
		}
	}

if(rsrc->use_pecache ==0)
	retval = dump_data(rsrc, sock, out, notify);
else
	retval = dump_data_to_pecache(rsrc, sock, out, notify);

cleanup:
	free_http_header(header);

    //if (raw_header)
	//	FREE(raw_header);
		

	if (proxy_url)
	{
		url_destroy(proxy_url);
		FREE(proxy_url);
	}

    if (sock >= 0)
    {
	    S_CLOSE(sock);
    }

	if (out)
		fclose(out);

    if (buf)
    {
        FREE(buf);
    }

#ifndef WIN32
	if (rsrc->outfile)
		fs_sync(rsrc->outfile);
#endif

    if (msg_code < 0 && rsrc->running)
    { 
		notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)msg_code);
		libnet_abort_url_read(TRUE);//to break url_open while loop //retval!=1 means transfer fail
    }

	return retval;

}
Ejemplo n.º 27
0
void *
http_go_proc(task_t *t)
{
  int index = TASK_THRINDEX(t);
  Request h;
  ArgumentList prefs;
  userkey k;
  HTTP_Status result;
  DistillerStatus dist_result;
  const char *content_type;
  Argument *arg;
  int thresh;
  gm_Bool no_distill = gm_False;
  gm_Bool is_text_html = gm_False;
#ifdef LOGGING
  struct loginfo lo;
  char logmsg[MAX_LOGMSG_LEN];
#endif /* LOGGING */
  
  /*
   *  New task data should be the request structure.
   */
  init_Request(&h);
  h.cli_fd = (int)TASK_DATA(t); /* socket FD of client */
  SET_TASK_DATA(t,&h);
  
  INST_begin_timestamp(index);
  INST_set_size(index,0);
  INST_set_thread_state(index, THR_ACCEPTED);
  INST_timestamp(index, m_arrival);
#ifdef LOGGING
  LOGGING_init_loginfo(&lo);
  h.lo = &lo;
#endif /* LOGGING */
  /*
   *  this should read all the headers.
   */
  if (TASK_METADATA(t) == NULL) {
    int result;
    
    assert( DistillerBufferAlloc(&h.cli_hdrs, PERF_HTTP_TOTAL_HEADERLEN)
            == gm_True);

    result = readline_or_timeout(&h, READ_ALL_HEADERS, NULL);

    INST_timestamp(index, m_headersdone);
    if (result == -1) { /* client request timed out, or error reading hdrs */
      /* TC::1 client timeout, or request doesn't sanity check */
      goto HTTPGO_FINISH;
      /* NOTREACHED */
    }
  } else {
#ifdef NEWFE
    /*
     *  This task is a child of a previous 
     */
    strncpy(h.cli_hdrs.mime_headers, TASK_METADATA(t),
            PERF_HTTP_TOTAL_HEADERLEN-1);
    FREE(TASK_METADATA(t));
#endif /* NEWFE */
  }

  /* parse the headers and request line, filling them in to the loginfo */
  result = parse_status_and_headers(&h);
  if (result != HTTP_NO_ERR) {
    /* BUG:: last arg of http_error_return should be a substitution arg */
    /* TC::2 parse_status_and_headers returns an error */
    http_error_return(&h, result);
    printf("Error occured here!\n");
    goto HTTPGO_FINISH;
  }
  
  /*
   *  We have a reasonable looking request.  Get prefs for this user.
   */

  k = userkey_from_sock_ipaddr(h.cli_fd);
#ifdef LOGGING
  lo.ipaddr = k;
#endif /* LOGGING */
  (void)get_userprefs(k, &prefs);
  /*
   *  Extract any arguments embedded in the URL itself, and add them
   *  to the arg list.
   *  TC::3 url is magic vs nonmagic
   */
  if (is_magic ((char *) h.url)) {
    /* demagifying a url will never lengthen it so this is a good 
     * upper bounds on the length of the non magical url
     */
    char *demagicURL = ALLOCA(strlen(h.url)+1);
    assert(demagicURL);
    strcpy(demagicURL, h.url);
    from_magic((char *) demagicURL, h.url, &prefs);
  }

  /* determine the threshold for bypassing */
  arg  = getArgumentFromIdInList(&prefs, FRONT_MTU);
  thresh = (arg == NULL ? PERF_FRONT_MTU : ARG_INT(*arg));

  /* determine if distillation is turned off for this
   * request. EXCEPTION: Force distillation for Prefs html form.
   */
  arg = getArgumentFromIdInList(&prefs, FRONT_NO_DISTILL);
  if (arg != NULL
      && ARG_INT(*arg)
      && strcasecmp(fe_get_prefs_url, h.url) != 0) {
    /* TC::4 no_distill is set */
    no_distill = gm_True;
  }  else {
    no_distill = gm_False;
  }
  
  /* Short-circuit the following special  URL's:
   *  - "set my prefs as follows" (e.g. form submission)
   */
  if (is_setpref_url(h.url)) {
    /* 
     * handle what send user prefs form sends back.
     * TC::5 is_setpref_url returns true
     */
    result = parse_and_change_prefs(h.url, k, h.errmsg);
    if (result == HTTP_NO_ERR) {
      /* TC::5.1 setpref url succeeds in setting prefs */
      correct_write(h.cli_fd, "HTTP/1.0 200\r\nContent-type: text/html\r\n\r\n",
                    -1);
      correct_write(h.cli_fd,
                    "<html><head><title>Preferences Set</title></head>"
                    "<body><center><h1>Preferences set</h1>"
                    "Your new preferences have been set.  Press the back "
                    "button twice to resume browsing."
                    "<p></center></body></html>", -1);
    } else {
      /* TC::5.2 setpref url fails in setting prefs */
      http_error_return(&h, result);
    }
  } else if (is_getpref_url(h.url)) {
    /* TC::6 gimme my prefs*/
    send_prefs(&prefs, h.cli_fd);
  } else if (is_server_url(h.url)==gm_False   && 
	     strcasecmp(h.method, "get") != 0 && 
	     strcasecmp(h.method, "post") != 0) {
    /*
     *  Doesn't appear to be an HTTP GET or POST request; so act as a
     *  "dumb tunnel" for passing the request to the server (actually, via
     *  the cache) and relaying the result to the client.
     */
    /* TC::7 tunnel */
    proxy_debug_3(DBG_HTTP, "Tunneling '%s'", 
		  DistillerBufferData(&h.cli_hdrs));
    INST_set_thread_state(index, THR_DISTILLERSEND);
    tunnel(&h);
  } else {
    /*
     *  It's not a special URL, and the request appears to be a GET/POST.
     * Add in the client's IP address as an INT32 argument so that
     *  the distiller driver can get at it.
     */
    SET_ARG_INT(prefs.arg[prefs.nargs], (INT32) k);
    SET_ARG_ID(prefs.arg[prefs.nargs], FRONT_CLIENT_IP);
    prefs.nargs++;
    result = server_dispatch(&prefs, t);
    /*
     *  If we get a transport-level error (i.e. fetch from cache failed
     *  due to an internal cache error), wrap the error in HTML (if
     *  needed) and return error to user.
     *  Otherwise, if the transaction succeeded but the server return
     *  code indicates failure (i.e. != 200),  **OR** if the server data
     *  is smaller than a threshold size, bypass the server data
     *  directly to the client.
     *  Otherwise, attempt to distill.
     */
    if (result != HTTP_NO_ERR) {
      /* transport level error: wrap in HTML for delivery to user */
      /* TC::8 server_dispatch returns transport level error */
      http_error_return(&h, result);
      goto HTTPGO_FINISH;
    }

    content_type = get_header_value(&h.svr_hdrs,
                                    "content-type", NULL, NULL, NULL);
    if (content_type == NULL) {
      /* TC::9 content-type can't be deduced */
      content_type = "application/octet-stream";
    }
    is_text_html = (  ((strncasecmp(content_type, "text/html", 9) == 0) ||
                       (strncasecmp(content_type, "text/plain", 10) == 0))
                    ? gm_True : gm_False);
    
    /*if ( (*h.url != '/' && strncasecmp(h.url, fe_agg_string, 
				       strlen(fe_agg_string)) != 0) &&*/

    /* bypass ONLY if it is not a server-type URL */
    /* TC::10.1 bypass because non-200s status */
    /* TC::10.2 bypass because not text/html and too small to distill */
    /* TC::4 bypass because no_distill is set */
    /* bypass server data directly to user */

    if ( is_server_url(h.url)==gm_False) {
      char *bypass_reason = NULL;
      if (h.svr_http_status != 200) {
        bypass_reason = "201 Non-OK server status";
      } else if (is_text_html == gm_False
                 && DistillerBufferLength(&h.svr_data) <= thresh) {
        bypass_reason = "202 content-type not text/html and content-length too short";
      } else if (no_distill == gm_True) {
        bypass_reason = "203 distillation not indicated";
      }
      if (bypass_reason) {
        INST_set_thread_state(index, THR_WRITEBACK);
        /*
         *  Set return headers to indicate why the bypass occurred.
         */
        insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER, bypass_reason, 0);
        complete_bypass(&h);
        goto HTTPGO_FINISH;
      }
    }
    
    /* all is well: continue by dispatching to a worker for distillation */
    dist_result = proxy_dispatch(&prefs, t);
    switch(dist_result) {
    case distOk:
      /* TC::11 distillation succeeded */
      INST_timestamp(index, m_wbstart);
      insert_header(&h.pxy_hdrs, TRANSEND_STATUS_HEADER, "200 distillation OK", 0);
      correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_hdrs),
                    (int)DistillerBufferLength(&h.pxy_hdrs));
      /* -1 to avoid NULL term gunk */
      correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_data),
                    (int)DistillerBufferLength(&h.pxy_data));
      INST_timestamp(thrindex, m_wbdone);
      break;

    case distDistillerNotFound:
    case distLaunchTimeout:
    case distBadInput:
    case distConnectionBroken:

      /* forward original if distiller for this type not found, connection
         repeatedly broken, or couldn't be launched */
      /* TC::12 bypass because distillation failed */

      insert_header(&h.svr_hdrs,
                      (dist_result == distBadInput ? TRANSEND_STATUS_HEADER
                       : TRANSEND_ERROR_HEADER),
                      FE_getDistillerStatusString(dist_result), 0);
      if ((arg = getArgumentFromIdInList(&prefs, FRONT_DEVELOPER))
          && ARG_INT(*arg)) {
        /* return explicit error message */
        int tmp_len =
          snprintf(h.errmsg, HTTP_ERRMSG_MAX,
                   "<i>[set arg <tt>i%d</tt> to 0 to suppress "
                   "this diagnostic]</i><br>",
                   FRONT_DEVELOPER);
        strncat(h.errmsg, FE_getDistillerStatusString(dist_result),
                HTTP_ERRMSG_MAX - tmp_len - 1);
        http_error_return(&h, HTTP_ERR_UNSPECIFIED);
      } else {

        /*if (*h.url == '/' || 
	    strncasecmp(h.url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/

        if (is_server_url(h.url)==gm_True) {
          /* this is a URL in the frontend's namespace, or an aggregator URL */

          strcpy(h.errmsg, h.url);
          http_error_return(&h, HTTP_ERR_AGGREGATOR_ERROR);
        } else {
          complete_bypass(&h);
        }
      }
    break;
        
    case distRedispatch:
      /*
       *  Redispatch count expired: too many redispatches (probably indicates
       * infinite loop in redispatch route.)
       */
      snprintf(h.errmsg, HTTP_ERRMSG_MAX, "%d", PERF_REQUEST_TTL);
      http_error_return(&h, HTTP_ERR_ROUTING_ERROR);
      break;
      
    default:
        
      /* TC::13 some other distillation error */
      insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER,
                    FE_getDistillerStatusString(dist_result), 0);

      http_error_return(&h, HTTP_ERR_UNSPECIFIED);
      break;
    } /* switch(dist_result) */
  } /* if...else...else...endif */

  /* all cases exit through this single exit point */
HTTPGO_FINISH:
  free_Request(&h);
  INST_timestamp(index, m_wbdone);
  INST_end_timestamp(index);

  if (TASK_PARENT(t) == 0 && TASK_CHILD_INDEX(t) == 0) {
    /* this is a "root task" */
    close(h.cli_fd);
  }

#ifdef LOGGING
  /* log the request info */
  /* BUG::relies on formatting of the userkey */

  /* I compare the IP address to 127.0.0.1 so that I don't log connections
     from localhost, namely the fe_check script.  I also MD5 the IP address. */
  k = lo.ipaddr;
  if (((UINT32) k) != ((UINT32) htonl(0x7F000001))) {
/*    MD5_CTX   theHash;
    UINT32    res;

    MD5Init(&theHash);
    MD5Update(&theHash, magicKey, sizeof(magicKey));
    MD5Update(&theHash, &k, sizeof(UINT32));
    MD5Final(&theHash);

    memcpy(&res, theHash.digest, sizeof(UINT32));
    res = ntohl(res);

    snprintf(logmsg, MAX_LOGMSG_LEN-1,
             "(HTTP) %lu %lu \"%s\" %d %ld %ld\n",
             res, lo.date, lo.url,
             lo.http_response, lo.size_before, lo.size_after);*/
    snprintf(logmsg, MAX_LOGMSG_LEN-1,
             "(HTTP) %08x %08x \"%s\" %d %ld %ld\n",
             (UINT32) k, lo.date, lo.url,
             lo.http_response, lo.size_before, lo.size_after);
    gm_log(logmsg);
  }
#endif /* LOGGING */
  return (void *)0;
}
Ejemplo n.º 28
0
/*
 * Function Name: validate_session_policy
 * This is the NSAPI directive funtion which gets called for each request
 * It does session validation and policy check for each request.
 * Input: As defined by a SAF
 * Output: As defined by a SAF
 */
NSAPI_PUBLIC int
validate_session_policy(pblock *param, Session *sn, Request *rq) {
    const char *thisfunc = "validate_session_policy()";
    char *dpro_cookie = NULL;
    am_status_t status = AM_SUCCESS;
    int  requestResult = REQ_ABORTED;
    int	 notifResult = REQ_ABORTED;
    const char *ruser = NULL;
    am_map_t env_parameter_map = NULL;
    am_policy_result_t result = AM_POLICY_RESULT_INITIALIZER;
    void *args[] = { (void *)rq };
    char *request_url = NULL;
    char *orig_req = NULL ;
    char *response = NULL;
    char *clf_req = NULL;
    char *server_protocol = NULL;
    void *agent_config = NULL;
    char *logout_url = NULL;
    char *uri_hdr = NULL;
    char *pathInfo_hdr = NULL;
    char *method_hdr = NULL;
    char *method = NULL;
    char *virtHost_hdr = NULL;
    char *query_hdr = NULL;
    char *query = NULL;
    char *protocol = "HTTP";
    const char *clientIP_hdr_name = NULL;
    char *clientIP_hdr = NULL;
    char *clientIP = NULL;
    const char *clientHostname_hdr_name = NULL;
    char *clientHostname_hdr = NULL;
    char *clientHostname = NULL;
    am_status_t cdStatus = AM_FAILURE;

    // check if agent is initialized.
    // if not initialized, then call agent init function
    // This needs to be synchronized as only one time agent
    // initialization needs to be done.

    if(agentInitialized != B_TRUE){
        //Start critical section
        crit_enter(initLock);
        if(agentInitialized != B_TRUE){
            am_web_log_debug("%s: Will call init.", thisfunc);
            init_at_request(); 
            if(agentInitialized != B_TRUE){
                am_web_log_error("%s: Agent is still not intialized",
                                 thisfunc);
                //deny the access
                requestResult =  do_deny(sn, rq, status);
                status = AM_FAILURE;
            } else {
                am_web_log_debug("%s: Agent intialized");
            }
        }
        //end critical section
        crit_exit(initLock);
    }
    if (status == AM_SUCCESS) {
        // Get the agent configuration
        agent_config = am_web_get_agent_configuration();
        // Dump the entire set of request headers
        if (am_web_is_max_debug_on()) {
            char *header_str = pblock_pblock2str(rq->reqpb, NULL);
            am_web_log_max_debug("%s: Headers: %s", thisfunc, header_str);
            system_free(header_str);
        }
    }
    // Get header values
    if (status == AM_SUCCESS) {
        status = get_header_value(rq->reqpb, REQUEST_URI,
                               B_TRUE, &uri_hdr, B_FALSE, NULL);
    }
    if (status == AM_SUCCESS) {
        status = get_header_value(rq->vars, PATH_INFO,
                               B_FALSE, &pathInfo_hdr, B_FALSE, NULL);
    }
    if (status == AM_SUCCESS) {
        status = get_header_value(rq->reqpb, REQUEST_METHOD,
                               B_TRUE, &method_hdr, B_TRUE, &method);
    }
    if (status == AM_SUCCESS) {
        status = get_header_value(rq->headers, "ampxy_host",
                               B_TRUE, &virtHost_hdr, B_FALSE, NULL);
    }
    if (status == AM_SUCCESS) {
        status = get_header_value(rq->reqpb, REQUEST_QUERY,
                               B_FALSE, &query_hdr, B_TRUE, &query);
    }
    if (security_active) {
        protocol = "HTTPS";
    }
    // Get the request URL
    if (status == AM_SUCCESS) {
        if (am_web_is_proxy_override_host_port_set(agent_config) == AM_FALSE) {
            status = am_web_get_request_url(virtHost_hdr, protocol,
                                            NULL, 0, uri_hdr, query,
                                            &request_url, agent_config);
            if(status == AM_SUCCESS) {
                am_web_log_debug("%s: Request_url: %s", thisfunc, request_url);
            } else {
                am_web_log_error("%s: Could not get the request URL. "
                                 "Failed with error: %s.",
                                 thisfunc, am_status_to_string(status));
            }
        }
    }
    if (status == AM_SUCCESS) {
        if (am_web_is_proxy_override_host_port_set(agent_config) == AM_TRUE) {
            const char *agent_host = am_web_get_agent_server_host(agent_config);
            int agent_port = am_web_get_agent_server_port(agent_config);
            if (agent_host != NULL) {
                char *temp = NULL;
                temp = replace_host_port(request_url, agent_host, agent_port,
                                         agent_config);
                if (temp != NULL) {
                    free(request_url);
                    request_url = temp;
                }
            }
            am_web_log_debug("%s: Request_url after overriding "
                             "host and port: %s",
                             thisfunc, request_url);
        }
    }
    if (status == AM_SUCCESS) {
        // Check for magic notification URL
        if (B_TRUE == am_web_is_notification(request_url, agent_config)) {
            am_web_free_memory(request_url);
            am_web_delete_agent_configuration(agent_config);
            if(query != NULL) {
                free(query);
                query = NULL;
            }
            if(method != NULL) {
                free(method);
                method = NULL;
            }
            return REQ_PROCEED;
        }
    }
    // Check if the SSO token is in the cookie header
    if (status == AM_SUCCESS) {
        requestResult = getISCookie(pblock_findval(COOKIE_HDR, rq->headers),
                                    &dpro_cookie, agent_config);
        if (requestResult == REQ_ABORTED) {
            status = AM_FAILURE;
        } else if (dpro_cookie != NULL) {
            am_web_log_debug("%s: SSO token found in cookie header.",
                             thisfunc);
        }
    }
    // Create the environment map
    if( status == AM_SUCCESS) {
        status = am_map_create(&env_parameter_map);
        if( status != AM_SUCCESS) {
            am_web_log_error("%s: Unable to create map, status = %s (%d)",
                   thisfunc, am_status_to_string(status), status);
        }
    }    
    // If there is a proxy in front of the agent, the user can set in the
    // properties file the name of the headers that the proxy uses to set
    // the real client IP and host name. In that case the agent needs
    // to use the value of these headers to process the request
    //
    // Get the client IP address header set by the proxy, if there is one
    if (status == AM_SUCCESS) {
        clientIP_hdr_name = am_web_get_client_ip_header_name(agent_config);
        if (clientIP_hdr_name != NULL) {
            status = get_header_value(rq->headers, clientIP_hdr_name,
                                    B_FALSE, &clientIP_hdr,
                                    B_FALSE, NULL);
        }
    }
    // Get the client host name header set by the proxy, if there is one
    if (status == AM_SUCCESS) {
        clientHostname_hdr_name = 
               am_web_get_client_hostname_header_name(agent_config);
        if (clientHostname_hdr_name != NULL) {
            status = get_header_value(rq->headers, clientHostname_hdr_name,
                                    B_FALSE, &clientHostname_hdr,
                                    B_FALSE, NULL);
        }
    }
    // If the client IP and host name headers contain more than one
    // value, take the first value.
    if (status == AM_SUCCESS) {
        if ((clientIP_hdr != NULL) || (clientHostname_hdr != NULL)) {
            status = am_web_get_client_ip_host(clientIP_hdr,
                                               clientHostname_hdr,
                                               &clientIP, &clientHostname);
        }
    }
    // Set the IP address and host name in the environment map
    if ((status == AM_SUCCESS) && (clientIP != NULL)) {
        status = am_web_set_host_ip_in_env_map(clientIP, clientHostname,
                                      env_parameter_map, agent_config);
    }
    // If the client IP was not obtained previously,
    // get it from the REMOTE_ADDR header.
    if ((status == AM_SUCCESS) && (clientIP == NULL)) {
        status = get_header_value(sn->client, REQUEST_IP_ADDR,
                               B_FALSE, &clientIP_hdr, B_TRUE, &clientIP);
    }
    // In CDSSO mode, check if the sso token is in the post data
    if( status == AM_SUCCESS) {
        if((am_web_is_cdsso_enabled(agent_config) == B_TRUE) &&
                   (strcmp(method, REQUEST_METHOD_POST) == 0))
        {
            if((dpro_cookie == NULL) && 
               (am_web_is_url_enforced(request_url, pathInfo_hdr,
                        clientIP, agent_config) == B_TRUE))
            {
                // Set original method to GET
                orig_req = strdup(REQUEST_METHOD_GET);
                if (orig_req != NULL) {
                    am_web_log_debug("%s: Request method set to GET.",
                                          thisfunc);
                } else {
                    am_web_log_error("%s: Not enough memory to ",
                                "allocate orig_req.", thisfunc);
                    status = AM_NO_MEMORY;
                }
                // Check if dpro_cookie is in post data
                if( status == AM_SUCCESS) {
                    response = get_post_assertion_data(sn, rq, request_url);
                    status = am_web_check_cookie_in_post(args, &dpro_cookie,
                                               &request_url,
                                               &orig_req, method, response,
                                               B_FALSE, set_cookie, 
                                               set_method, agent_config);
                    if( status == AM_SUCCESS) {
                        am_web_log_debug("%s: SSO token found in "
                                             "assertion.",thisfunc);
                    } else {
                        am_web_log_debug("%s: SSO token not found in "
                                   "assertion. Redirecting to login page.",
                                   thisfunc);
                        status = AM_INVALID_SESSION;
                    }
                }
                // Set back the original clf-request attribute
                if (status == AM_SUCCESS) {
                    int clf_reqSize = 0;
                    if ((query != NULL) && (strlen(query) > 0)) {
                        clf_reqSize = strlen(orig_req) + strlen(uri_hdr) +
                                      strlen (query) + strlen(protocol) + 4;
                    } else {
                        clf_reqSize = strlen(orig_req) + strlen(uri_hdr) +
                                      strlen(protocol) + 3;
                    }
                    clf_req = malloc(clf_reqSize);
                    if (clf_req == NULL) {
                        am_web_log_error("%s: Unable to allocate %i "
                                         "bytes for clf_req",
                                         thisfunc, clf_reqSize);
                        status = AM_NO_MEMORY;
                    } else {
                        memset (clf_req,'\0',clf_reqSize);
                        strcpy(clf_req, orig_req);
                        strcat(clf_req, " ");
                        strcat(clf_req, uri_hdr);
                        if ((query != NULL) && (strlen(query) > 0)) {
                            strcat(clf_req, "?");
                            strcat(clf_req, query);
                        }
                        strcat(clf_req, " ");
                        strcat(clf_req, protocol);
                        am_web_log_debug("%s: clf-request set to %s",
                                          thisfunc, clf_req);
                    }
                    pblock_nvinsert(REQUEST_CLF, clf_req, rq->reqpb);
                }
            } 
        }
    }
    // Check if access is allowed.
    if( status == AM_SUCCESS) {
        if (dpro_cookie != NULL) {
            am_web_log_debug("%s: SSO token = %s", thisfunc, dpro_cookie);
        } else {
            am_web_log_debug("%s: SSO token not found.", thisfunc);
        }
        status = am_web_is_access_allowed(dpro_cookie,
                                          request_url,
                                          pathInfo_hdr, method,
                                          clientIP,
                                          env_parameter_map,
                                          &result,
                                          agent_config);
        am_map_destroy(env_parameter_map);
    }
    switch(status) {
    case AM_SUCCESS:
        // Set remote user and authentication type
        ruser = result.remote_user;
        if (ruser != NULL) {
            pb_param *pbuser = pblock_remove(AUTH_USER_VAR, rq->vars);
            pb_param *pbauth = pblock_remove(AUTH_TYPE_VAR, rq->vars);
            if (pbuser != NULL) {
                param_free(pbuser);
            }
            pblock_nvinsert(AUTH_USER_VAR, ruser, rq->vars);
            if (pbauth != NULL) {
                param_free(pbauth);
            }
            pblock_nvinsert(AUTH_TYPE_VAR, AM_WEB_AUTH_TYPE_VALUE, rq->vars);
            am_web_log_debug("%s: access allowed to %s", thisfunc, ruser);
        } else {
            am_web_log_debug("%s: Remote user not set, "
                             "allowing access to the url as it is in not "
                             "enforced list", thisfunc);
        }

        if (am_web_is_logout_url(request_url,  agent_config) == B_TRUE) {
            (void)am_web_logout_cookies_reset(reset_cookie, args, agent_config);
        }
        // set LDAP user attributes to http header
        status = am_web_result_attr_map_set(&result, set_header, 
                                           set_cookie_in_response, 
                                           set_header_attr_as_cookie, 
                                           get_cookie_sync, args, agent_config);
        if (status != AM_SUCCESS) {
            am_web_log_error("%s: am_web_result_attr_map_set failed, "
                        "status = %s (%d)", thisfunc,
                        am_status_to_string(status), status);
            requestResult = REQ_ABORTED;
        } else {
            requestResult = REQ_PROCEED;
        }
        break;

    case AM_ACCESS_DENIED:
        am_web_log_debug("%s: Access denied to %s", thisfunc,
                    result.remote_user ? result.remote_user :
                    "******");
        requestResult = do_redirect(sn, rq, status, &result,
                                request_url, method, agent_config);
        break;

    case AM_INVALID_SESSION:
        if (am_web_is_cdsso_enabled(agent_config) == B_TRUE) {
            cdStatus = am_web_do_cookie_domain_set(set_cookie, args,
                                                   EMPTY_STRING,
                                                   agent_config);
            if(cdStatus != AM_SUCCESS) {
                am_web_log_error("%s: CDSSO reset cookie failed", thisfunc);
            }
        }
        am_web_do_cookies_reset(reset_cookie, args, agent_config);
        requestResult =  do_redirect(sn, rq, status, &result,
                                 request_url, method,
                                 agent_config);
        break;

    case AM_INVALID_FQDN_ACCESS:
        // Redirect to self with correct FQDN - no post preservation
        requestResult = do_redirect(sn, rq, status, &result,
                                request_url, method, agent_config);
        break;

    case AM_REDIRECT_LOGOUT:
        status = am_web_get_logout_url(&logout_url, agent_config);
        if(status == AM_SUCCESS)
        {
            do_url_redirect(sn,rq,logout_url);
        }
        else
        {
            requestResult = REQ_ABORTED;
            am_web_log_debug("validate_session_policy(): "
                             "am_web_get_logout_url failed. ");
        }
        break;

    case AM_INVALID_ARGUMENT:
    case AM_NO_MEMORY:
    default:
        am_web_log_error("validate_session_policy() Status: %s (%d)",
                          am_status_to_string(status), status);
        requestResult = REQ_ABORTED;
        break;
    }
    // Cleaning
    am_web_clear_attributes_map(&result);
    am_policy_result_destroy(&result);
    am_web_free_memory(dpro_cookie);
    am_web_free_memory(request_url);
    am_web_free_memory(logout_url);
    am_web_delete_agent_configuration(agent_config);
    if (orig_req != NULL) {
        free(orig_req);
        orig_req = NULL;
    }
    if (response != NULL) {
        free(response);
        response = NULL;
    }
    if (clf_req != NULL) {
        free(clf_req);
        clf_req = NULL;
    }
    if(query != NULL) {
        free(query);
        query = NULL;
    }
    if(method != NULL) {
        free(method);
        method = NULL;
    }
    if(clientIP != NULL) {
        am_web_free_memory(clientIP);
    }
    if(clientHostname != NULL) {
        am_web_free_memory(clientHostname);
    }
    am_web_log_max_debug("%s: Completed handling request with status: %s.",
                         thisfunc, am_status_to_string(status));

    return requestResult;
}
Ejemplo n.º 29
0
void build_environ_header(conn_obj* objp){
	char *hdr_value;
	char *path_info;
	char *query_str;
	char *tmp;
	request_obj *req_objp;
	tmp=NULL;

	req_objp=objp->req_objp;
	path_info=req_objp->uri+strlen("/cgi");
	query_str=strchr(req_objp->uri,'?');
	query_str=query_str==NULL?query_str:query_str+1;

	hdr_value=get_header_value(req_objp->header_list,"Content-Length");
	add_tail(objp->environ_list,create_environ_header("CONTENT_LENGTH",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Content-Type");
	add_tail(objp->environ_list,create_environ_header("CONTENT_TYPE",hdr_value));

	add_tail(objp->environ_list,create_environ_header("GATEWAY_INTERFACE","CGI/1.1"));

	add_tail(objp->environ_list,create_environ_header("REQUEST_URI",req_objp->uri));

	add_tail(objp->environ_list,create_environ_header("PATH_INFO",path_info));

	add_tail(objp->environ_list,create_environ_header("QUERY_STRING",query_str));

	add_tail(objp->environ_list,create_environ_header("SCRIPT_NAME","/cgi"));

	add_tail(objp->environ_list,create_environ_header("REMOTE_ADDR",objp->remote_addr));
	switch(req_objp->mtdcode){
		case GET:
			tmp="GET";break;
		case POST:
			tmp="POST";break;
		case HEAD:
			tmp="HEAD";break;
		default:
			break;
	}

	add_tail(objp->environ_list,create_environ_header("REQUEST_METHOD",tmp));

	if(objp->protocal==HTTP){
		tmp=HTTP_port_str;
	}
	else{
		tmp=HTTPS_port_str;
	}
	add_tail(objp->environ_list,create_environ_header("SERVER_PORT",tmp));

	add_tail(objp->environ_list,create_environ_header("SERVER_PROTOCOL","HTTP/1.1"));

	add_tail(objp->environ_list,create_environ_header("SERVER_SOFTWARE","Liso/1.0"));

	hdr_value=get_header_value(req_objp->header_list,"Accept");
	add_tail(objp->environ_list,create_environ_header("HTTP_ACCEPT",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Referer");
	add_tail(objp->environ_list,create_environ_header("HTTP_REFERER",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Accept-Encoding");
	add_tail(objp->environ_list,create_environ_header("HTTP_ACCEPT_ENCODING",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Accept-Language");
	add_tail(objp->environ_list,create_environ_header("HTTP_ACCEPT_LANGUAGE",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Accept-Charset");
	add_tail(objp->environ_list,create_environ_header("HTTP_ACCEPT_CHARSET",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Host");
	add_tail(objp->environ_list,create_environ_header("HTTP_HOST",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Cookie");
	add_tail(objp->environ_list,create_environ_header("HTTP_COOKIE",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"User-Agent");
	add_tail(objp->environ_list,create_environ_header("HTTP_USER_AGENT",hdr_value));

	hdr_value=get_header_value(req_objp->header_list,"Connection");
	add_tail(objp->environ_list,create_environ_header("HTTP_CONNECTION",hdr_value));	


}