Beispiel #1
0
/**
 * g_vfs_ftp_connection_listen_data_connection:
 * @conn: a connection
 * @error: %NULL or location to take potential errors
 *
 * Initiates a listening socket that the FTP server can connect to. To accept 
 * connections and initialize data transfers, use 
 * g_vfs_ftp_connection_accept_data_connection().
 * This function supports what is known as "active FTP", while
 * g_vfs_ftp_connection_open_data_connection() is to be used for "passive FTP".
 *
 * Returns: the actual address the socket is listening on or %NULL on error
 **/
GSocketAddress *
g_vfs_ftp_connection_listen_data_connection (GVfsFtpConnection *conn,
                                             GError **          error)
{
  GSocketAddress *local, *addr;

  g_return_val_if_fail (conn != NULL, NULL);
  g_return_val_if_fail (conn->data == NULL, NULL);

  g_vfs_ftp_connection_stop_listening (conn);

  local = g_socket_connection_get_local_address (conn->connection, error);
  if (local == NULL)
    return NULL;

  conn->listen_socket = g_socket_new (g_socket_address_get_family (local),
                                      G_SOCKET_TYPE_STREAM,
                                      G_SOCKET_PROTOCOL_TCP,
                                      error);
  if (conn->listen_socket == NULL)
    return NULL;

  g_assert (G_IS_INET_SOCKET_ADDRESS (local));
  addr = g_inet_socket_address_new (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (local)), 0);
  g_object_unref (local);

  if (!g_socket_bind (conn->listen_socket, addr, TRUE, error) ||
      !g_socket_listen (conn->listen_socket, error) ||
      !(local = g_socket_get_local_address (conn->listen_socket, error)))
    {
      g_object_unref (addr);
      g_vfs_ftp_connection_stop_listening (conn);
      return NULL;
    }

  g_object_unref (addr);
  return local;
}
Beispiel #2
0
static gboolean
on_socket_input (GSocket *socket,
                 GIOCondition condition,
                 gpointer user_data)
{
  CockpitRequest *request = user_data;
  guchar first_byte;
  GInputVector vector[1] = { { &first_byte, 1 } };
  gint flags = G_SOCKET_MSG_PEEK;
  gboolean redirect_tls;
  gboolean is_tls;
  GSocketAddress *addr;
  GInetAddress *inet;
  GError *error = NULL;
  GIOStream *tls_stream;
  gssize num_read;

  num_read = g_socket_receive_message (socket,
                                       NULL, /* out GSocketAddress */
                                       vector,
                                       1,
                                       NULL, /* out GSocketControlMessage */
                                       NULL, /* out num_messages */
                                       &flags,
                                       NULL, /* GCancellable* */
                                       &error);
  if (num_read < 0)
    {
      /* Just wait and try again */
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
        {
          g_error_free (error);
          return TRUE;
        }

      if (!should_suppress_request_error (error))
        g_message ("couldn't read from socket: %s", error->message);

      cockpit_request_finish (request);
      g_error_free (error);
      return FALSE;
    }

  is_tls = TRUE;
  redirect_tls = FALSE;

  /*
   * TLS streams are guaranteed to start with octet 22.. this way we can distinguish them
   * from regular HTTP requests
   */
  if (first_byte != 22 && first_byte != 0x80)
    {
      is_tls = FALSE;
      redirect_tls = request->web_server->redirect_tls;
      if (redirect_tls)
        {
          addr = g_socket_connection_get_local_address (G_SOCKET_CONNECTION (request->io), NULL);
          if (G_IS_INET_SOCKET_ADDRESS (addr))
            {
              inet = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
              redirect_tls = !g_inet_address_get_is_loopback (inet);
            }
          g_clear_object (&addr);
        }
    }

  if (is_tls)
    {
      tls_stream = g_tls_server_connection_new (request->io,
                                                request->web_server->certificate,
                                                &error);
      if (tls_stream == NULL)
        {
          g_warning ("couldn't create new TLS stream: %s", error->message);
          cockpit_request_finish (request);
          g_error_free (error);
          return FALSE;
        }

      if (cockpit_webserver_want_certificate)
        {
          g_object_set (tls_stream, "authentication-mode", G_TLS_AUTHENTICATION_REQUESTED, NULL);
          g_signal_connect (tls_stream, "accept-certificate", G_CALLBACK (on_accept_certificate), NULL);
        }

      g_object_unref (request->io);
      request->io = G_IO_STREAM (tls_stream);
    }
  else if (redirect_tls)
    {
      request->delayed_reply = 301;
    }

  start_request_input (request);

  /* No longer run *this* source */
  return FALSE;
}
Beispiel #3
0
static void
synce_device_set_property (GObject      *obj,
                           guint         property_id,
                           const GValue *value,
                           GParamSpec   *pspec)
{
  SynceDevice *self = SYNCE_DEVICE (obj);
  SynceDevicePrivate *priv = SYNCE_DEVICE_GET_PRIVATE (self);

  switch (property_id) {
  case PROP_CONNECTION:
    if (priv->conn != NULL)
      {
	g_object_unref (priv->conn);
      }

    priv->conn = g_value_get_pointer (value);
    g_object_ref (priv->conn);

    GInputStream *in_stream = g_io_stream_get_input_stream(G_IO_STREAM(priv->conn));
    priv->iobuf = g_malloc(sizeof (guint32));
    g_input_stream_read_async(in_stream, priv->iobuf, sizeof (guint32), G_PRIORITY_DEFAULT, NULL, synce_device_conn_event_cb, g_object_ref(self));

    GInetSocketAddress *address = NULL;
    GInetAddress *inet_address = NULL;
    address = G_INET_SOCKET_ADDRESS(g_socket_connection_get_remote_address(priv->conn, NULL));
    inet_address = g_inet_socket_address_get_address(address);
    priv->ip_address =  g_inet_address_to_string(inet_address);
    g_object_unref(address);

    address = G_INET_SOCKET_ADDRESS(g_socket_connection_get_local_address(priv->conn, NULL));
    inet_address = g_inet_socket_address_get_address(address);
    priv->iface_address = g_inet_address_to_string(inet_address);
    g_object_unref(address);

    break;
  case PROP_DEVICE_PATH:
    g_free (priv->device_path);
    priv->device_path = g_value_dup_string (value);
    g_debug("%s: running for device %s", G_STRFUNC, priv->device_path);

    break;
  case PROP_OBJ_PATH:
    g_free (priv->obj_path);
    priv->obj_path = g_value_dup_string (value);
    break;
  case PROP_GUID:
    g_free (priv->guid);
    priv->guid = g_value_dup_string (value);
    break;
  case PROP_OS_MAJOR:
    priv->os_major = g_value_get_uint (value);
    break;
  case PROP_OS_MINOR:
    priv->os_minor = g_value_get_uint (value);
    break;
  case PROP_NAME:
    g_free (priv->name);
    priv->name = g_value_dup_string (value);
    break;
  case PROP_VERSION:
    priv->version = g_value_get_uint (value);
    break;
  case PROP_CPU_TYPE:
    priv->cpu_type = g_value_get_uint (value);
    break;
  case PROP_CURRENT_PARTNER_ID:
    priv->cur_partner_id = g_value_get_uint (value);
    break;
  case PROP_ID:
    priv->id = g_value_get_uint (value);
    break;
  case PROP_PLATFORM_NAME:
    g_free (priv->platform_name);
    priv->platform_name = g_value_dup_string (value);
    break;
  case PROP_MODEL_NAME:
    g_free (priv->model_name);
    priv->model_name = g_value_dup_string (value);
    break;
  case PROP_PASSWORD_FLAGS:
    priv->pw_flags = g_value_get_uint (value);
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
    break;
  }
}
static gboolean
connect_to_server (CamelService *service,
                   GCancellable *cancellable,
                   GError **error)
{
	CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
	CamelNetworkSettings *network_settings;
	CamelNetworkSecurityMethod method;
	CamelSettings *settings;
	CamelStream *stream;
	GIOStream *base_stream;
	GIOStream *tls_stream;
	gchar *respbuf = NULL;
	gboolean success = TRUE;
	gchar *host;

	if (!CAMEL_SERVICE_CLASS (camel_smtp_transport_parent_class)->
		connect_sync (service, cancellable, error))
		return FALSE;

	/* set some smtp transport defaults */
	transport->flags = 0;
	transport->authtypes = NULL;

	settings = camel_service_ref_settings (service);

	network_settings = CAMEL_NETWORK_SETTINGS (settings);
	host = camel_network_settings_dup_host (network_settings);
	method = camel_network_settings_get_security_method (network_settings);

	g_object_unref (settings);

	base_stream = camel_network_service_connect_sync (
		CAMEL_NETWORK_SERVICE (service), cancellable, error);

	if (base_stream != NULL) {
		/* get the localaddr - needed later by smtp_helo */
		transport->local_address =
			g_socket_connection_get_local_address (
			G_SOCKET_CONNECTION (base_stream), NULL);

		stream = camel_stream_new (base_stream);
		g_object_unref (base_stream);
	} else {
		success = FALSE;
		goto exit;
	}

	transport->connected = TRUE;

	transport->ostream = stream;
	transport->istream = camel_stream_buffer_new (
		stream, CAMEL_STREAM_BUFFER_READ);

	/* Read the greeting, note whether the server is ESMTP or not. */
	do {
		/* Check for "220" */
		g_free (respbuf);
		respbuf = camel_stream_buffer_read_line (
			CAMEL_STREAM_BUFFER (transport->istream),
			cancellable, error);
		d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
		if (respbuf == NULL) {
			g_prefix_error (error, _("Welcome response error: "));
			transport->connected = FALSE;
			success = FALSE;
			goto exit;
		}
		if (strncmp (respbuf, "220", 3)) {
			smtp_set_error (
				transport, respbuf, cancellable, error);
			g_prefix_error (error, _("Welcome response error: "));
			g_free (respbuf);
			success = FALSE;
			goto exit;
		}
	} while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */
	g_free (respbuf);

	/* Try sending EHLO */
	transport->flags |= CAMEL_SMTP_TRANSPORT_IS_ESMTP;
	if (!smtp_helo (transport, cancellable, error)) {
		if (!transport->connected) {
			success = FALSE;
			goto exit;
		}

		/* Fall back to HELO */
		g_clear_error (error);
		transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP;

		if (!smtp_helo (transport, cancellable, error)) {
			success = FALSE;
			goto exit;
		}
	}

	/* Clear any EHLO/HELO exception and assume that
	 * any SMTP errors encountered were non-fatal. */
	g_clear_error (error);

	if (method != CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT)
		goto exit;  /* we're done */

	if (!(transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS)) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Failed to connect to SMTP server %s in secure mode: %s"),
			host, _("STARTTLS not supported"));

		success = FALSE;
		goto exit;
	}

	d (fprintf (stderr, "[SMTP] sending: STARTTLS\r\n"));
	if (camel_stream_write (
		stream, "STARTTLS\r\n", 10, cancellable, error) == -1) {
		g_prefix_error (error, _("STARTTLS command failed: "));
		success = FALSE;
		goto exit;
	}

	respbuf = NULL;

	do {
		/* Check for "220 Ready for TLS" */
		g_free (respbuf);
		respbuf = camel_stream_buffer_read_line (
			CAMEL_STREAM_BUFFER (transport->istream),
			cancellable, error);
		d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
		if (respbuf == NULL) {
			g_prefix_error (error, _("STARTTLS command failed: "));
			transport->connected = FALSE;
			success = FALSE;
			goto exit;
		}
		if (strncmp (respbuf, "220", 3) != 0) {
			smtp_set_error (
				transport, respbuf, cancellable, error);
			g_prefix_error (error, _("STARTTLS command failed: "));
			g_free (respbuf);
			success = FALSE;
			goto exit;
		}
	} while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */

	/* Okay, now toggle SSL/TLS mode */
	base_stream = camel_stream_ref_base_stream (stream);
	tls_stream = camel_network_service_starttls (
		CAMEL_NETWORK_SERVICE (service), base_stream, error);
	g_object_unref (base_stream);

	if (tls_stream != NULL) {
		camel_stream_set_base_stream (stream, tls_stream);
		g_object_unref (tls_stream);
	} else {
		g_prefix_error (
			error,
			_("Failed to connect to SMTP server %s in secure mode: "),
			host);
		success = FALSE;
		goto exit;
	}

	/* We are supposed to re-EHLO after a successful STARTTLS to
	 * re-fetch any supported extensions. */
	if (!smtp_helo (transport, cancellable, error)) {
		success = FALSE;
	}

exit:
	g_free (host);

	if (!success) {
		transport->connected = FALSE;
		g_clear_object (&transport->istream);
		g_clear_object (&transport->ostream);
	}

	return success;
}