[gnome-online-accounts/gnome-3-14] kerberos: fail inquiry if provided buffer is too small for password



commit 8736e30aaeb22b1d783a1fe89939a504b6d9b98b
Author: Ray Strode <rstrode redhat com>
Date:   Tue Nov 4 09:40:38 2014 -0500

    kerberos: fail inquiry if provided buffer is too small for password
    
    Right now we just truncate the user's response if it's too big for
    the passed in buffer.  That's wrong on a theoretical level; we
    shouldn't ever use a password that the user didn't enter
    (even if it's a truncated version of what the user did enter).
    In practice, it's not actually a problem. The kerberos library provides
    a full 1024 byte buffer, which is much longer than a user would
    realistically enter into an entry.
    
    Still, this commit addresses the problem by introducing a mechanism for
    failing the inquiry.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=739593

 src/goaidentity/goaidentityinquiry.c         |    8 +++++
 src/goaidentity/goaidentityinquiry.h         |    2 +
 src/goaidentity/goakerberosidentity.c        |    4 ++-
 src/goaidentity/goakerberosidentityinquiry.c |   43 ++++++++++++++++++++++---
 4 files changed, 50 insertions(+), 7 deletions(-)
---
diff --git a/src/goaidentity/goaidentityinquiry.c b/src/goaidentity/goaidentityinquiry.c
index d065d3a..1eefdb6 100644
--- a/src/goaidentity/goaidentityinquiry.c
+++ b/src/goaidentity/goaidentityinquiry.c
@@ -74,6 +74,14 @@ goa_identity_inquiry_is_complete (GoaIdentityInquiry *self)
   return GOA_IDENTITY_INQUIRY_GET_IFACE (self)->is_complete (self);
 }
 
+gboolean
+goa_identity_inquiry_is_failed (GoaIdentityInquiry *self)
+{
+  g_return_val_if_fail (GOA_IS_IDENTITY_INQUIRY (self), TRUE);
+
+  return GOA_IDENTITY_INQUIRY_GET_IFACE (self)->is_failed (self);
+}
+
 void
 goa_identity_inquiry_iter_init (GoaIdentityInquiryIter *iter,
                                 GoaIdentityInquiry     *inquiry)
diff --git a/src/goaidentity/goaidentityinquiry.h b/src/goaidentity/goaidentityinquiry.h
index da34f37..32dbd13 100644
--- a/src/goaidentity/goaidentityinquiry.h
+++ b/src/goaidentity/goaidentityinquiry.h
@@ -79,6 +79,7 @@ struct _GoaIdentityInquiryInterface
                                        GoaIdentityQuery   *query);
   gboolean             (* is_answered) (GoaIdentityInquiry *inquiry,
                                         GoaIdentityQuery   *query);
+  gboolean             (* is_failed)  (GoaIdentityInquiry *inquiry);
 };
 
 GType goa_identity_inquiry_get_type (void);
@@ -87,6 +88,7 @@ GoaIdentity *goa_identity_inquiry_get_identity (GoaIdentityInquiry *inquiry);
 char        *goa_identity_inquiry_get_name     (GoaIdentityInquiry *inquiry);
 char        *goa_identity_inquiry_get_banner   (GoaIdentityInquiry *inquiry);
 gboolean     goa_identity_inquiry_is_complete  (GoaIdentityInquiry *inquiry);
+gboolean     goa_identity_inquiry_is_failed    (GoaIdentityInquiry *inquiry);
 void         goa_identity_inquiry_answer_query (GoaIdentityInquiry *inquiry,
                                                 GoaIdentityQuery   *query,
                                                 const char         *answer);
diff --git a/src/goaidentity/goakerberosidentity.c b/src/goaidentity/goakerberosidentity.c
index c862941..d501a59 100644
--- a/src/goaidentity/goakerberosidentity.c
+++ b/src/goaidentity/goakerberosidentity.c
@@ -999,7 +999,9 @@ on_kerberos_inquiry (krb5_context      kerberos_context,
                            operation->cancellable,
                            operation->inquiry_data);
 
-  if (!goa_identity_inquiry_is_complete (inquiry))
+  if (goa_identity_inquiry_is_failed (inquiry))
+    error_code = KRB5_LIBOS_CANTREADPWD;
+  else if (!goa_identity_inquiry_is_complete (inquiry))
     g_cancellable_cancel (operation->cancellable);
 
   if (g_cancellable_is_cancelled (operation->cancellable))
