static void goa_smtp_auth_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GoaSmtpAuth *self = GOA_SMTP_AUTH (object); switch (prop_id) { case PROP_PROVIDER: self->provider = g_value_dup_object (value); break; case PROP_OBJECT: self->object = g_value_dup_object (value); break; case PROP_DOMAIN: self->domain = g_value_dup_string (value); break; case PROP_USERNAME: self->username = g_value_dup_string (value); break; case PROP_PASSWORD: self->password = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void goa_smtp_auth_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GoaSmtpAuth *auth = GOA_SMTP_AUTH (object); switch (prop_id) { case PROP_PROVIDER: g_value_set_object (value, auth->provider); break; case PROP_OBJECT: g_value_set_object (value, auth->object); break; case PROP_DOMAIN: g_value_set_string (value, auth->domain); break; case PROP_USERNAME: g_value_set_string (value, auth->username); break; case PROP_PASSWORD: g_value_set_string (value, auth->password); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void goa_smtp_auth_finalize (GObject *object) { GoaSmtpAuth *self = GOA_SMTP_AUTH (object); g_clear_object (&self->provider); g_clear_object (&self->object); g_free (self->domain); g_free (self->username); g_free (self->password); G_OBJECT_CLASS (goa_smtp_auth_parent_class)->finalize (object); }
static gboolean goa_smtp_auth_starttls_sync (GoaMailAuth *auth, GCancellable *cancellable, GError **error) { GoaSmtpAuth *self = GOA_SMTP_AUTH (auth); GDataInputStream *input; GDataOutputStream *output; gboolean ret; gboolean starttls_supported; gchar *domain; gchar *request; gchar *response; starttls_supported = FALSE; domain = NULL; request = NULL; response = NULL; ret = FALSE; domain = smtp_auth_get_domain (self, error); if (domain == NULL) goto out; input = goa_mail_auth_get_input (auth); output = goa_mail_auth_get_output (auth); /* Check the greeting */ if (!smtp_auth_check_greeting (input, cancellable, error)) goto out; /* Send EHLO */ request = g_strdup_printf ("EHLO %s\r\n", domain); g_debug ("> %s", request); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); /* Check if STARTTLS is supported or not */ ehlo_again: response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_421 (response, error)) goto out; if (smtp_auth_check_not_250 (response, error)) goto out; if (g_str_has_prefix (response + 4, "STARTTLS")) starttls_supported = TRUE; if (response[3] == '-') { g_free (response); goto ehlo_again; } else if (!starttls_supported) { g_set_error (error, GOA_ERROR, GOA_ERROR_NOT_SUPPORTED, _("Server does not support STARTTLS")); goto out; } g_clear_pointer (&response, g_free); /* Send STARTTLS */ request = g_strdup ("STARTTLS\r\n"); g_debug ("> %s", request); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_454 (response, error)) goto out; if (smtp_auth_check_not_220 (response, error)) goto out; g_clear_pointer (&response, g_free); /* There won't be a greeting after this */ self->greeting_absent = TRUE; ret = TRUE; out: g_free (domain); g_free (response); g_free (request); return ret; }
static gboolean goa_smtp_auth_run_sync (GoaMailAuth *auth, GCancellable *cancellable, GError **error) { GoaSmtpAuth *self = GOA_SMTP_AUTH (auth); GDataInputStream *input; GDataOutputStream *output; gboolean ret; gchar *auth_arg_base64; gchar *auth_arg_plain; gchar *domain; gchar *password; gchar *request; gchar *response; gsize auth_arg_plain_len; auth_arg_base64 = NULL; auth_arg_plain = NULL; domain = NULL; password = NULL; request = NULL; response = NULL; ret = FALSE; password = smtp_auth_get_password (self, cancellable, error); if (password == NULL) goto out; domain = smtp_auth_get_domain (self, error); if (domain == NULL) goto out; input = goa_mail_auth_get_input (auth); output = goa_mail_auth_get_output (auth); /* Check the greeting, if there is one */ if (!self->greeting_absent) { if (!smtp_auth_check_greeting (input, cancellable, error)) goto out; } /* Send EHLO */ request = g_strdup_printf ("EHLO %s\r\n", domain); g_debug ("> %s", request); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); /* Check which SASL mechanisms are supported */ ehlo_again: response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_421 (response, error)) goto out; if (smtp_auth_check_not_250 (response, error)) goto out; if (g_str_has_prefix (response + 4, "AUTH")) { self->auth_supported = TRUE; if (strstr (response, "PLAIN") != NULL) self->plain_supported = TRUE; else if (strstr (response, "LOGIN") != NULL) self->login_supported = TRUE; } if (response[3] == '-') { g_free (response); goto ehlo_again; } else if (!self->auth_supported) { ret = TRUE; goto out; } else if (!self->login_supported && !self->plain_supported) { g_set_error (error, GOA_ERROR, GOA_ERROR_NOT_SUPPORTED, _("Unknown authentication mechanism")); goto out; } g_clear_pointer (&response, g_free); /* Try different SASL mechanisms */ if (self->plain_supported) { /* AUTH PLAIN */ auth_arg_plain = g_strdup_printf ("%s%c%s%c%s", self->username, '\0', self->username, '\0', password); auth_arg_plain_len = 2 * strlen (self->username) + 2 + strlen (password); auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len); request = g_strdup_printf ("AUTH PLAIN %s\r\n", auth_arg_base64); g_debug ("> AUTH PLAIN ********************"); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); } else { /* AUTH LOGIN */ auth_arg_plain = g_strdup (self->username); auth_arg_plain_len = strlen (self->username); auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len); request = g_strdup_printf ("AUTH LOGIN %s\r\n", auth_arg_base64); g_debug ("> AUTH LOGIN ********************"); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_not_334_login_password (response, error)) goto out; g_free (auth_arg_plain); g_free (auth_arg_base64); auth_arg_plain = g_strdup (password); auth_arg_plain_len = strlen (password); auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len); request = g_strdup_printf ("%s\r\n", auth_arg_base64); g_debug ("> ********************"); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); } response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_not_235 (response, error)) goto out; g_clear_pointer (&response, g_free); ret = TRUE; out: g_free (auth_arg_base64); g_free (auth_arg_plain); g_free (domain); g_free (password); g_free (response); g_free (request); return ret; }
static gboolean goa_smtp_auth_is_needed (GoaMailAuth *auth) { GoaSmtpAuth *self = GOA_SMTP_AUTH (auth); return self->auth_supported; }