Exemple #1
0
/**
 * self: The SeahorseSource to use as server for the uri
 * path: The path to add to the SOUP uri
 *
 * Returns: A #SoupUri with server, port and paths
 */
static SoupURI*
get_http_server_uri (SeahorseHKPSource *self, const char *path)
{
    g_autoptr(SoupURI) uri = NULL;
    g_autofree gchar *server = NULL;
    gchar *port;

    g_object_get (self, "key-server", &server, NULL);
    g_return_val_if_fail (server != NULL, NULL);

    uri = soup_uri_new (NULL);
    soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);

    /* If it already has a port then use that */
    port = strchr (server, ':');
    if (port) {
        *port++ = '\0';
        soup_uri_set_port (uri, atoi (port));
    } else {
        /* default HKP port */
        soup_uri_set_port (uri, 11371);
    }

    soup_uri_set_host (uri, server);
    soup_uri_set_path (uri, path);

    return g_steal_pointer (&uri);
}
Exemple #2
0
/**
 * Change scheme and port of soup messages uri if the host is a known and
 * valid hsts host.
 *
 * This logic should be implemented in request_queued function but the changes
 * that are done there to the uri do not appear in webkit_web_view_get_uri().
 * If a valid hsts host is requested via http and the url is changed to https
 * vimb would still show the http uri in url bar. This seems to be a
 * missbehaviour in webkit, but for now we provide this function to put in the
 * logic in the scope of the navigation-policy-decision-requested event of the
 * webview.
 *
 * Returns newly allocated string with new URI if the URI was change to
 * fullfill HSTS, else NULL.
 */
char *hsts_get_changed_uri(SoupSession* session, SoupMessage *msg)
{
    SoupSessionFeature *feature;
    HSTSProvider *provider;
    SoupURI *uri;

    if (!msg) {
        return NULL;
    }

    feature = soup_session_get_feature_for_message(session, HSTS_TYPE_PROVIDER, msg);
    uri     = soup_message_get_uri(msg);
    if (!feature || !uri) {
        return NULL;
    }

    provider = HSTS_PROVIDER(feature);
    /* if URI uses still https we don't nee to rewrite it */
    if (uri->scheme != SOUP_URI_SCHEME_HTTPS
        && should_secure_host(provider, uri->host)
    ) {
        /* the ports is set by soup uri if scheme is changed */
        soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTPS);
        return soup_uri_to_string(uri, false);
    }
    return NULL;
}
Exemple #3
0
int
main (int argc, char **argv)
{
	SoupServer *server;
	SoupURI *uri;
	guint port;
	int ret;

	/* Force this test to use the dummy TLS backend */
	g_setenv ("GIO_USE_TLS", "dummy", TRUE);

	test_init (argc, argv, NULL);

	/* Make a non-SSL server and pretend that it's ssl, which is fine
	 * since we won't ever actually talk to it anyway. We don't
	 * currently test that failing to construct an SSL server works.
	 */
	server = soup_test_server_new (TRUE);
	soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
	uri = soup_test_server_get_uri (server, "http", NULL);
	port = uri->port;
	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
	soup_uri_set_port (uri, port);

	g_test_add_func ("/no-ssl/session-properties", do_session_property_tests);
	g_test_add_data_func ("/no-ssl/request-error", uri, do_ssl_tests);

	ret = g_test_run ();

	soup_uri_free (uri);
	soup_test_server_quit_unref (server);

	test_cleanup ();
	return ret;
}
Exemple #4
0
static GSocketAddressEnumerator *
soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable)
{
	SoupAddress *addr = SOUP_ADDRESS (connectable);
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	GSocketAddressEnumerator *proxy_enum;
	SoupURI *uri;
	char *uri_string;

	/* We cheerily assume "http" here because you shouldn't be
	 * using SoupAddress any more if you're not doing HTTP anyway.
	 */
	uri = soup_uri_new (NULL);
	soup_uri_set_scheme (uri, priv->protocol ? priv->protocol : "http");
	soup_uri_set_host (uri, priv->name ? priv->name : soup_address_get_physical (addr));
	soup_uri_set_port (uri, priv->port);
	soup_uri_set_path (uri, "");
	uri_string = soup_uri_to_string_internal (uri, FALSE, TRUE);

	proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
				   "connectable", connectable,
				   "uri", uri_string,
				   NULL);
	g_free (uri_string);
	soup_uri_free (uri);

	return proxy_enum;
}
static SoupURI *
uri_from_address (SoupAddress *addr)
{
	SoupURI *proxy_uri;

	proxy_uri = soup_uri_new (NULL);
	soup_uri_set_scheme (proxy_uri, SOUP_URI_SCHEME_HTTP);
	soup_uri_set_host (proxy_uri, soup_address_get_name (addr));
	soup_uri_set_port (proxy_uri, soup_address_get_port (addr));
	return proxy_uri;
}
static void 
seahorse_hkp_operation_init (SeahorseHKPOperation *hop)
{
    SoupURI *uri;
    gchar *host;
#if DEBUG_HKP_ENABLE
    SoupLogger *logger;
#endif
    
    if (seahorse_gconf_get_boolean (GCONF_USE_HTTP_PROXY)) {
        
        host = seahorse_gconf_get_string (GCONF_HTTP_PROXY_HOST);
        if (host) {
            uri = soup_uri_new (NULL);
            
            if (!uri) {
                g_warning ("creation of SoupURI from '%s' failed", host);
                
            } else {

                soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
                soup_uri_set_host (uri, host);
                g_free (host);
                soup_uri_set_port (uri, seahorse_gconf_get_integer (GCONF_PROXY_PORT));
                
                if (seahorse_gconf_get_boolean (GCONF_USE_AUTH)) {
                    char *user, *pass;

                    user = seahorse_gconf_get_string (GCONF_AUTH_USER);
                    soup_uri_set_user (uri, user);
                    g_free (user);
                    pass = seahorse_gconf_get_string (GCONF_AUTH_PASS);
                    soup_uri_set_password (uri, pass);
                    g_free (pass);
                }
                
                hop->session = soup_session_async_new_with_options (SOUP_SESSION_PROXY_URI, uri, NULL);
                soup_uri_free (uri);
            }
        }
    }
    
    /* Without a proxy */
    if (!hop->session)
        hop->session = soup_session_async_new ();

#if DEBUG_HKP_ENABLE
    logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
    soup_logger_attach (logger, hop->session);
    g_object_unref (logger);
#endif
}
void
dmap_connection_setup (DMAPConnection * connection)
{
	connection->priv->session = soup_session_async_new ();

	connection->priv->base_uri = soup_uri_new (NULL);
	soup_uri_set_scheme (connection->priv->base_uri,
			     SOUP_URI_SCHEME_HTTP);
	soup_uri_set_host (connection->priv->base_uri,
			   connection->priv->host);
	soup_uri_set_port (connection->priv->base_uri,
			   connection->priv->port);
}
Exemple #8
0
/**
 * Check if the host is known and switch the URI scheme to https.
 */