diff --git a/src/goaidentity/goakerberosidentityinquiry.c b/src/goaidentity/goakerberosidentityinquiry.c
index e1bbfd6..4851ca7 100644
--- a/src/goaidentity/goakerberosidentityinquiry.c
+++ b/src/goaidentity/goakerberosidentityinquiry.c
@@ -33,6 +33,7 @@ struct _GoaKerberosIdentityInquiryPrivate
   GList *queries;
   int number_of_queries;
   int number_of_unanswered_queries;
+  guint is_failed : 1;
 };
 
 typedef struct
@@ -230,7 +231,19 @@ goa_kerberos_identity_inquiry_is_complete (GoaIdentityInquiry *inquiry)
 
   self = GOA_KERBEROS_IDENTITY_INQUIRY (inquiry);
 
-  return self->priv->number_of_unanswered_queries == 0;
+  return self->priv->number_of_unanswered_queries == 0 || self->priv->is_failed;
+}
+
+static gboolean
+goa_kerberos_identity_inquiry_is_failed (GoaIdentityInquiry *inquiry)
+{
+  GoaKerberosIdentityInquiry *self;
+
+  g_return_val_if_fail (GOA_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), FALSE);
+
+  self = GOA_KERBEROS_IDENTITY_INQUIRY (inquiry);
+
+  return self->priv->is_failed;
 }
 
 static void
@@ -252,12 +265,20 @@ goa_kerberos_identity_inquiry_mark_query_answered (GoaKerberosIdentityInquiry *
 }
 
 static void
+goa_kerberos_identity_inquiry_fail (GoaKerberosIdentityInquiry *self)
+{
+  self->priv->is_failed = TRUE;
+  _goa_identity_inquiry_emit_complete (GOA_IDENTITY_INQUIRY (self));
+}
+
+static void
 goa_kerberos_identity_inquiry_answer_query (GoaIdentityInquiry * inquiry,
                                             GoaIdentityQuery *query,
                                             const char *answer)
 {
   GoaKerberosIdentityInquiry *self;
   GoaKerberosIdentityQuery *kerberos_query = (GoaKerberosIdentityQuery *) query;
+  size_t answer_length;
 
   g_return_if_fail (GOA_IS_KERBEROS_IDENTITY_INQUIRY (inquiry));
   g_return_if_fail (inquiry == kerberos_query->inquiry);
@@ -265,12 +286,21 @@ goa_kerberos_identity_inquiry_answer_query (GoaIdentityInquiry * inquiry,
 
   self = GOA_KERBEROS_IDENTITY_INQUIRY (inquiry);
 
-  strncpy (kerberos_query->kerberos_prompt->reply->data,
-           answer, kerberos_query->kerberos_prompt->reply->length);
-  kerberos_query->kerberos_prompt->reply->length =
-    (unsigned int) strlen (kerberos_query->kerberos_prompt->reply->data);
+  answer_length = strlen (answer);
+
+  if (kerberos_query->kerberos_prompt->reply->length < answer_length)
+    {
+      goa_kerberos_identity_inquiry_fail (self);
+    }
+  else
+    {
+      strncpy (kerberos_query->kerberos_prompt->reply->data,
+               answer, kerberos_query->kerberos_prompt->reply->length);
+      kerberos_query->kerberos_prompt->reply->length =
+        (unsigned int) strlen (kerberos_query->kerberos_prompt->reply->data);
 
-  goa_kerberos_identity_inquiry_mark_query_answered (self, kerberos_query);
+      goa_kerberos_identity_inquiry_mark_query_answered (self, kerberos_query);
+    }
 }
 
 static void
@@ -359,6 +389,7 @@ identity_inquiry_interface_init (GoaIdentityInquiryInterface *interface)
   interface->get_name = goa_kerberos_identity_inquiry_get_name;
   interface->get_banner = goa_kerberos_identity_inquiry_get_banner;
   interface->is_complete = goa_kerberos_identity_inquiry_is_complete;
+  interface->is_failed = goa_kerberos_identity_inquiry_is_failed;
   interface->answer_query = goa_kerberos_identity_inquiry_answer_query;
   interface->iter_init = goa_kerberos_identity_inquiry_iter_init;
   interface->iter_next = goa_kerberos_identity_inquiry_iter_next;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]