Blame src/goabackend/goaimapauthlogin.c

Packit 79f644
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit 79f644
/*
Packit 79f644
 * Copyright © 2011 – 2017 Red Hat, Inc.
Packit 79f644
 *
Packit 79f644
 * This library is free software; you can redistribute it and/or
Packit 79f644
 * modify it under the terms of the GNU Lesser General Public
Packit 79f644
 * License as published by the Free Software Foundation; either
Packit 79f644
 * version 2 of the License, or (at your option) any later version.
Packit 79f644
 *
Packit 79f644
 * This library is distributed in the hope that it will be useful,
Packit 79f644
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 79f644
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 79f644
 * Lesser General Public License for more details.
Packit 79f644
 *
Packit 79f644
 * You should have received a copy of the GNU Lesser General
Packit 79f644
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit 79f644
 */
Packit 79f644
Packit 79f644
#include "config.h"
Packit 79f644
Packit 79f644
#include <string.h>
Packit 79f644
Packit 79f644
#include <gio/gio.h>
Packit 79f644
#include <glib/gi18n-lib.h>
Packit 79f644
#include <stdlib.h>
Packit 79f644
Packit 79f644
#include "goaimapauthlogin.h"
Packit 79f644
#include "goautils.h"
Packit 79f644
Packit 79f644
/*
Packit 79f644
 * SECTION:goaimapauthlogin
Packit 79f644
 * @title: GoaImapAuthLogin
Packit 79f644
 * @short_description: LOGIN authentication method for IMAP
Packit 79f644
 *
Packit 79f644
 * #GoaImapAuthLogin implements the standard 
Packit 79f644
 * url="http://tools.ietf.org/html/rfc3501#section-6.2.3">LOGIN</ulink>
Packit 79f644
 * authentication method (e.g. using usernames / passwords) for IMAP.
Packit 79f644
 */
Packit 79f644
Packit 79f644
/*
Packit 79f644
 * GoaImapAuthLogin:
Packit 79f644
 *
Packit 79f644
 * The #GoaImapAuthLogin structure contains only private data
Packit 79f644
 * and should only be accessed using the provided API.
Packit 79f644
 */
Packit 79f644
struct _GoaImapAuthLogin
Packit 79f644
{
Packit 79f644
  GoaMailAuth parent_instance;
Packit 79f644
Packit 79f644
  gboolean greeting_absent;
Packit 79f644
  gchar *username;
Packit 79f644
  gchar *password;
Packit 79f644
};
Packit 79f644
Packit 79f644
enum
Packit 79f644
{
Packit 79f644
  PROP_0,
Packit 79f644
  PROP_USERNAME,
Packit 79f644
  PROP_PASSWORD
Packit 79f644
};
Packit 79f644
Packit 79f644
static gboolean goa_imap_auth_login_is_needed (GoaMailAuth        *auth);
Packit 79f644
static gboolean goa_imap_auth_login_run_sync (GoaMailAuth         *auth,
Packit 79f644
                                              GCancellable        *cancellable,
Packit 79f644
                                              GError             **error);
Packit 79f644
static gboolean goa_imap_auth_login_starttls_sync (GoaMailAuth    *auth,
Packit 79f644
                                                   GCancellable   *cancellable,
Packit 79f644
                                                   GError        **error);