static void request_queued(SoupSessionFeature *feature,
    SoupSession *session, SoupMessage *msg)
{
    SoupURI *uri = soup_message_get_uri(msg);
    HSTSProvider *provider = HSTS_PROVIDER(feature);

    /* only look for HSTS headers sent over https RFC 6797 7.2*/
    if (uri->scheme == SOUP_URI_SCHEME_HTTPS) {
        soup_message_add_header_handler(
            msg, "got-headers", HSTS_HEADER_NAME, G_CALLBACK(process_hsts_header), feature
        );
    } else if (should_secure_host(provider, uri->host)) {
        /* the ports is set by soup uri if scheme is changed */
        soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTPS);
        soup_session_requeue_message(session, msg);
    }
}
Exemple #9
0
static SoupURI *
network_get_proxy_uri (void)
{
	SoupURI *uri = NULL;
	
	if (!proxyname)
		return uri;
		
	uri = soup_uri_new (NULL);
	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
	soup_uri_set_host (uri, proxyname);
	soup_uri_set_port (uri, proxyport);
	soup_uri_set_user (uri, proxyusername);
	soup_uri_set_password (uri, proxypassword);

	return uri;
}
Exemple #10
0
/**
 * Change scheme and port of soup messages uri if the host is a known and
 * valid hsts host.
 * This logic should be implemented in request_queued function but the changes
 * that are done there to the uri do not appear in webkit_web_view_get_uri().
 * If a valid hsts host is requested via http and the url is changed to https
 * vimb would still show the http uri in url bar. This seems to be a
 * missbehaviour in webkit, but for now we provide this function to put in the
 * logic in the scope of the resource-request-starting event of the webview.
 */
