gsasl-commit
[Top][All Lists]
Advanced

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

[SCM] GNU gsasl branch, master, updated. gsasl-1-4-1-84-ga7825de


From: Simon Josefsson
Subject: [SCM] GNU gsasl branch, master, updated. gsasl-1-4-1-84-ga7825de
Date: Mon, 29 Mar 2010 22:17:15 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gsasl".

http://git.savannah.gnu.org/cgit/gsasl.git/commit/?id=a7825de9b86a28f27d53046d08ec64be31b77b62

The branch, master has been updated
       via  a7825de9b86a28f27d53046d08ec64be31b77b62 (commit)
       via  47ff497fafcce6eaceb984b522a9949ed61a69c3 (commit)
       via  cc7420c20eb1926e60454f19f85f52369aac1dc9 (commit)
       via  49e89f2beb1539fa148c85da185f1ccac29390aa (commit)
       via  d183ec50cf2357b24ac87838556dedfb3da60423 (commit)
       via  cca6e05400c172ba3a6e2d8c74f8f5cdcf49cedd (commit)
       via  95388a3e13f6a7ee7e8332c5d8a6c0601cddf70b (commit)
       via  a4ed5c3e6b95d780a5a6bd5d1c4dfdcc225dd54b (commit)
       via  16860ed2801b406dfe48b269ce34922f8bc2dc70 (commit)
       via  4f16fbcef5d0e3e7e17ac1bc097e9b732ab6e1ce (commit)
       via  45e9a2f4ee40a4621273061dc673a673ec6ff839 (commit)
       via  ba7a65a22c361d2480d5e270a0418127007b6db9 (commit)
       via  68f50cf9bc968a49c431de414531694b8fad7b49 (commit)
       via  c8fae990dddac47b5ad95d41b299b99bb8df6d64 (commit)
       via  9b56a8b1e65c990370bd235a2eeccd82ee677bab (commit)
       via  d43c264a510c0d4ab29ef306a59bf529d0b73882 (commit)
       via  801ac9d7911407265c7320d9afe838ebc692bbdd (commit)
      from  1610bba5a367d39ce4c379da1011acef854bb20a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a7825de9b86a28f27d53046d08ec64be31b77b62
Author: Simon Josefsson <address@hidden>
Date:   Tue Mar 30 00:12:04 2010 +0200

    Fix warnings.

commit 47ff497fafcce6eaceb984b522a9949ed61a69c3
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 23:52:06 2010 +0200

    Use gss_oid_equal when available.

commit cc7420c20eb1926e60454f19f85f52369aac1dc9
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 23:47:05 2010 +0200

    Also check for gss_oid_equal.

commit 49e89f2beb1539fa148c85da185f1ccac29390aa
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 23:44:40 2010 +0200

    Make gs2helper.h standalone.

commit d183ec50cf2357b24ac87838556dedfb3da60423
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 23:41:58 2010 +0200

    Update NEWS.

commit cca6e05400c172ba3a6e2d8c74f8f5cdcf49cedd
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 23:40:42 2010 +0200

    GS2: Cleanup code.

commit 95388a3e13f6a7ee7e8332c5d8a6c0601cddf70b
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 23:40:27 2010 +0200

    Add more GSS-API error codes.

commit a4ed5c3e6b95d780a5a6bd5d1c4dfdcc225dd54b
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 22:58:17 2010 +0200

    Use GSS capsulate functions to simplify code.

commit 16860ed2801b406dfe48b269ce34922f8bc2dc70
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 22:57:55 2010 +0200

    Fix error code values.

commit 4f16fbcef5d0e3e7e17ac1bc097e9b732ab6e1ce
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 22:45:51 2010 +0200

    Silence compiler warning.

commit 45e9a2f4ee40a4621273061dc673a673ec6ff839
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 22:35:56 2010 +0200

    Improve GS2 error codes.

commit ba7a65a22c361d2480d5e270a0418127007b6db9
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 22:21:04 2010 +0200

    gss_inquire_mech_for_saslname: Fix replacement and usage.

commit 68f50cf9bc968a49c431de414531694b8fad7b49
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 22:07:03 2010 +0200

    Improve GSS-API library feature checks.

commit c8fae990dddac47b5ad95d41b299b99bb8df6d64
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 21:51:00 2010 +0200

    Fix typo.

commit 9b56a8b1e65c990370bd235a2eeccd82ee677bab
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 21:39:13 2010 +0200

    Check ret_flags.

commit d43c264a510c0d4ab29ef306a59bf529d0b73882
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 21:33:27 2010 +0200

    Doc fix to avoid warning from GTK-DOC.

commit 801ac9d7911407265c7320d9afe838ebc692bbdd
Author: Simon Josefsson <address@hidden>
Date:   Mon Mar 29 21:29:14 2010 +0200

    Check for extended GSS-API interfaces.

-----------------------------------------------------------------------