Packit 79f644
Packit 79f644
G_DEFINE_TYPE (GoaImapAuthLogin, goa_imap_auth_login, GOA_TYPE_MAIL_AUTH);
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static const gchar *IMAP_TAG = "A001";
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
imap_auth_login_check_BYE (const gchar *response, GError **error)
Packit 79f644
{
Packit 79f644
  if (g_str_has_prefix (response, "* BYE"))
Packit 79f644
    {
Packit 79f644
      g_set_error (error,
Packit 79f644
                   GOA_ERROR,
Packit 79f644
                   GOA_ERROR_FAILED, /* TODO: more specific */
Packit 79f644
                   _("Service not available"));
Packit 79f644
      return TRUE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
imap_auth_login_check_NO (const gchar *response, GError **error)
Packit 79f644
{
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
  gchar *str = NULL;
Packit 79f644
Packit 79f644
  str = g_strdup_printf ("%s NO", IMAP_TAG);
Packit 79f644
Packit 79f644
  if (g_str_has_prefix (response, str))
Packit 79f644
    {
Packit 79f644
      g_set_error (error,
Packit 79f644
                   GOA_ERROR,
Packit 79f644
                   GOA_ERROR_FAILED, /* TODO: more specific */
Packit 79f644
                   _("Authentication failed"));
Packit 79f644
      ret = TRUE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_free (str);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
imap_auth_login_check_not_CAPABILITY (const gchar *response)
Packit 79f644
{
Packit 79f644
  if (!g_str_has_prefix (response, "* CAPABILITY"))
Packit 79f644
    return TRUE;
Packit 79f644
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
imap_auth_login_check_not_LOGIN (const gchar *response, GError **error)
Packit 79f644
{
Packit 79f644
  if (strstr (response, "AUTH=PLAIN") == NULL)
Packit 79f644
    {
Packit 79f644
      g_set_error (error,
Packit 79f644
                   GOA_ERROR,
Packit 79f644
                   GOA_ERROR_NOT_SUPPORTED,
Packit 79f644
                   _("Server does not support PLAIN"));
Packit 79f644
      return TRUE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
imap_auth_login_check_not_OK (const gchar *response, gboolean tagged, GError **error)
Packit 79f644
{
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
Packit 79f644
  if (tagged)
Packit 79f644
    {
Packit 79f644
      gchar *str;
Packit 79f644
Packit 79f644
      str = g_strdup_printf ("%s OK", IMAP_TAG);
Packit 79f644
      if (!g_str_has_prefix (response, str))
Packit 79f644
        {
Packit 79f644
          g_set_error (error,
Packit 79f644
                       GOA_ERROR,
Packit 79f644
                       GOA_ERROR_FAILED, /* TODO: more specific */
Packit 79f644
                       "Unexpected response `%s' while doing LOGIN authentication",
Packit 79f644
                       response);
Packit 79f644
          ret = TRUE;
Packit 79f644
        }
Packit 79f644
      g_free (str);
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    {
Packit 79f644
      if (!g_str_has_prefix (response, "* OK"))
Packit 79f644
        {
Packit 79f644
          g_set_error (error,
Packit 79f644
                       GOA_ERROR,
Packit 79f644
                       GOA_ERROR_FAILED, /* TODO: more specific */
Packit 79f644
                       "Unexpected response `%s' while doing LOGIN authentication",
Packit 79f644
                       response);
Packit 79f644
          ret = TRUE;
Packit 79f644
        }
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
imap_auth_login_check_not_STARTTLS (const gchar *response, GError **error)
Packit 79f644
{
Packit 79f644
  if (strstr (response, "STARTTLS") == NULL)
Packit 79f644
    {
Packit 79f644
      g_set_error (error,
Packit 79f644
                   GOA_ERROR,
Packit 79f644
                   GOA_ERROR_NOT_SUPPORTED,
Packit 79f644
                   _("Server does not support STARTTLS"));
Packit 79f644
      return TRUE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gchar *
Packit 79f644
imap_auth_escape_backslash (const gchar *str)
Packit 79f644
{
Packit 79f644
  GString *ret;
Packit 79f644
  gsize i;
Packit 79f644
  gsize len;
Packit 79f644
Packit 79f644
  ret = g_string_new ("");
Packit 79f644
  len = strlen (str);
Packit 79f644
Packit 79f644
  for (i = 0; i < len; i++)
Packit 79f644
    {
Packit 79f644
      if (str[i] == '\\')
Packit 79f644
        g_string_append_c (ret, '\\');
Packit 79f644
      g_string_append_c (ret, str[i]);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return g_string_free (ret, FALSE);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_imap_auth_login_finalize (GObject *object)
Packit 79f644
{
Packit 79f644
  GoaImapAuthLogin *self = GOA_IMAP_AUTH_LOGIN (object);
Packit 79f644
Packit 79f644
  g_free (self->username);
Packit 79f644
  g_free (self->password);
Packit 79f644
Packit 79f644
  G_OBJECT_CLASS (goa_imap_auth_login_parent_class)->finalize (object);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_imap_auth_login_get_property (GObject      *object,
Packit 79f644
                                  guint         prop_id,
Packit 79f644
                                  GValue       *value,
Packit 79f644
                                  GParamSpec   *pspec)
Packit 79f644
{
Packit 79f644
  GoaImapAuthLogin *self = GOA_IMAP_AUTH_LOGIN (object);
Packit 79f644
Packit 79f644
  switch (prop_id)
Packit 79f644
    {
Packit 79f644
    case PROP_USERNAME:
Packit 79f644
      g_value_set_string (value, self->username);
Packit 79f644
      break;
Packit 79f644
Packit 79f644
    case PROP_PASSWORD:
Packit 79f644
      g_value_set_string (value, self->password);
Packit 79f644
      break;
Packit 79f644
Packit 79f644
    default:
Packit 79f644
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 79f644
      break;
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_imap_auth_login_set_property (GObject      *object,
Packit 79f644
                                  guint         prop_id,
Packit 79f644
                                  const GValue *value,
Packit 79f644
                                  GParamSpec   *pspec)
Packit 79f644
{
Packit 79f644
  GoaImapAuthLogin *self = GOA_IMAP_AUTH_LOGIN (object);
Packit 79f644
Packit 79f644
  switch (prop_id)
Packit 79f644
    {
Packit 79f644
    case PROP_USERNAME:
Packit 79f644
      self->username = g_value_dup_string (value);
Packit 79f644
      break;
Packit 79f644
Packit 79f644
    case PROP_PASSWORD:
Packit 79f644
      self->password = g_value_dup_string (value);
Packit 79f644
      break;
Packit 79f644
Packit 79f644
    default:
Packit 79f644
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 79f644
      break;
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_imap_auth_login_init (GoaImapAuthLogin *self)
Packit 79f644
{
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_imap_auth_login_class_init (GoaImapAuthLoginClass *klass)
Packit 79f644
{
Packit 79f644
  GObjectClass *gobject_class;
Packit 79f644
  GoaMailAuthClass *auth_class;
Packit 79f644
Packit 79f644
  gobject_class = G_OBJECT_CLASS (klass);
Packit 79f644
  gobject_class->finalize     = goa_imap_auth_login_finalize;
Packit 79f644
  gobject_class->get_property = goa_imap_auth_login_get_property;
Packit 79f644
  gobject_class->set_property = goa_imap_auth_login_set_property;
Packit 79f644
Packit 79f644
  auth_class = GOA_MAIL_AUTH_CLASS (klass);
Packit 79f644
  auth_class->is_needed = goa_imap_auth_login_is_needed;
Packit 79f644
  auth_class->run_sync = goa_imap_auth_login_run_sync;
Packit 79f644
  auth_class->starttls_sync = goa_imap_auth_login_starttls_sync;
Packit 79f644
Packit 79f644
  /**
Packit 79f644
   * GoaImapAuthLogin:user-name:
Packit 79f644
   *
Packit 79f644
   * The user name.
Packit 79f644
   */
Packit 79f644
  g_object_class_install_property (gobject_class,
Packit 79f644
                                   PROP_USERNAME,
Packit 79f644
                                   g_param_spec_string ("user-name",
Packit 79f644
                                                        "user-name",
Packit 79f644
                                                        "user-name",
Packit 79f644
                                                        NULL,
Packit 79f644
                                                        G_PARAM_READABLE |
Packit 79f644
                                                        G_PARAM_WRITABLE |
Packit 79f644
                                                        G_PARAM_CONSTRUCT_ONLY |
Packit 79f644
                                                        G_PARAM_STATIC_STRINGS));
Packit 79f644
Packit 79f644
  /**
Packit 79f644
   * GoaImapAuthLogin:password:
Packit 79f644
   *
Packit 79f644
   * The password.
Packit 79f644
   */
Packit 79f644
  g_object_class_install_property (gobject_class,
Packit 79f644
                                   PROP_PASSWORD,
Packit 79f644
                                   g_param_spec_string ("password",
Packit 79f644
                                                        "password",
Packit 79f644
                                                        "password",
Packit 79f644
                                                        NULL,
Packit 79f644
                                                        G_PARAM_READABLE |
Packit 79f644
                                                        G_PARAM_WRITABLE |
Packit 79f644
                                                        G_PARAM_CONSTRUCT_ONLY |
Packit 79f644
                                                        G_PARAM_STATIC_STRINGS));
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_imap_auth_login_new:
Packit 79f644
 * @username: The user name to use.
Packit 79f644
 * @password: The password to use.
Packit 79f644
 *
Packit 79f644
 * Creates a new #GoaMailAuth to be used for username/password
Packit 79f644
 * authentication using LOGIN over IMAP.
Packit 79f644
 *
Packit 79f644
 * Returns: (type GoaImapAuthLogin): A #GoaImapAuthLogin. Free with
Packit 79f644
 * g_object_unref().
Packit 79f644
 */
Packit 79f644
GoaMailAuth *
Packit 79f644
goa_imap_auth_login_new (const gchar       *username,
Packit 79f644
                         const gchar       *password)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (username != NULL, NULL);
Packit 79f644
  g_return_val_if_fail (password != NULL && password[0] != '\0', NULL);
Packit 79f644
Packit 79f644
  return GOA_MAIL_AUTH (g_object_new (GOA_TYPE_IMAP_AUTH_LOGIN,
Packit 79f644
                                      "user-name", username,
Packit 79f644
                                      "password", password,
Packit 79f644
                                      NULL));
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_imap_auth_login_is_needed (GoaMailAuth *auth)
Packit 79f644
{
Packit 79f644
  /* TODO: support authentication-less IMAP servers */
Packit 79f644
  return TRUE;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_imap_auth_login_run_sync (GoaMailAuth         *auth,
Packit 79f644
                              GCancellable        *cancellable,
Packit 79f644
                              GError             **error)
Packit 79f644
{
Packit 79f644
  GoaImapAuthLogin *self = GOA_IMAP_AUTH_LOGIN (auth);
Packit 79f644
  GDataInputStream *input;
Packit 79f644
  GDataOutputStream *output;
Packit 79f644
  gchar *request = NULL;
Packit 79f644
  gchar *response = NULL;
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
  gchar *password = NULL;
Packit 79f644
Packit 79f644
  password = imap_auth_escape_backslash (self->password);
Packit 79f644
Packit 79f644
  input = goa_mail_auth_get_input (auth);
Packit 79f644
  output = goa_mail_auth_get_output (auth);
Packit 79f644
Packit 79f644
  /* Check the greeting, if there is one */
Packit 79f644
Packit 79f644
  if (!self->greeting_absent)
Packit 79f644
    {
Packit 79f644
      response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
      if (response == NULL)
Packit 79f644
        goto out;
Packit 79f644
      g_debug ("< %s", response);
Packit 79f644
      if (imap_auth_login_check_BYE (response, error))
Packit 79f644
        goto out;
Packit 79f644
      if (imap_auth_login_check_not_OK (response, FALSE, error))
Packit 79f644
        goto out;
Packit 79f644
      g_clear_pointer (&response, g_free);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  /* Send CAPABILITY */
Packit 79f644
Packit 79f644
  request = g_strdup_printf ("%s CAPABILITY\r\n", IMAP_TAG);
Packit 79f644
  g_debug ("> %s", request);
Packit 79f644
  if (!g_data_output_stream_put_string (output, request, cancellable, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&request, g_free);
Packit 79f644
Packit 79f644
  /* Check if LOGIN is supported or not */
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_not_LOGIN (response, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_not_OK (response, TRUE, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  /* Send LOGIN */
Packit 79f644
Packit 79f644
  request = g_strdup_printf ("%s LOGIN \"%s\" \"%s\"\r\n", IMAP_TAG, self->username, password);
Packit 79f644
  g_debug ("> %s LOGIN \"********************\" \"********************\"", IMAP_TAG);
Packit 79f644
  if (!g_data_output_stream_put_string (output, request, cancellable, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&request, g_free);
Packit 79f644
Packit 79f644
  /* Skip post-login CAPABILITY, if any */
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_not_CAPABILITY (response))
Packit 79f644
    goto check_login_response;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
 check_login_response:
Packit 79f644
  if (imap_auth_login_check_NO (response, error))
Packit 79f644
    goto out;
Packit 79f644
  if (imap_auth_login_check_not_OK (response, TRUE, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  ret = TRUE;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  g_free (response);
Packit 79f644
  g_free (request);
Packit 79f644
  g_free (password);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_imap_auth_login_starttls_sync (GoaMailAuth         *auth,
Packit 79f644
                                   GCancellable        *cancellable,
Packit 79f644
                                   GError             **error)
Packit 79f644
{
Packit 79f644
  GoaImapAuthLogin *self = GOA_IMAP_AUTH_LOGIN (auth);
Packit 79f644
  GDataInputStream *input;
Packit 79f644
  GDataOutputStream *output;
Packit 79f644
  gchar *request = NULL;
Packit 79f644
  gchar *response = NULL;
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
Packit 79f644
  input = goa_mail_auth_get_input (auth);
Packit 79f644
  output = goa_mail_auth_get_output (auth);
Packit 79f644
Packit 79f644
  /* Check the greeting */
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_BYE (response, error))
Packit 79f644
    goto out;
Packit 79f644
  if (imap_auth_login_check_not_OK (response, FALSE, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  /* Send CAPABILITY */
Packit 79f644
Packit 79f644
  request = g_strdup_printf ("%s CAPABILITY\r\n", IMAP_TAG);
Packit 79f644
  g_debug ("> %s", request);
Packit 79f644
  if (!g_data_output_stream_put_string (output, request, cancellable, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&request, g_free);
Packit 79f644
Packit 79f644
  /* Check if STARTTLS is supported or not */
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_not_STARTTLS (response, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_not_OK (response, TRUE, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  /* Send STARTTLS */
Packit 79f644
Packit 79f644
  request = g_strdup_printf ("%s STARTTLS\r\n", IMAP_TAG);
Packit 79f644
  g_debug ("> %s", request);
Packit 79f644
  if (!g_data_output_stream_put_string (output, request, cancellable, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&request, g_free);
Packit 79f644
Packit 79f644
  response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
Packit 79f644
  if (response == NULL)
Packit 79f644
    goto out;
Packit 79f644
  g_debug ("< %s", response);
Packit 79f644
  if (imap_auth_login_check_not_OK (response, TRUE, error))
Packit 79f644
    goto out;
Packit 79f644
  g_clear_pointer (&response, g_free);
Packit 79f644
Packit 79f644
  /* There won't be a greeting after this */
Packit 79f644
  self->greeting_absent = TRUE;
Packit 79f644
Packit 79f644
  ret = TRUE;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  g_free (response);
Packit 79f644
  g_free (request);
Packit 79f644
  return ret;
Packit 79f644
}