void hsts_prepare_message(SoupSession* session, SoupMessage *msg)
{
    SoupSessionFeature *feature;
    HSTSProvider *provider;
    SoupURI *uri;

    feature = soup_session_get_feature_for_message(session, HSTS_TYPE_PROVIDER, msg);
    uri     = soup_message_get_uri(msg);
    if (!feature || !uri) {
        return;
    }

    provider = HSTS_PROVIDER(feature);
    if (should_secure_host(provider, uri->host)) {
        /* the ports is set by soup uri if scheme is changed */
        soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTPS);
    }
}
Exemple #11
0
static void
liferea_webkit_set_proxy (const gchar *host, guint port, const gchar *user, const gchar *pwd)
{
	SoupURI *proxy = NULL;

	if (host) {
		proxy = soup_uri_new (NULL);
		soup_uri_set_scheme (proxy, SOUP_URI_SCHEME_HTTP);
		soup_uri_set_host (proxy, host);
		soup_uri_set_port (proxy, port);
		soup_uri_set_user (proxy, user);
		soup_uri_set_password (proxy, pwd);
	}

	g_object_set (webkit_get_default_session (),
		      SOUP_SESSION_PROXY_URI, proxy,
		      NULL);
}
Exemple #12
0
const gchar *
soupcut_server_build_uri(SoupServer   *server,
                              const gchar  *path)
{
    SoupAddress *address;
    SoupURI *uri;
    const gchar *uri_string;

    g_object_get(server,
                 SOUP_SERVER_INTERFACE, &address,
                 NULL);

    uri = soup_uri_new(NULL);
    soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTP);
    soup_uri_set_host(uri, "localhost");
    soup_uri_set_port(uri, soup_address_get_port(address));
    soup_uri_set_path(uri, path);

    uri_string = cut_take_string(soup_uri_to_string(uri, FALSE));
    soup_uri_free(uri);

    return uri_string;
}
Exemple #13
0
static void
network_set_soup_session_proxy (SoupSession *session, ProxyDetectMode mode, const gchar *host, guint port, const gchar *user, const gchar *password)
{
	SoupURI *uri = NULL;

	switch (mode) {
		case PROXY_DETECT_MODE_AUTO:
			/* Sets proxy-resolver to the default resolver, this unsets proxy-uri. */
			g_object_set (G_OBJECT (session),
				SOUP_SESSION_PROXY_RESOLVER, g_proxy_resolver_get_default (),
				NULL);
			break;
		case PROXY_DETECT_MODE_NONE:
			/* Sets proxy-resolver to NULL, this unsets proxy-uri. */
			g_object_set (G_OBJECT (session),
				SOUP_SESSION_PROXY_RESOLVER, NULL,
				NULL);
			break;
		case PROXY_DETECT_MODE_MANUAL:
			uri = soup_uri_new (NULL);
			soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
			soup_uri_set_host (uri, host);
			soup_uri_set_port (uri, port);
			soup_uri_set_user (uri, user);
			soup_uri_set_password (uri, password);
			soup_uri_set_path (uri, "/");

			if (SOUP_URI_IS_VALID (uri)) {
				/* Sets proxy-uri, this unsets proxy-resolver. */
				g_object_set (G_OBJECT (session),
					SOUP_SESSION_PROXY_URI, uri,
					NULL);
			}
			soup_uri_free (uri);
			break;
	}
}
Exemple #14
0
SoupMessageQueueItem *
soup_session_make_connect_message (SoupSession *session,
				   SoupAddress *server_addr)
{
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
	SoupURI *uri;
	SoupMessage *msg;

	uri = soup_uri_new (NULL);
	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
	soup_uri_set_host (uri, soup_address_get_name (server_addr));
	soup_uri_set_port (uri, soup_address_get_port (server_addr));
	soup_uri_set_path (uri, "");
	msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, uri);
	soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
	soup_uri_free (uri);

	/* Call the base implementation of soup_session_queue_message
	 * directly, to add msg to the SoupMessageQueue and cause all
	 * the right signals to be emitted.
	 */
	queue_message (session, msg, tunnel_connected, NULL);
	return soup_message_queue_lookup (priv->queue, msg);
}
static guint
parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
		       SoupEncoding *encoding, gpointer sock)
{
	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
	char *req_method, *req_path, *url;
	SoupHTTPVersion version;
	const char *req_host;
	guint status;
	SoupURI *uri;

	status = soup_headers_parse_request (headers, headers_len,
					     msg->request_headers,
					     &req_method,
					     &req_path,
					     &version);
	if (!SOUP_STATUS_IS_SUCCESSFUL (status))
		return status;

	g_object_set (G_OBJECT (msg),
		      SOUP_MESSAGE_METHOD, req_method,
		      SOUP_MESSAGE_HTTP_VERSION, version,
		      NULL);
	g_free (req_method);

	/* Handle request body encoding */
	*encoding = soup_message_headers_get_encoding (msg->request_headers);
	if (*encoding == SOUP_ENCODING_UNRECOGNIZED) {
		if (soup_message_headers_get_list (msg->request_headers, "Transfer-Encoding"))
			return SOUP_STATUS_NOT_IMPLEMENTED;
		else
			return SOUP_STATUS_BAD_REQUEST;
	}

	/* Generate correct context for request */
	req_host = soup_message_headers_get_one (msg->request_headers, "Host");
	if (req_host && strchr (req_host, '/')) {
		g_free (req_path);
		return SOUP_STATUS_BAD_REQUEST;
	}

	if (!strcmp (req_path, "*") && req_host) {
		/* Eg, "OPTIONS * HTTP/1.1" */
		url = g_strdup_printf ("%s://%s",
				       soup_socket_is_ssl (sock) ? "https" : "http",
				       req_host);
		uri = soup_uri_new (url);
		if (uri)
			soup_uri_set_path (uri, "*");
		g_free (url);
	} else if (*req_path != '/') {
		/* Must be an absolute URI */
		uri = soup_uri_new (req_path);
	} else if (req_host) {
		url = g_strdup_printf ("%s://%s%s",
				       soup_socket_is_ssl (sock) ? "https" : "http",
				       req_host, req_path);
		uri = soup_uri_new (url);
		g_free (url);
	} else if (priv->http_version == SOUP_HTTP_1_0) {
		/* No Host header, no AbsoluteUri */
		SoupAddress *addr = soup_socket_get_local_address (sock);

		uri = soup_uri_new (NULL);
		soup_uri_set_scheme (uri, soup_socket_is_ssl (sock) ?
				     SOUP_URI_SCHEME_HTTPS :
				     SOUP_URI_SCHEME_HTTP);
		soup_uri_set_host (uri, soup_address_get_physical (addr));
		soup_uri_set_port (uri, soup_address_get_port (addr));
		soup_uri_set_path (uri, req_path);
	} else
		uri = NULL;

	g_free (req_path);

	if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
		/* certainly not "a valid host on the server" (RFC2616 5.2.3)
		 * SOUP_URI_VALID_FOR_HTTP also guards against uri == NULL
		 */
		if (uri)
			soup_uri_free (uri);
		return SOUP_STATUS_BAD_REQUEST;
	}

	soup_message_set_uri (msg, uri);
	soup_uri_free (uri);

	return SOUP_STATUS_OK;
}
static gboolean
do_one_attempt (gpointer user_data)
{
  GError *local_error = NULL;
  MinCloudAgentApp *self = user_data;
  gs_free char *uri_str = NULL;
  gs_unref_object SoupRequest *request = NULL;
  gs_unref_object GInputStream *instream = NULL;
  gs_unref_object GFileOutputStream *outstream = NULL;
  gs_unref_object GFile *authorized_keys_path = NULL;
  gs_unref_object SoupMessage *msg = NULL;
  SoupURI *uri = NULL;
  const int max_request_failures = 5;
  const char *state_description = NULL;

  /* Skip over already completed states */
 again:
  switch (self->state)
    {
    case MCA_STATE_USER_DATA:
      if (g_file_query_exists (self->userdata_done_stamp, NULL))
        {
          self->state++;
          goto again;
        }
      break;
    case MCA_STATE_OPENSSH_KEY:
      if (g_file_query_exists (self->authorized_keys_path, NULL))
        {
          self->state++;
          goto again;
        }
      break;
    case MCA_STATE_DONE:
      goto out;
    }

  uri = soup_uri_new (NULL);
  soup_uri_set_scheme (uri, "http");
  {
    gs_free char *addr_str = g_inet_address_to_string (self->addr);
    soup_uri_set_host (uri, addr_str);
  }
  soup_uri_set_port (uri, g_inet_socket_address_get_port (self->addr_port));
  switch (self->state)
    {
    case MCA_STATE_USER_DATA:
      soup_uri_set_path (uri, "/2009-04-04/user-data");
      state_description = "user-data";
      break;
    case MCA_STATE_OPENSSH_KEY:
      soup_uri_set_path (uri, "/2009-04-04/meta-data/public-keys/0/openssh-key");
      state_description = "openssh-key";
      break;
    case MCA_STATE_DONE:
      g_assert_not_reached ();
    }

  uri_str = soup_uri_to_string (uri, FALSE);
  g_print ("Requesting '%s'...\n", uri_str);

  request = soup_session_request_uri (self->session, uri, &local_error);
  soup_uri_free (uri);
  if (!request)
    goto out;

  instream = soup_request_send (request, NULL, &local_error);
  if (!instream)
    goto out;

  msg = soup_request_http_get_message ((SoupRequestHTTP*) request);
  if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
    {
      switch (msg->status_code)
        {
        case 404:
        case 410:
          {
            gs_log_structured_print_id_v (MCA_NOT_FOUND_ID, "No %s found", state_description);
            g_clear_error (&local_error);
            /* Note fallthrough to out, where we'll advance to the
               next state */
            goto out;
          }
        default:
          /* Don't actually set the error, we will just continue to
           * the next phase.
           */
          gs_log_structured_print_id_v (MCA_TIMEOUT_ID,
                                        "Error fetching %s: %u %s",
                                        uri_str,
                                        msg->status_code,
                                        soup_status_get_phrase (msg->status_code));
          goto out;
        }
    }

  switch (self->state)
    {
    case MCA_STATE_USER_DATA:
      if (!handle_userdata_script (self, instream, self->cancellable,
                                   &local_error))
        goto out;
      break;
    case MCA_STATE_OPENSSH_KEY:
      if (!handle_install_authorized_keys (self, instream, self->cancellable,
                                           &local_error))
        goto out;
      break;
    default:
      g_assert_not_reached ();
    }

  g_assert (self->state != MCA_STATE_DONE);
  self->state++;
  self->request_failure_count = 0;

 out:
  if (local_error)
    {
      self->request_failure_count++;
      if (self->request_failure_count >= max_request_failures)
        {
          g_error_free (local_error);
          gs_log_structured_print_id_v (MCA_TIMEOUT_ID,
                                        "Reached maximum failed attempts (%u) to fetch metadata",
                                        self->request_failure_count);
          self->do_one_attempt_id = 0;
          self->running = FALSE;
        }
      else
        {
          gs_log_structured_print_id_v (MCA_REQUEST_FAILED_ID,
                                        "Request failed (count: %u): %s", self->request_failure_count,
                                        local_error->message);
          g_error_free (local_error);
          self->do_one_attempt_id = g_timeout_add_seconds (self->request_failure_count,
                                                           do_one_attempt, self);
        }
    }
  else
    {
      /* If we advanced in state, schedule the next callback in an
       * idle so we're consistently scheduled out of an idle.
       */
      if (self->state != MCA_STATE_DONE)
        self->do_one_attempt_id = g_idle_add (do_one_attempt, self);
      else
        {
          self->do_one_attempt_id = 0;
          self->running = FALSE;
        }
    }

  return FALSE;
}
static void
do_soup_uri_null_tests (void)
{
	SoupURI *uri, *uri2;
	char *uri_string;

	debug_printf (1, "\nsoup_uri_new (NULL)\n");
	uri = soup_uri_new (NULL);
	if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: soup_uri_new(NULL) returns valid URI?\n");
		errors++;
	}

	/* This implicitly also verifies that none of these methods g_warn */
	if (soup_uri_get_scheme (uri) ||
	    soup_uri_get_user (uri) ||
	    soup_uri_get_password (uri) ||
	    soup_uri_get_host (uri) ||
	    soup_uri_get_port (uri) ||
	    soup_uri_get_path (uri) ||
	    soup_uri_get_query (uri) ||
	    soup_uri_get_fragment (uri)) {
		debug_printf (1, "  ERROR: soup_uri_new(NULL) returns non-empty URI?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri2 = soup_uri_new_with_base (uri, "/path");
	if (uri2 || expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't fail on NULL URI?\n");
		errors++;
		expect_warning = FALSE;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on NULL URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (*uri_string) {
		debug_printf (1, "  ERROR: soup_uri_to_string on NULL URI returned '%s'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
	if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme on NULL URI makes it valid?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on scheme-only URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (strcmp (uri_string, "http:") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string returned '%s' instead of 'http:'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	soup_uri_set_host (uri, "localhost");
	if (SOUP_URI_IS_VALID (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host on NULL URI makes it valid?\n");
		errors++;
	}
	if (SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host on NULL URI makes it valid for http?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on scheme+host URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (strcmp (uri_string, "http://localhost/") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string with NULL path returned '%s' instead of 'http://localhost/'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	expect_warning = TRUE;
	uri2 = soup_uri_new_with_base (uri, "/path");
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't warn on NULL+scheme URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (!uri2) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't fix path on NULL+scheme URI\n");
		errors++;
	}

	if (uri2) {
		uri_string = soup_uri_to_string (uri2, FALSE);
		if (!uri_string) {
			debug_printf (1, "  ERROR: soup_uri_to_string failed on uri2?\n");
			errors++;
		} else if (strcmp (uri_string, "http://localhost/path") != 0) {
			debug_printf (1, "  ERROR: soup_uri_to_string returned '%s' instead of 'http://localhost/path'\n",
				      uri_string);
			errors++;
		}
		g_free (uri_string);
		soup_uri_free (uri2);
	}

	expect_warning = TRUE;
	soup_uri_set_path (uri, NULL);
	if (expect_warning) {
		debug_printf (1, "  ERROR: setting path to NULL doesn't warn\n");
		errors++;
		expect_warning = FALSE;
	}
	if (!uri->path || *uri->path) {
		debug_printf (1, "  ERROR: setting path to NULL != \"\"\n");
		errors++;
		soup_uri_set_path (uri, "");
	}

	uri_string = soup_uri_to_string (uri, FALSE);
	if (!uri_string) {
		debug_printf (1, "  ERROR: soup_uri_to_string failed on complete URI?\n");
		errors++;
	} else if (strcmp (uri_string, "http://localhost/") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string with empty path returned '%s' instead of 'http://localhost/'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	if (!SOUP_URI_IS_VALID (uri)) {
		debug_printf (1, "  ERROR: setting scheme+path on NULL URI doesn't make it valid?\n");
		errors++;
	}
	if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host+path on NULL URI doesn't make it valid for http?\n");
		errors++;
	}

	soup_uri_free (uri);
}
static void _do_token_query(GSignondOauthPlugin *self,
                         GSignondSessionData *session_data,
                         GHashTable* params,
                         GError** error)
{
    gboolean force_request_body_auth;
    if (gsignond_dictionary_get_boolean(session_data, 
        "ForceClientAuthViaRequestBody",
        &force_request_body_auth) && force_request_body_auth)
    {
        const gchar* client_id = gsignond_dictionary_get_string(session_data,
                                                            "ClientId");
        const gchar* client_secret = gsignond_dictionary_get_string(session_data,
                                                            "ClientSecret");
        if (client_id != NULL && client_secret != NULL) {
            g_hash_table_insert(params, "client_id", (gchar*)client_id);
            g_hash_table_insert(params, "client_secret", (gchar*)client_secret);
        }
    }
    
    const gchar* host = gsignond_dictionary_get_string(session_data, "TokenHost");
    if (host == NULL) {
        *error = g_error_new(GSIGNOND_ERROR,
                            GSIGNOND_ERROR_MISSING_DATA,
                            "TokenHost not set");
        return;
    }
    gsignond_oauth_plugin_check_host(host, gsignond_session_data_get_allowed_realms (session_data), error);
    if (*error != NULL)
        return;

    const gchar* token_path = gsignond_dictionary_get_string(session_data, "TokenPath");
    if (token_path == NULL) {
        *error = g_error_new(GSIGNOND_ERROR,
                            GSIGNOND_ERROR_MISSING_DATA,
                            "TokenPath not set");
        return;
    }
    
    const gchar* token_query_str = gsignond_dictionary_get_string(session_data, "TokenQuery");
    
    SoupURI* open_url = soup_uri_new(NULL);
    soup_uri_set_scheme(open_url, SOUP_URI_SCHEME_HTTPS);
    soup_uri_set_host(open_url, host);
    soup_uri_set_path(open_url, token_path);

    guint port;
    if (gsignond_dictionary_get_uint32(session_data, "TokenPort", &port) != FALSE)
        soup_uri_set_port(open_url, port);    

    if (token_query_str != NULL) {
        soup_uri_set_query(open_url, token_query_str);
    }
    
    SoupMessage *msg = soup_message_new_from_uri ("POST", open_url);
    soup_uri_free(open_url);
    gchar* formdata = soup_form_encode_hash(params);
    soup_message_set_request (msg, "application/x-www-form-urlencoded",
              SOUP_MEMORY_TAKE, formdata, strlen (formdata));
    
    soup_session_queue_message (self->soup_session, msg, _http_token_callback, self);
}
static void _request_new_token(GSignondOauthPlugin *self, 
                        GSignondSessionData *session_data,
                        GError** error)
{
    const gchar* response_type = gsignond_dictionary_get_string(session_data, "ResponseType");
    const gchar* grant_type = gsignond_dictionary_get_string(session_data, "GrantType");
    
    if (response_type != NULL &&
            (g_strcmp0(response_type, "code") == 0 || 
            g_strcmp0(response_type, "token") == 0)) {
        const gchar* host = gsignond_dictionary_get_string(session_data, "AuthHost");
        if (host == NULL) {
            *error = g_error_new(GSIGNOND_ERROR,
                                 GSIGNOND_ERROR_MISSING_DATA,
                                 "AuthHost not set");
            return;
        }

        gsignond_oauth_plugin_check_host(host, gsignond_session_data_get_allowed_realms (session_data), error);
        if (*error != NULL)
            return;
        
        const gchar* auth_path = gsignond_dictionary_get_string(session_data, "AuthPath");
        if (auth_path == NULL) {
            *error = g_error_new(GSIGNOND_ERROR,
                                 GSIGNOND_ERROR_MISSING_DATA,
                                 "AuthPath not set");
            return;
        }
        const gchar* client_id = gsignond_dictionary_get_string(session_data, "ClientId");
        if (client_id == NULL) {
            *error = g_error_new(GSIGNOND_ERROR,
                                 GSIGNOND_ERROR_MISSING_DATA,
                                 "ClientId not set");
            return;
        }

        SoupURI* open_url = soup_uri_new(NULL);
        soup_uri_set_scheme(open_url, SOUP_URI_SCHEME_HTTPS);
        soup_uri_set_host(open_url, host);
        soup_uri_set_path(open_url, auth_path);

        guint port;
        if (gsignond_dictionary_get_uint32(session_data, "AuthPort", &port) != FALSE)
            soup_uri_set_port(open_url, port);

        GHashTable* query = g_hash_table_new((GHashFunc)g_str_hash,
                                             (GEqualFunc)g_str_equal);
        const gchar* auth_query_str = gsignond_dictionary_get_string(session_data, "AuthQuery");
        GHashTable *auth_query = NULL;
        if (auth_query_str != NULL) {
            auth_query = soup_form_decode(auth_query_str);
            if (auth_query)
                // insert all key/values in AuthQuery into final query
                // according to RFC6749 section 3.1
                g_hash_table_foreach(auth_query, _insert_key_value, query);
        }

        g_hash_table_insert(query, "response_type", (gchar*)response_type);
        g_hash_table_insert(query, "client_id", (gchar*)client_id);
        
        const gchar* redirect_uri = gsignond_dictionary_get_string(session_data, "RedirectUri");
        if (redirect_uri != NULL) {
            g_hash_table_insert(query, "redirect_uri", (gchar*)redirect_uri);
        }

        const gchar* scope_str = gsignond_dictionary_get_string(session_data, "Scope");
        if (scope_str != NULL) {
            g_hash_table_insert(query, "scope", (gchar*)scope_str);
        }
        
        gchar* state = gsignond_oauth_plugin_generate_random_data(20);
        g_hash_table_insert(query, "state", state);
        gsignond_dictionary_set_string(self->oauth2_request, "_Oauth2State", state);

        const gchar* username = gsignond_session_data_get_username(session_data);
        const gchar* secret = gsignond_session_data_get_secret(session_data);

        // login_hint is a google extension specified here:
        // https://developers.google.com/accounts/docs/OAuth2InstalledApp#formingtheurl
        gboolean use_login_hint = FALSE;
        if (gsignond_dictionary_get_boolean(session_data, 
            "UseLoginHint", &use_login_hint) && 
            use_login_hint && username != NULL)
            g_hash_table_insert(query, "login_hint", (gchar*)username);
        
        // display is a facebook extension specified here:
        // https://developers.facebook.com/docs/reference/dialogs/oauth/
        const gchar* display = gsignond_dictionary_get_string(session_data, "UseDisplay");
        if (display != NULL) {
            g_hash_table_insert(query, "display", (gchar*)display);
        }
        
        soup_uri_set_query_from_form(open_url, query);
        g_free(state);
        g_hash_table_unref(query);
        if (auth_query)
            g_hash_table_unref(auth_query);

        char* open_url_str = soup_uri_to_string(open_url, FALSE);
        soup_uri_free(open_url);
        
        GSignondSignonuiData* ui_request = gsignond_dictionary_new();
        gsignond_signonui_data_set_open_url(ui_request, open_url_str);
        free(open_url_str);
        
        if (redirect_uri != NULL)
            gsignond_signonui_data_set_final_url(ui_request, redirect_uri);
        
        /* add username and password, for fields initialization (the
         * decision on whether to actually use them is up to the signon UI */
        if (username != NULL)
            gsignond_signonui_data_set_username(ui_request, username);
        if (secret != NULL)
            gsignond_signonui_data_set_password(ui_request, secret);
        
        gsignond_plugin_user_action_required(GSIGNOND_PLUGIN(self), ui_request);
        gsignond_dictionary_unref(ui_request);
        
    } else if (grant_type != NULL &&
            (g_strcmp0(grant_type, "password") == 0)) {
        const gchar* username = gsignond_session_data_get_username(session_data);
        const gchar* secret = gsignond_session_data_get_secret(session_data);
        if (username == NULL || secret == NULL) {
            *error = g_error_new(GSIGNOND_ERROR,
                                 GSIGNOND_ERROR_MISSING_DATA,
                                 "username or password not set");
            return;
        }
        GHashTable* params = g_hash_table_new((GHashFunc)g_str_hash,
                                             (GEqualFunc)g_str_equal);
        g_hash_table_insert(params, "grant_type", "password");
        g_hash_table_insert(params, "username", (gchar*)username);
        g_hash_table_insert(params, "password", (gchar*)secret);
        _set_scope(params, session_data);
    
        _do_token_query(self, session_data, params, error);
        g_hash_table_unref(params);
    } else if (grant_type != NULL &&
            (g_strcmp0(grant_type, "client_credentials") == 0)) {
        GHashTable* params = g_hash_table_new((GHashFunc)g_str_hash,
                                             (GEqualFunc)g_str_equal);
        g_hash_table_insert(params, "grant_type", "client_credentials");
        _set_scope(params, session_data);
    
        _do_token_query(self, session_data, params, error);
        g_hash_table_unref(params);
    } else {
        *error = g_error_new(GSIGNOND_ERROR,
                             GSIGNOND_ERROR_MISSING_DATA,
                             "Unknown ResponseType or GrantType");
    }
}
Exemple #20
0
static void
server_callback (SoupServer *server, SoupMessage *msg,
		 const char *path, GHashTable *query,
		 SoupClientContext *context, gpointer data)
{
	SoupURI *uri = soup_message_get_uri (msg);
	const char *server_protocol = data;

	soup_message_headers_append (msg->response_headers,
				     "X-Handled-By", "server_callback");

	if (!strcmp (path, "*")) {
		debug_printf (1, "    default server_callback got request for '*'!\n");
		errors++;
		soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
		return;
	}

	if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
		return;
	}

	if (!strcmp (path, "/redirect")) {
		soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/");
		return;
	}

	if (!strcmp (path, "/alias-redirect")) {
		SoupURI *redirect_uri;
		char *redirect_string;
		const char *redirect_protocol;

		redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol");

		redirect_uri = soup_uri_copy (uri);
		soup_uri_set_scheme (redirect_uri, "foo");
		if (!g_strcmp0 (redirect_protocol, "https"))
			soup_uri_set_port (redirect_uri, ssl_base_uri->port);
		else
			soup_uri_set_port (redirect_uri, base_uri->port);
		soup_uri_set_path (redirect_uri, "/alias-redirected");
		redirect_string = soup_uri_to_string (redirect_uri, FALSE);

		soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string);
		g_free (redirect_string);
		soup_uri_free (redirect_uri);
		return;
	} else if (!strcmp (path, "/alias-redirected")) {
		soup_message_set_status (msg, SOUP_STATUS_OK);
		soup_message_headers_append (msg->response_headers,
					     "X-Redirected-Protocol",
					     server_protocol);
		return;
	}

	if (!strcmp (path, "/slow")) {
		soup_server_pause_message (server, msg);
		g_object_set_data (G_OBJECT (msg), "server", server);
		soup_add_timeout (soup_server_get_async_context (server),
				  1000, timeout_finish_message, msg);
	}

	soup_message_set_status (msg, SOUP_STATUS_OK);
	if (!strcmp (uri->host, "foo")) {
		soup_message_set_response (msg, "text/plain",
					   SOUP_MEMORY_STATIC, "foo-index", 9);
		return;
	} else {
		soup_message_set_response (msg, "text/plain",
					   SOUP_MEMORY_STATIC, "index", 5);
		return;
	}
}