Summary of changes:
 lib/NEWS            |   23 +++--
 lib/configure.ac    |   23 +++--
 lib/gs2/Makefile.am |    3 +-
 lib/gs2/client.c    |   99 ++++++-----------
 lib/gs2/gs2asn1.c   |   77 -------------
 lib/gs2/gs2asn1.h   |   32 -----
 lib/gs2/gs2helper.c |  314 +++++++++++++++++++++++++++++++++++++++++++++++++--
 lib/gs2/gs2helper.h |   42 +++++++-
 lib/gs2/server.c    |  101 ++++++++++-------
 lib/src/error.c     |   13 ++-
 lib/src/gsasl.h     |    7 +-
 lib/src/saslprep.c  |    4 +-
 tests/readnz.c      |    2 +-
 13 files changed, 485 insertions(+), 255 deletions(-)
 delete mode 100644 lib/gs2/gs2asn1.c
 delete mode 100644 lib/gs2/gs2asn1.h

diff --git a/lib/NEWS b/lib/NEWS
index 7d65455..6582793 100644
--- a/lib/NEWS
+++ b/lib/NEWS
@@ -5,18 +5,25 @@ See the end for copying conditions.
 * Version 1.5.0 (unreleased) [beta]
 
 ** GS2-KRB5: New mechanism GS2 with support for Kerberos V5.
-The supported GSS-API implementations are (like for GSS-API) GNU GSS,
-MIT Kerberos or Heimdal.  The GS2-KRB5-PLUS variant with TLS channel
-bindings are not supported.
-
-** Detecting GSS-API implementation simplified.
-MIT Kerberos and Heimdal are now treated the same, it appears as if
-they are compatible in modern releases.
+The supported GSS-API implementations are GNU GSS, MIT Kerberos or
+Heimdal.  The GS2-KRB5-PLUS variant with TLS channel bindings are not
+supported.
 
 ** DIGEST-MD5: The server code now returns GSASL_OK after the final token.
 
+** New error codes for GSS-API library errors (used by GS2).
+The error codes are GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR,
+GSASL_GSSAPI_DECAPSULATE_TOKEN_ERROR,
+GSASL_GSSAPI_INQUIRE_MECH_FOR_SASLNAME_ERROR,
+GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR, and
+GSASL_GSSAPI_RELEASE_OID_SET_ERROR.
+
 ** API and ABI modifications.
-No changes since last version.
+GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR: ADDED.
+GSASL_GSSAPI_DECAPSULATE_TOKEN_ERROR: ADDED.
+GSASL_GSSAPI_INQUIRE_MECH_FOR_SASLNAME_ERROR: ADDED.
+GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR: ADDED.
+GSASL_GSSAPI_RELEASE_OID_SET_ERROR: ADDED.
 
 * Version 1.4.4 (released 2010-03-25) [stable]
 
diff --git a/lib/configure.ac b/lib/configure.ac
index 6dee565..cb11d8f 100644
--- a/lib/configure.ac
+++ b/lib/configure.ac
@@ -249,17 +249,24 @@ fi
 AC_SUBST([GSS_CFLAGS])
 AC_SUBST([GSS_LIBS])
 
-if test "$gssapi_impl" = "mit" || \
-    test "$gssapi_impl" = "heimdal" || \
-    test "$gssapi_impl" = "mitheimdal"; then
+# Test for GSS-API library features.
+if test "$gssapi_impl" != "no"; then
   save_CPPFLAGS="$CPPFLAGS"
   save_LIBS="$LIBS"
   CPPFLAGS="$CPPFLAGS $GSS_CFLAGS"
-  LIBS="$LIBS $GSS_LIBS"
-  AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
-  if test "$ac_cv_header_gssapi_h$ac_cv_header_gssapi_gssapi_h" = "nono"; then
-    gssapi_impl=no
-    AC_MSG_WARN([Cannot find gssapi.h or gssapi/gssapi.h, disabling GSSAPI])
+  LIBS="$LIBS $LIBGSS $GSS_LIBS"
+  AC_CHECK_FUNCS([gss_encapsulate_token])
+  AC_CHECK_FUNCS([gss_decapsulate_token])
+  AC_CHECK_FUNCS([gss_oid_equal])
+  AC_CHECK_FUNCS([gss_inquire_mech_for_saslname])
+  if test "$gssapi_impl" = "mit" || \
+      test "$gssapi_impl" = "heimdal" || \
+      test "$gssapi_impl" = "mitheimdal"; then
+    AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
+    if test "$ac_cv_header_gssapi_h$ac_cv_header_gssapi_gssapi_h" = "nono"; 
then
+      gssapi_impl=no
+      AC_MSG_WARN([Cannot find gssapi.h or gssapi/gssapi.h, disabling GSSAPI])
+    fi
   fi
   CPPFLAGS="$save_CPPFLAGS"
   LIBS="$save_LIBS"
diff --git a/lib/gs2/Makefile.am b/lib/gs2/Makefile.am
index 329e0bd..4350ba6 100644
--- a/lib/gs2/Makefile.am
+++ b/lib/gs2/Makefile.am
@@ -27,8 +27,7 @@ EXTRA_DIST = README
 
 noinst_LTLIBRARIES = libgsasl-gs2.la
 libgsasl_gs2_la_SOURCES = gs2.h mechinfo.c \
-       gs2helper.h gs2helper.c \
-       gs2asn1.h gs2asn1.c
+       gs2helper.h gs2helper.c
 
 if CLIENT
 libgsasl_gs2_la_SOURCES += client.c
diff --git a/lib/gs2/client.c b/lib/gs2/client.c
index 2d93e15..b7b6498 100644
--- a/lib/gs2/client.c
+++ b/lib/gs2/client.c
@@ -33,16 +33,7 @@
 /* Get memcpy, strlen. */
 #include <string.h>
 
-#ifdef HAVE_LIBGSS
-# include <gss.h>
-#elif HAVE_GSSAPI_H
-# include <gssapi.h>
-#elif HAVE_GSSAPI_GSSAPI_H
-# include <gssapi/gssapi.h>
-#endif
-
 #include "gs2helper.h"
-#include "gs2asn1.h"
 
 struct _gsasl_gs2_client_state
 {
@@ -58,13 +49,19 @@ int
 _gsasl_gs2_client_start (Gsasl_session * sctx, void **mech_data)
 {
   _gsasl_gs2_client_state *state;
-  OM_uint32 maj_stat, min_stat;
-  gss_buffer_desc sasl_mech_name;
+  int res;
 
   state = (_gsasl_gs2_client_state *) malloc (sizeof (*state));
   if (state == NULL)
     return GSASL_MALLOC_ERROR;
 
+  res = gs2_get_oid (sctx, &state->mech_oid);
+  if (res != GSASL_OK)
+    {
+      free (state);
+      return res;
+    }
+
   state->context = GSS_C_NO_CONTEXT;
   state->service = GSS_C_NO_NAME;
   state->step = 0;
@@ -82,16 +79,6 @@ _gsasl_gs2_client_start (Gsasl_session * sctx, void 
**mech_data)
   state->cb.application_data.length = 0;
   state->cb.application_data.value = NULL;
 
-  sasl_mech_name.value = (void *) gsasl_mechanism_name (sctx);
-  if (!sasl_mech_name.value)
-    return GSASL_AUTHENTICATION_ERROR;
-  sasl_mech_name.length = strlen (sasl_mech_name.value);
-
-  maj_stat = gss_inquiry_mech_for_saslname (&min_stat, &sasl_mech_name,
-                                           &state->mech_oid);
-  if (GSS_ERROR (maj_stat))
-    return GSASL_AUTHENTICATION_ERROR;
-
   *mech_data = state;
 
   return GSASL_OK;
@@ -139,7 +126,7 @@ _gsasl_gs2_client_step (Gsasl_session * sctx,
   _gsasl_gs2_client_state *state = mech_data;
   gss_buffer_desc bufdesc, bufdesc2;
   gss_buffer_t buf = GSS_C_NO_BUFFER;
-  OM_uint32 maj_stat, min_stat;
+  OM_uint32 maj_stat, min_stat, ret_flags;
   gss_OID actual_mech_type;
   int res;
 
@@ -206,66 +193,48 @@ _gsasl_gs2_client_step (Gsasl_session * sctx,
                                       &state->context,
                                       state->service,
                                       state->mech_oid,
-                                      GSS_C_MUTUAL_FLAG |
-                                      GSS_C_INTEG_FLAG |
-                                      GSS_C_CONF_FLAG,
+                                      GSS_C_MUTUAL_FLAG,
                                       0,
                                       &state->cb,
                                       buf,
                                       &actual_mech_type,
                                       &bufdesc2,
-                                      NULL, /* ret_flags irrelevant */
+                                      &ret_flags,
                                       NULL);
       if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
        return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
 
-      if (state->mech_oid->length != actual_mech_type->length ||
-         memcmp (state->mech_oid->elements, actual_mech_type->elements,
-                 state->mech_oid->length) != 0)
+      /* The mutual_req_flag MUST be set.  Clients MUST check that the
+        corresponding ret_flag is set when the context is fully
+        established, else authentication MUST fail. */
+      if (maj_stat == GSS_S_COMPLETE && !(ret_flags & GSS_C_MUTUAL_FLAG))
+       return GSASL_AUTHENTICATION_ERROR;
+
+      if (!gss_oid_equal (state->mech_oid, actual_mech_type))
        return GSASL_AUTHENTICATION_ERROR;
 
       if (state->step == 0)
        {
-         const char *der = bufdesc2.value;
-         size_t derlen = bufdesc2.length;
-         size_t l, ll;
-
-         /* Strip off RFC 2743 section 3.1 token header. */
-
-         if (derlen-- == 0)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         if (*der++ != '\x60')
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         l = gs2_asn1_get_length_der (der, derlen, &ll);
-         if (l <= 0 || derlen <= ll)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         derlen -= ll;
-         der += ll;
-         if (derlen != l)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         if (derlen-- == 0)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         if (*der++ != '\x06')
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         l = gs2_asn1_get_length_der (der, derlen, &ll);
-         if (l <= 0 || derlen <= ll)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         derlen -= ll;
-         der += ll;
-         if (l != state->mech_oid->length)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         if (memcmp (state->mech_oid->elements, der, l) != 0)
-           return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
-         derlen -= l;
-         der += l;
-
-         *output_len = state->cb.application_data.length + derlen;
+         maj_stat = gss_decapsulate_token (&bufdesc2, state->mech_oid,
+                                           &bufdesc);
+         if (GSS_ERROR (maj_stat))
+           return GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR;
+
+         *output_len = state->cb.application_data.length + bufdesc.length;
          *output = malloc (*output_len);
          if (!*output)
-           return GSASL_MALLOC_ERROR;
+           {
+             gss_release_buffer (&min_stat, &bufdesc);
+             return GSASL_MALLOC_ERROR;
+           }
          memcpy (*output, state->cb.application_data.value,
                  state->cb.application_data.length);
-         memcpy (*output + state->cb.application_data.length, der, derlen);
+         memcpy (*output + state->cb.application_data.length,
+                 bufdesc.value, bufdesc.length);
+
+         maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
+         if (GSS_ERROR (maj_stat))
+           return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
        }
       else
        {
diff --git a/lib/gs2/gs2asn1.c b/lib/gs2/gs2asn1.c
deleted file mode 100644
index b889846..0000000
--- a/lib/gs2/gs2asn1.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* gs2asn1.h --- ASN.1 helper functions for GS2
- * Copyright (C) 2010  Simon Josefsson
- * Copyright (C) 2002, 2004, 2006, 2008, 2009, 2010 Free Software
- * Foundation, Inc.
- *
- * This file is part of GNU SASL Library.
- *
- * GNU SASL Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * GNU SASL Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GNU SASL Library; if not, write to the Free
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "gs2asn1.h"
-
-/* The following function is copied from GNU Libtasn1 (under
-   LGPLv2.1+) lib/decoding.c:asn1_get_length_der.  It is renamed for
-   namespace reasons, and uses better types and error codes. */
-
-ssize_t
-gs2_asn1_get_length_der (const char *der, size_t der_len, size_t *len)
-{
-  ssize_t ans;
-  size_t k, punt;
-
-  *len = 0;
-  if (der_len <= 0)
-    return -3;
-
-  if (!(der[0] & 128))
-    {
-      /* short form */
-      *len = 1;
-      return (unsigned char) der[0];
-    }
-  else
-    {
-      /* Long form */
-      k = (unsigned char) der[0] & 0x7F;
-      punt = 1;
-      if (k)
-       {                       /* definite length method */
-         ans = 0;
-         while (punt <= k && punt < der_len)
-           {
-             ssize_t last = ans;
-
-             ans = ans * 256 + (unsigned char) der[punt++];
-             if (ans < last)
-               /* we wrapped around, no bignum support... */
-               return -2;
-           }
-       }
-      else
-       {                       /* indefinite length method */
-         ans = -1;
-       }
-
-      *len = punt;
-      return ans;
-    }
-}
diff --git a/lib/gs2/gs2asn1.h b/lib/gs2/gs2asn1.h
deleted file mode 100644
index 8c77f0c..0000000
--- a/lib/gs2/gs2asn1.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* gs2asn1.h --- ASN.1 helper functions for GS2
- * Copyright (C) 2010  Simon Josefsson
- *
- * This file is part of GNU SASL Library.
- *
- * GNU SASL Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * GNU SASL Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GNU SASL Library; if not, write to the Free
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GS2_ASN1_H
-# define GS2_ASN1_H
-
-#include <stddef.h> /* size_t */
-#include <unistd.h> /* ssize_t */
-
-ssize_t
-gs2_asn1_get_length_der (const char *der, size_t der_len, size_t *len);
-
-#endif
diff --git a/lib/gs2/gs2helper.c b/lib/gs2/gs2helper.c
index b235772..861ff5f 100644
--- a/lib/gs2/gs2helper.c
+++ b/lib/gs2/gs2helper.c
@@ -1,4 +1,4 @@
-/* gs2helper.h --- GS2 helper functions for missing GSS-API interface.
+/* gs2helper.c --- GS2 helper functions common to client and server.
  * Copyright (C) 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
@@ -27,28 +27,65 @@
 /* Get strcmp. */
 #include <string.h>
 
-#ifdef HAVE_LIBGSS
-# include <gss.h>
-#elif HAVE_GSSAPI_H
-# include <gssapi.h>
-#elif HAVE_GSSAPI_GSSAPI_H
-# include <gssapi/gssapi.h>
-#endif
+/* Get malloc, free. */
+#include <stdlib.h>
 
 /* Get specification. */
 #include "gs2helper.h"
 
+/* Populate mech_oid with OID for the current SASL mechanism name.  A
+   bit silly given that we only support Kerberos V5 today, but will be
+   useful when that changes.  */
+int
+gs2_get_oid (Gsasl_session * sctx, gss_OID *mech_oid)
+{
+  gss_buffer_desc sasl_mech_name;
+  OM_uint32 maj_stat, min_stat;
+
+  sasl_mech_name.value = (void *) gsasl_mechanism_name (sctx);
+  if (!sasl_mech_name.value)
+    return GSASL_AUTHENTICATION_ERROR;
+  sasl_mech_name.length = strlen (sasl_mech_name.value);
+
+  maj_stat = gss_inquire_mech_for_saslname (&min_stat, &sasl_mech_name,
+                                           mech_oid);
+  if (GSS_ERROR (maj_stat))
+    return GSASL_GSSAPI_INQUIRE_MECH_FOR_SASLNAME_ERROR;
+
+  return GSASL_OK;
+}
+
+#ifndef HAVE_GSS_OID_EQUAL
+
+int
+gss_oid_equal (const gss_OID first_oid, const gss_OID second_oid)
+{
+  return first_oid && second_oid &&
+    first_oid->length == second_oid->length &&
+    memcmp (first_oid->elements, second_oid->elements,
+           second_oid->length) == 0;
+}
+
+#endif
+
+#ifndef HAVE_GSS_INQUIRE_MECH_FOR_SASLNAME
+
+/* Provide a dummy replacement function for GSS-API libraries that
+   lacks gss_inquire_mech_for_saslname.  This function only works for
+   Kerberos V5.  */
+
 OM_uint32
-gss_inquiry_mech_for_saslname (OM_uint32 *minor_status,
+gss_inquire_mech_for_saslname (OM_uint32 *minor_status,
                               const gss_buffer_t sasl_mech_name,
                               gss_OID *mech_type)
 {
-  static const gss_OID_desc krb5oid_static = {
-    9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
+  static gss_OID_desc krb5oid_static = {
+    9, (char *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
   };
 
   if (sasl_mech_name->value == NULL ||
-      strcmp (sasl_mech_name->value, "GS2-KRB5") != 0)
+      sasl_mech_name->length != 8 ||
+      memcmp (sasl_mech_name->value, "GS2-KRB5", 8) != 0)
     {
       if (minor_status)
        *minor_status = 0;
@@ -60,3 +97,256 @@ gss_inquiry_mech_for_saslname (OM_uint32 *minor_status,
 
   return GSS_S_COMPLETE;
 }
+
+#endif
+
+/*
+ * The functions _gss_asn1_length_der and _gss_asn1_get_length_der are
+ * borrowed from GNU Libtasn1, under LGPLv2.1+.
+ * Copyright (C) 2002 Fabio Fiorina.
+ * The remaining functions below are copied from GNU GSS but re-licensed
+ * to LGPLv2.1+.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010  Simon 
Josefsson
+ */
+
+#ifndef HAVE_GSS_ENCAPSULATE_TOKEN
+
+static void
+_gss_asn1_length_der (size_t len, unsigned char *ans, size_t * ans_len)
+{
+  size_t k;
+  unsigned char temp[sizeof (len)];
+
+  if (len < 128)
+    {
+      if (ans != NULL)
+       ans[0] = (unsigned char) len;
+      *ans_len = 1;
+    }
+  else
+    {
+      k = 0;
+
+      while (len)
+       {
+         temp[k++] = len & 0xFF;
+         len = len >> 8;
+       }
+
+      *ans_len = k + 1;
+
+      if (ans != NULL)
+       {
+         ans[0] = ((unsigned char) k & 0x7F) + 128;
+         while (k--)
+           ans[*ans_len - 1 - k] = temp[k];
+       }
+    }
+}
+
+static OM_uint32
+_gss_encapsulate_token_prefix (const char *prefix, size_t prefixlen,
+                              const char *in, size_t inlen,
+                              const char *oid, OM_uint32 oidlen,
+                              void **out, size_t * outlen)
+{
+  size_t oidlenlen;
+  size_t asn1len, asn1lenlen;
+  unsigned char *p;
+
+  if (prefix == NULL)
+    prefixlen = 0;
+
+  _gss_asn1_length_der (oidlen, NULL, &oidlenlen);
+  asn1len = 1 + oidlenlen + oidlen + prefixlen + inlen;
+  _gss_asn1_length_der (asn1len, NULL, &asn1lenlen);
+
+  *outlen = 1 + asn1lenlen + asn1len;
+  p = *out = malloc (*outlen);
+  if (!p)
+    return -1;
+
+  *p++ = '\x60';
+  _gss_asn1_length_der (asn1len, p, &asn1lenlen);
+  p += asn1lenlen;
+  *p++ = '\x06';
+  _gss_asn1_length_der (oidlen, p, &oidlenlen);
+  p += oidlenlen;
+  memcpy (p, oid, oidlen);
+  p += oidlen;
+  if (prefixlen > 0)
+    {
+      memcpy (p, prefix, prefixlen);
+      p += prefixlen;
+    }
+  memcpy (p, in, inlen);
+
+  return 0;
+}
+
+extern OM_uint32
+gss_encapsulate_token (const gss_buffer_t input_token,
+                      const gss_OID token_oid,
+                      gss_buffer_t output_token)
+{
+  int rc;
+
+  if (!input_token)
+    return GSS_S_CALL_INACCESSIBLE_READ;
+  if (!token_oid)
+    return GSS_S_CALL_INACCESSIBLE_READ;
+  if (!output_token)
+    return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+  rc = _gss_encapsulate_token_prefix (NULL, 0,
+                                     input_token->value,
+                                     input_token->length,
+                                     token_oid->elements,
+                                     token_oid->length,
+                                     &output_token->value,
+                                     &output_token->length);
+  if (rc != 0)
+    return GSS_S_FAILURE;
+
+  return GSS_S_COMPLETE;
+}
+
+#endif /* HAVE_GSS_ENCAPSULATE_TOKEN */
+
+#ifndef HAVE_GSS_ENCAPSULATE_TOKEN
+
+static size_t
+_gss_asn1_get_length_der (const char *der, size_t der_len, size_t *len)
+{
+  size_t ans;
+  size_t k, punt;
+
+  *len = 0;
+  if (der_len <= 0)
+    return 0;
+
+  if (!(der[0] & 128))
+    {
+      /* short form */
+      *len = 1;
+      return (unsigned char) der[0];
+    }
+  else
+    {
+      /* Long form */
+      k = (unsigned char) der[0] & 0x7F;
+      punt = 1;
+      if (k)
+       {                       /* definite length method */
+         ans = 0;
+         while (punt <= k && punt < der_len)
+           {
+             size_t last = ans;
+
+             ans = ans * 256 + (unsigned char) der[punt++];
+             if (ans < last)
+               /* we wrapped around, no bignum support... */
+               return -2;
+           }
+       }
+      else
+       {                       /* indefinite length method */
+         ans = -1;
+       }
+
+      *len = punt;
+      return ans;
+    }
+}
+
+static int
+_gss_decapsulate_token (const char *in, size_t inlen,
+                       char **oid, size_t * oidlen,
+                       char **out, size_t * outlen)
+{
+  size_t i;
+  size_t asn1lenlen;
+
+  if (inlen-- == 0)
+    return -1;
+  if (*in++ != '\x60')
+    return -1;
+
+  i = inlen;
+  asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
+  if (inlen < i)
+    return -1;
+
+  inlen -= i;
+  in += i;
+
+  if (inlen != asn1lenlen)
+    return -1;
+
+  if (inlen-- == 0)
+    return -1;
+  if (*in++ != '\x06')
+    return -1;
+
+  i = inlen;
+  asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
+  if (inlen < i)
+    return -1;
+
+  inlen -= i;
+  in += i;
+
+  if (inlen < asn1lenlen)
+    return -1;
+
+  *oidlen = asn1lenlen;
+  *oid = (char *) in;
+
+  inlen -= asn1lenlen;
+  in += asn1lenlen;
+
+  *outlen = inlen;
+  *out = (char *) in;
+
+  return 0;
+}
+
+OM_uint32
+gss_decapsulate_token (const gss_buffer_t input_token,
+                      const gss_OID token_oid,
+                      gss_buffer_t output_token)
+{
+  gss_OID_desc tmpoid;
+  char *oid = NULL, *out = NULL;
+  size_t oidlen = 0, outlen = 0;
+
+  if (!input_token)
+    return GSS_S_CALL_INACCESSIBLE_READ;
+  if (!token_oid)
+    return GSS_S_CALL_INACCESSIBLE_READ;
+  if (!output_token)
+    return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+  if (_gss_decapsulate_token ((char *) input_token->value,
+                             input_token->length,
+                             &oid, &oidlen,
+                             &out, &outlen) != 0)
+    return GSS_S_DEFECTIVE_TOKEN;
+
+  tmpoid.length = oidlen;
+  tmpoid.elements = oid;
+
+  if (!gss_oid_equal (token_oid, &tmpoid))
+    return GSS_S_DEFECTIVE_TOKEN;
+
+  output_token->length = outlen;
+  output_token->value = malloc (outlen);
+  if (!output_token->value)
+    return GSS_S_FAILURE;
+
+  memcpy (output_token->value, out, outlen);
+
+  return GSS_S_COMPLETE;
+}
+
+#endif
diff --git a/lib/gs2/gs2helper.h b/lib/gs2/gs2helper.h
index ec0b604..66b84c2 100644
--- a/lib/gs2/gs2helper.h
+++ b/lib/gs2/gs2helper.h
@@ -1,4 +1,4 @@
-/* gs2helper.h --- GS2 helper functions for missing GSS-API interface.
+/* gs2helper.h --- GS2 helper functions common to client and server.
  * Copyright (C) 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
@@ -23,9 +23,45 @@
 #ifndef GS2_HELPER_H
 # define GS2_HELPER_H
 
-extern OM_uint32
-gss_inquiry_mech_for_saslname (OM_uint32 *minor_status,
+/* Get GSS-API functions. */
+#ifdef HAVE_LIBGSS
+# include <gss.h>
+#elif HAVE_GSSAPI_H
+# include <gssapi.h>
+#elif HAVE_GSSAPI_GSSAPI_H
+# include <gssapi/gssapi.h>
+#endif
+
+/* Get gsasl functions and types. */
+#include <gsasl.h>
+
+extern int
+gs2_get_oid (Gsasl_session * sctx, gss_OID *mech_oid);
+
+#ifndef HAVE_GSS_OID_EQUAL
+extern int
+gss_oid_equal (const gss_OID first_oid, const gss_OID second_oid);
+#endif /* HAVE_GSS_OID_EQUAL */
+
+#ifndef HAVE_GSS_INQUIRE_MECH_FOR_SASLNAME
+OM_uint32
+gss_inquire_mech_for_saslname (OM_uint32 *minor_status,
                               const gss_buffer_t sasl_mech_name,
                               gss_OID *mech_type);
+#endif /* HAVE_GSS_INQUIRE_MECH_FOR_SASLNAME */
+
+#ifndef HAVE_GSS_ENCAPSULATE_TOKEN
+extern OM_uint32
+gss_encapsulate_token (const gss_buffer_t input_token,
+                      const gss_OID token_oid,
+                      gss_buffer_t output_token);
+#endif /* HAVE_GSS_ENCAPSULATE_TOKEN */
 
+#ifndef HAVE_GSS_DECAPSULATE_TOKEN
+OM_uint32
+gss_decapsulate_token (const gss_buffer_t input_token,
+                      const gss_OID token_oid,
+                      gss_buffer_t output_token);
 #endif
+
+#endif /* GS2_HELPER_H */
diff --git a/lib/gs2/server.c b/lib/gs2/server.c
index 80795e4..7b00d78 100644
--- a/lib/gs2/server.c
+++ b/lib/gs2/server.c
@@ -33,14 +33,6 @@
 /* Get memcpy, strlen. */
 #include <string.h>
 
-#ifdef HAVE_LIBGSS
-# include <gss.h>
-#elif HAVE_GSSAPI_H
-# include <gssapi.h>
-#elif HAVE_GSSAPI_GSSAPI_H
-# include <gssapi/gssapi.h>
-#endif
-
 #include "gs2helper.h"
 
 struct _Gsasl_gs2_server_state
@@ -54,15 +46,18 @@ struct _Gsasl_gs2_server_state
 };
 typedef struct _Gsasl_gs2_server_state _Gsasl_gs2_server_state;
 
-int
-_gsasl_gs2_server_start (Gsasl_session * sctx, void **mech_data)
+/* Populate state->cred with credential to use for connection. */
+static int
+gs2_get_cred  (Gsasl_session * sctx, _Gsasl_gs2_server_state * state)
 {
-  _Gsasl_gs2_server_state *state;
   OM_uint32 maj_stat, min_stat;
-  gss_name_t server;
   gss_buffer_desc bufdesc;
   const char *service;
   const char *hostname;
+  gss_name_t server;
+  gss_OID_set_desc oid_set;
+  gss_OID_set actual_mechs;
+  int present;
 
   service = gsasl_property_get (sctx, GSASL_SERVICE);
   if (!service)
@@ -77,46 +72,61 @@ _gsasl_gs2_server_start (Gsasl_session * sctx, void 
**mech_data)
   if (bufdesc.length <= 0 || bufdesc.value == NULL)
     return GSASL_MALLOC_ERROR;
 
-  state = (_Gsasl_gs2_server_state *) malloc (sizeof (*state));
-  if (state == NULL)
-    {
-      free (bufdesc.value);
-      return GSASL_MALLOC_ERROR;
-    }
-
-  maj_stat = gss_import_name (&min_stat, &bufdesc, GSS_C_NT_HOSTBASED_SERVICE,
+  maj_stat = gss_import_name (&min_stat, &bufdesc,
+                             GSS_C_NT_HOSTBASED_SERVICE,
                              &server);
   free (bufdesc.value);
   if (GSS_ERROR (maj_stat))
-    {
-      free (state);
-      return GSASL_GSSAPI_IMPORT_NAME_ERROR;
-    }
+    return GSASL_GSSAPI_IMPORT_NAME_ERROR;
+
+  oid_set.count = 1;
+  oid_set.elements = state->mech_oid;
 
   maj_stat = gss_acquire_cred (&min_stat, server, 0,
-                              GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
-                              &state->cred, NULL, NULL);
+                              &oid_set, GSS_C_ACCEPT,
+                              &state->cred, &actual_mechs, NULL);
   gss_release_name (&min_stat, &server);
+  if (GSS_ERROR (maj_stat))
+    return GSASL_GSSAPI_ACQUIRE_CRED_ERROR;
 
+  maj_stat = gss_test_oid_set_member (&min_stat, state->mech_oid,
+                                     actual_mechs, &present);
   if (GSS_ERROR (maj_stat))
     {
-      free (state);
-      return GSASL_GSSAPI_ACQUIRE_CRED_ERROR;
+      gss_release_oid_set (&min_stat, &actual_mechs);
+      return GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR;
     }
 
-  {
-    gss_buffer_desc sasl_mech_name;
+  maj_stat = gss_release_oid_set (&min_stat, &actual_mechs);
+  if (GSS_ERROR (maj_stat))
+    return GSASL_GSSAPI_RELEASE_OID_SET_ERROR;
 
-    sasl_mech_name.value = (void *) gsasl_mechanism_name (sctx);
-    if (!sasl_mech_name.value)
-      return GSASL_AUTHENTICATION_ERROR;
-    sasl_mech_name.length = strlen (sasl_mech_name.value);
+  return GSASL_OK;
+}
+
+int
+_gsasl_gs2_server_start (Gsasl_session * sctx, void **mech_data)
+{
+  _Gsasl_gs2_server_state *state;
+  int res;
+
+  state = (_Gsasl_gs2_server_state *) malloc (sizeof (*state));
+  if (state == NULL)
+    return GSASL_MALLOC_ERROR;
+
+  res = gs2_get_oid (sctx, &state->mech_oid);
+  if (res != GSASL_OK)
+    {
+      free (state);
+      return res;
+    }
 
-    maj_stat = gss_inquiry_mech_for_saslname (&min_stat, &sasl_mech_name,
-                                             &state->mech_oid);
-    if (GSS_ERROR (maj_stat))
-      return GSASL_AUTHENTICATION_ERROR;
-  }
+  res = gs2_get_cred (sctx, state);
+  if (res != GSASL_OK)
+    {
+      free (state);
+      return res;
+    }
 
   state->step = 0;
   state->context = GSS_C_NO_CONTEXT;
@@ -244,7 +254,10 @@ _gsasl_gs2_server_step (Gsasl_session * sctx,
          return res;
 
        if (authzid)
-         gsasl_property_set (sctx, GSASL_AUTHZID, authzid);
+         {
+           gsasl_property_set (sctx, GSASL_AUTHZID, authzid);
+           free (authzid);
+         }
 
        state->cb.application_data.value = input;
        state->cb.application_data.length = headerlen;
@@ -252,9 +265,11 @@ _gsasl_gs2_server_step (Gsasl_session * sctx,
        bufdesc2.value = input + headerlen;
        bufdesc2.length = input_len - headerlen;
 
-       res = gss_encapsulate_token (&bufdesc2, state->mech_oid, &bufdesc1);
-       if (res != 1)
-         return res;
+       maj_stat = gss_encapsulate_token (&bufdesc2, state->mech_oid,
+                                         &bufdesc1);
+       if (GSS_ERROR (maj_stat))
+         return GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR;
+
        free_bufdesc1 = 1;
       }
       state->step++;
diff --git a/lib/src/error.c b/lib/src/error.c
index 712899d..22d3a21 100644
--- a/lib/src/error.c
+++ b/lib/src/error.c
@@ -185,7 +185,18 @@ static struct {
   ERR (GSASL_NO_SERVICE,
        N_("Authentication failed because the service name was not provided.")),
   ERR (GSASL_NO_HOSTNAME,
-       N_("Authentication failed because the host name was not provided."))
+       N_("Authentication failed because the host name was not provided.")),
+  ERR (GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR,
+       N_("GSSAPI error encapsulating token.")),
+  ERR (GSASL_GSSAPI_DECAPSULATE_TOKEN_ERROR,
+       N_("GSSAPI error decapsulating token.")),
+  ERR (GSASL_GSSAPI_INQUIRE_MECH_FOR_SASLNAME_ERROR,
+       N_("GSSAPI error getting OID for SASL mechanism name.")),
+  ERR (GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR,
+       N_("GSSAPI error testing for OID in OID set.")),
+  ERR (GSASL_GSSAPI_RELEASE_OID_SET_ERROR,
+       N_("GSSAPI error releasing OID set."))
+
 };
 
 /**
diff --git a/lib/src/gsasl.h b/lib/src/gsasl.h
index 4da3ef9..65c0701 100644
--- a/lib/src/gsasl.h
+++ b/lib/src/gsasl.h
@@ -148,7 +148,12 @@ extern "C"
     GSASL_KERBEROS_V5_INTERNAL_ERROR = 47,
     GSASL_SHISHI_ERROR = GSASL_KERBEROS_V5_INTERNAL_ERROR,
     GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE = 48,
-    GSASL_SECURID_SERVER_NEED_NEW_PIN = 49
+    GSASL_SECURID_SERVER_NEED_NEW_PIN = 49,
+    GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR = 60,
+    GSASL_GSSAPI_DECAPSULATE_TOKEN_ERROR = 61,
+    GSASL_GSSAPI_INQUIRE_MECH_FOR_SASLNAME_ERROR = 62,
+    GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR = 63,
+    GSASL_GSSAPI_RELEASE_OID_SET_ERROR = 64
   } Gsasl_rc;
 
   /* Quality of Protection types, used by DIGEST-MD5 */
diff --git a/lib/src/saslprep.c b/lib/src/saslprep.c
index 93055b3..f5e178d 100644
--- a/lib/src/saslprep.c
+++ b/lib/src/saslprep.c
@@ -1,5 +1,5 @@
 /* saslprep.c --- Internationalized SASL string processing.
- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009  Simon 
Josefsson
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010  Simon 
Josefsson
  *
  * This file is part of GNU SASL Library.
  *
@@ -30,7 +30,7 @@
 #endif
 
 /**
- * gsasl_saslprep - prepare internationalized string
+ * gsasl_saslprep:
  * @in: a UTF-8 encoded string.
  * @flags: any SASLprep flag, e.g., %GSASL_ALLOW_UNASSIGNED.
  * @out: on exit, contains newly allocated output string.
diff --git a/tests/readnz.c b/tests/readnz.c
index c3f6de1..02eaecf 100644
--- a/tests/readnz.c
+++ b/tests/readnz.c
@@ -36,7 +36,7 @@ doit2 (bool server_p)
   Gsasl *ctx = NULL;
   Gsasl_session *session = NULL;
   char *mechs;
-  char *mech, *ptrptr;
+  char *mech, *ptrptr = NULL;
   char *s1;
   size_t s1len;
   int res;


hooks/post-receive
-- 
GNU gsasl




reply via email to

[Prev in Thread] Current Thread [Next in Thread]