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-5-2-8-g53b1c36


From: Simon Josefsson
Subject: [SCM] GNU gsasl branch, master, updated. gsasl-1-5-2-8-g53b1c36
Date: Sat, 13 Nov 2010 23:42: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=53b1c367dea600eb54b213a7babd02f7e17b6788

The branch, master has been updated
       via  53b1c367dea600eb54b213a7babd02f7e17b6788 (commit)
       via  b4f6cdd48c4afcc61c88ee6b42c1146cba638ebf (commit)
       via  243b1a43b3a6ca757cbe22441261c667fb74821e (commit)
       via  58e617fd23fce8cbb2131be5ef60e20c8301fcbc (commit)
       via  fe30677c955198550aaac721a64efe64cbf83025 (commit)
      from  20291af559757a0290c9d9c84aa18b54d6205ec3 (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 53b1c367dea600eb54b213a7babd02f7e17b6788
Author: Simon Josefsson <address@hidden>
Date:   Sun Nov 14 00:39:25 2010 +0100

    Generated.

commit b4f6cdd48c4afcc61c88ee6b42c1146cba638ebf
Author: Simon Josefsson <address@hidden>
Date:   Sun Nov 14 00:35:30 2010 +0100

    Generated.

commit 243b1a43b3a6ca757cbe22441261c667fb74821e
Author: Simon Josefsson <address@hidden>
Date:   Sun Nov 14 00:31:45 2010 +0100

    Version 1.5.3.

commit 58e617fd23fce8cbb2131be5ef60e20c8301fcbc
Author: Simon Josefsson <address@hidden>
Date:   Sun Nov 14 00:04:49 2010 +0100

    Support SCRAM-SHA-1-PLUS.  Add GSASL_CB_TLS_UNIQUE.  Use GnuTLS for 
tls-unique CB.

commit fe30677c955198550aaac721a64efe64cbf83025
Author: Simon Josefsson <address@hidden>
Date:   Sat Nov 13 20:01:05 2010 +0100

    Ignore more.

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

Summary of changes:
 .gitignore                     |   24 +++++++++++
 ChangeLog                      |   45 ++++++++++++++++++++
 NEWS                           |   12 +++++-
 README                         |    6 +-
 configure.ac                   |    7 +++
 doc/gsasl.texi                 |   44 ++++++++++++++++----
 doc/reference/gsasl-docs.sgml  |    4 +-
 lib/ChangeLog                  |   45 ++++++++++++++++++++
 lib/NEWS                       |   13 +++++-
 lib/README                     |    4 +-
 lib/scram/client.c             |   87 ++++++++++++++++++++++++++++++++++------
 lib/scram/mechinfo.c           |   39 +++++++++++++++++-
 lib/scram/parser.c             |   25 ++++++++++-
 lib/scram/printer.c            |    4 +-
 lib/scram/scram.h              |   10 ++++-
 lib/scram/server.c             |   80 +++++++++++++++++++++++++++++++-----
 lib/scram/validate.c           |   14 +++++-
 lib/src/error.c                |    5 +-
 lib/src/gsasl.h                |    4 ++
 lib/src/init.c                 |    6 ++-
 lib/src/internal.h             |    3 +-
 lib/src/property.c             |    6 ++-
 lib/src/xfinish.c              |    1 +
 src/callbacks.c                |   13 +++++-
 src/gsasl.c                    |   20 +++++++++
 src/internal.h                 |    1 +
 tests/Makefile.am              |    2 +-
 tests/scram.c                  |    3 +
 tests/{scram.c => scramplus.c} |   74 +++++++++++----------------------
 29 files changed, 492 insertions(+), 109 deletions(-)
 copy tests/{scram.c => scramplus.c} (86%)

diff --git a/.gitignore b/.gitignore
index 82ec4dc..9c984c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,7 @@ doc/gsasl.fns
 doc/gsasl.html
 doc/gsasl.info
 doc/gsasl.info-1
+doc/gsasl.info-2
 doc/gsasl.ky
 doc/gsasl.log
 doc/gsasl.pdf
@@ -48,6 +49,7 @@ doc/reference/Makefile
 doc/reference/Makefile.in
 doc/reference/gsasl-decl-list.txt
 doc/reference/gsasl-decl.txt
+doc/reference/gsasl-decl.txt.bak
 doc/reference/gsasl-overrides.txt
 doc/reference/gsasl-sections.txt
 doc/reference/gsasl-undeclared.txt
@@ -62,6 +64,8 @@ doc/reference/gsasl.types
 doc/reference/html-build.stamp
 doc/reference/html.stamp
 doc/reference/html/
+doc/reference/pdf-build.stamp
+doc/reference/pdf.stamp
 doc/reference/scan-build.stamp
 doc/reference/sgml-build.stamp
 doc/reference/sgml.stamp
@@ -115,6 +119,7 @@ gl/iconv_open-solaris.h
 gl/libgl.la
 gl/localcharset.lo
 gl/localcharset.o
+gl/netdb.h
 gl/printf-args.lo
 gl/printf-args.o
 gl/printf-parse.lo
@@ -222,6 +227,8 @@ gltests/test-perror.o
 gltests/test-poll
 gltests/test-poll.o
 gltests/test-quotearg
+gltests/test-quotearg-simple
+gltests/test-quotearg-simple.o
 gltests/test-quotearg.o
 gltests/test-select
 gltests/test-select-fd
@@ -265,6 +272,8 @@ gltests/test-sys_stat
 gltests/test-sys_stat.o
 gltests/test-sys_time
 gltests/test-sys_time.o
+gltests/test-sys_wait
+gltests/test-sys_wait.o
 gltests/test-time
 gltests/test-time.o
 gltests/test-unistd
@@ -273,6 +282,9 @@ gltests/test-unsetenv
 gltests/test-unsetenv.o
 gltests/test-vasnprintf
 gltests/test-vasnprintf.o
+gltests/test-vasprintf
+gltests/test-vasprintf.o
+gltests/test-verify
 gltests/test-version-etc
 gltests/test-version-etc.o
 gltests/test-wchar
@@ -383,6 +395,8 @@ lib/gl/asnprintf.o
 lib/gl/base64.lo
 lib/gl/base64.o
 lib/gl/c++defs.h
+lib/gl/c-ctype.lo
+lib/gl/c-ctype.o
 lib/gl/gc-libgcrypt.lo
 lib/gl/gc-libgcrypt.o
 lib/gl/gc-pbkdf2-sha1.lo
@@ -397,6 +411,7 @@ lib/gl/printf-parse.o
 lib/gl/stdio.h
 lib/gl/stdlib.h
 lib/gl/string.h
+lib/gl/sys/
 lib/gl/unistd.h
 lib/gl/vasnprintf.lo
 lib/gl/vasnprintf.o
@@ -413,6 +428,8 @@ lib/gltests/test-alloca-opt
 lib/gltests/test-alloca-opt.o
 lib/gltests/test-base64
 lib/gltests/test-base64.o
+lib/gltests/test-c-ctype
+lib/gltests/test-c-ctype.o
 lib/gltests/test-errno
 lib/gltests/test-errno.o
 lib/gltests/test-gc
@@ -447,14 +464,19 @@ lib/gltests/test-stdlib
 lib/gltests/test-stdlib.o
 lib/gltests/test-string
 lib/gltests/test-string.o
+lib/gltests/test-strnlen
+lib/gltests/test-strnlen.o
 lib/gltests/test-strverscmp
 lib/gltests/test-strverscmp.o
+lib/gltests/test-sys_wait
+lib/gltests/test-sys_wait.o
 lib/gltests/test-unistd
 lib/gltests/test-unistd.o
 lib/gltests/test-vasnprintf
 lib/gltests/test-vasnprintf.o
 lib/gltests/test-vasprintf
 lib/gltests/test-vasprintf.o
+lib/gltests/test-verify
 lib/gltests/test-wchar
 lib/gltests/test-wchar.o
 lib/gltests/warn-on-use.h
@@ -762,6 +784,8 @@ tests/readnz
 tests/readnz.o
 tests/scram
 tests/scram.o
+tests/scramplus
+tests/scramplus.o
 tests/simple
 tests/simple.o
 tests/suggest
diff --git a/ChangeLog b/ChangeLog
index 767b8ee..9eadfd4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2010-11-14  Simon Josefsson <address@hidden>
+
+       * lib/ChangeLog: Generated.
+
+2010-11-14  Simon Josefsson <address@hidden>
+
+       * NEWS, lib/NEWS: Version 1.5.3.
+
+2010-11-14  Simon Josefsson <address@hidden>
+
+       * .gitignore, NEWS, README, configure.ac, doc/gsasl.texi,
+       doc/reference/gsasl-docs.sgml, lib/NEWS, lib/README,
+       lib/scram/client.c, lib/scram/mechinfo.c, lib/scram/parser.c,
+       lib/scram/printer.c, lib/scram/scram.h, lib/scram/server.c,
+       lib/scram/validate.c, lib/src/error.c, lib/src/gsasl.h,
+       lib/src/init.c, lib/src/internal.h, lib/src/property.c,
+       lib/src/xfinish.c, src/callbacks.c, src/gsasl.c, src/internal.h,
+       tests/Makefile.am, tests/scram.c, tests/scramplus.c: Support
+       SCRAM-SHA-1-PLUS.  Add GSASL_CB_TLS_UNIQUE.  Use GnuTLS for
+       tls-unique CB.
+
+2010-11-13  Simon Josefsson <address@hidden>
+
+       * .gitignore: Ignore more.
+
+2010-11-13  Simon Josefsson <address@hidden>
+
+       * src/gsasl.c, tests/cram-md5.c, tests/digest-md5.c,
+       tests/errors.c, tests/external.c, tests/old-cram-md5.c,
+       tests/old-digest-md5.c, tests/old-md5file.c, tests/old-simple.c,
+       tests/scram.c, tests/simple.c, tests/utils.c: Fix compiler warnings.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * NEWS, configure.ac, lib/NEWS, lib/configure.ac, lib/src/gsasl.h: 
+       Bump versions.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * doc/gsasl.texi: Fix typo.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * ChangeLog: Generated.
+
 2010-09-27  Simon Josefsson <address@hidden>
 
        * lib/ChangeLog: Generated.
diff --git a/NEWS b/NEWS
index 520e746..5e41244 100644
--- a/NEWS
+++ b/NEWS
@@ -6,13 +6,21 @@ Note that changes to the GNU SASL Library is documented in 
lib/NEWS.
 This file track changes to the remaining, non-library, parts of GNU
 SASL.  That include the manual, the command line tool, and self tests.
 
-* Version 1.5.3 (unreleased) [beta]
+* Version 1.5.3 (released 2010-11-14) [beta]
+
+** gsasl: Support for TLS channel bindings.
+Requires GnuTLS 2.11.4 or later for the gnutls_session_channel_binding
+function.  Used by the SCRAM-SHA-1-PLUS mechanism.
+
+** doc: Mention new property GSASL_CB_TLS_UNIQUE and SCRAM-SHA-1-PLUS.
+
+** tests: Added self-tests for SCRAM-SHA-1-PLUS.
 
 * Version 1.5.2 (released 2010-09-27) [beta]
 
 ** gsasl: Avoid fixed size buffers.
 This caused problems on Windows where the BUFSIZ was too small for
-some line lengths with GS2-KRb5.
+some line lengths with GS2-KRB5.
 
 ** tests: Fix error strings to be more unique.
 
diff --git a/README b/README
index 4279d2e..f6a1e97 100644
--- a/README
+++ b/README
@@ -35,11 +35,11 @@ Currently there is some support for the following 
mechanisms:
   - PLAIN (RFC 2595)
   - SECURID (RFC 2808)
   - DIGEST-MD5 (RFC 2831)
+  - SCRAM-SHA-1 and SCRAM-SHA-1-PLUS (RFC 5802)
+  - GS2-KRB5 (RFC 5801, no CB, requires GSS, Heimdal, or MIT Kerberos)
   - LOGIN (non-standard)
   - NTLM (non-standard, client only, requires Libntlm)
   - KERBEROS_V5 (experimental, requires Shishi)
-  - SCRAM (no channel bindings)
-  - GS2-KRB5 (no channel bindings, requires GSS, Heimdal or MIT Kerberos)
 
 The library should be portable to all C89 platforms.  The command-line
 application currently requires POSIX for network communication.
@@ -47,7 +47,7 @@ application currently requires POSIX for network 
communication.
 Things left to do below.  If you like to start working on anything,
 please let me know so work duplication can be avoided.
 
-  * Support channel bindings in SCRAM/GS2.
+  * Support channel bindings in GS2.
   + Authentication infrastructure implementing the callbacks for
     PAM, Kerberos, SQL, etc.  Separate project?  GNU Mailutils has
     some starting points for this, but the API is inflexible.
diff --git a/configure.ac b/configure.ac
index f75274f..09f71eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,13 @@ fi
 AC_MSG_CHECKING([if STARTTLS support via GnuTLS should be built])
 AC_MSG_RESULT($gnutls)
 
+if test "$ac_cv_libgnutls" = yes; then
+  save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBGNUTLS"
+  AC_CHECK_FUNCS([gnutls_session_channel_binding])
+  LIBS="$save_LIBS"
+fi
+
 # Check for gtk-doc.
 GTK_DOC_CHECK(1.1)
 
diff --git a/doc/gsasl.texi b/doc/gsasl.texi
index db3d3fc..d87e925 100644
--- a/doc/gsasl.texi
+++ b/doc/gsasl.texi
@@ -172,7 +172,7 @@ manual.  The library includes support for the framework 
(with
 authentication functions and application data privacy and integrity
 functions) and at least partial support for the ANONYMOUS, CRAM-MD5,
 DIGEST-MD5, EXTERNAL, GS2-KRB5, GSSAPI, LOGIN, NTLM, PLAIN,
-SCRAM-SHA-1, and SECURID mechanisms.
+SCRAM-SHA-1 (and SCRAM-SHA-1-PLUS), and SECURID mechanisms.
 
 The library is easily ported because it does not do network
 communication by itself, but rather leaves it up to the calling
@@ -1551,6 +1551,15 @@ string.  In the client, the SCRAM-SHA-1 mechanism set 
these properties
 before asking for asking the application to provide a
 @code{GSASL_SCRAM_SALTED_PASSWORD} value.
 
address@hidden @code{GSASL_CB_TLS_UNIQUE}
+
address@hidden channel binding
address@hidden tls-unique
+This property holds base64 encoded @code{tls-unique} channel binding
+data.  As a hint, if you use GnuTLS, the API
address@hidden can be used to extract channel
+bindings for a session.
+
 @end itemize
 
 Next follows a list of data properties used to trigger the callback,
@@ -1818,11 +1827,15 @@ techniques such as HMAC-SHA-1 hashing and PKCS#5 PBKDF2 
key
 derivation.  SCRAM-SHA-1 supports authorization identities.  Like
 CRAM-MD5 and DIGEST-MD5, only a hashed password is transferred.
 Consequently, SCRAM-SHA-1 needs access to the correct password to
-verify the client response.
-
-In the client, this mechanism is always enabled, and it requires the
address@hidden property, and either @code{GSASL_PASSWORD} or
address@hidden  If set, @code{GSASL_AUTHZID} will
+verify the client response.  Channel bindings are supported through
+the SCRAM-SHA-1-PLUS mechanism.
+
+In the client, the non-PLUS mechanism is always enabled, and it
+requires the @code{GSASL_AUTHID} property, and either
address@hidden or @code{GSASL_SCRAM_SALTED_PASSWORD}.  When the
address@hidden property is available, the SCRAM-SHA-1-PLUS
+mechanism is also available and it will negotiate channel bindings
+when the server also supports it.  If set, @code{GSASL_AUTHZID} will
 be used by the client.  To be able to return the proper
 @code{GSASL_SCRAM_SALTED_PASSWORD} value, the client needs to check
 the @code{GSASL_SCRAM_ITER} and @code{GSASL_SCRAM_SALT} values which
@@ -1837,11 +1850,24 @@ normalize the returned password, and compare the client 
response with
 the computed correct response, and accept the user accordingly.  The
 server may also set the @code{GSASL_SCRAM_ITER} and
 @code{GSASL_SCRAM_SALT} properties to influence the values to be used
-by clients to derive a key from a password.
+by clients to derive a key from a password.  When the
address@hidden property is set, the SCRAM-SHA-1-PLUS
+mechanism is supported and is used to negotiate channel bindings.
 
 @cindex channel binding
-Currently channel bindings are not supported, so there is no support
-for SCRAM-SHA-1-PLUS.
+The @code{GSASL_CB_TLS_UNIQUE} property signal that this side of the
+authentication supports channel bindings.  Setting the property will
+enable the SCRAM-SHA-1-PLUS mechanism.  For clients, this also
+instructs the SCRAM-SHA-1 mechanism to tell servers that the client
+believes the server does not support channel bindings if it is used
+(remember that clients should otherwise have chosen the
+SCRAM-SHA-1-PLUS mechanism instead of the SCRAM-SHA-1 mechanism).  For
+servers, it means the SCRAM-SHA-1 mechanism will refuse to
+authenticate against a client that signals that it believes the server
+does not support channel bindings.
+
+The SCRAM-SHA-1-PLUS mechanism will never complete authentication
+successfully if channel bindings are not confirmed.
 
 @node NTLM
 @section The NTLM mechanism
diff --git a/doc/reference/gsasl-docs.sgml b/doc/reference/gsasl-docs.sgml
index c1c5b84..4ad9cd2 100644
--- a/doc/reference/gsasl-docs.sgml
+++ b/doc/reference/gsasl-docs.sgml
@@ -22,8 +22,8 @@ GNU SASL consists of a library (`libgsasl'), a command line 
utility
 library includes support for the framework (with authentication
 functions and application data privacy and integrity functions) and at
 least partial support for the ANONYMOUS, CRAM-MD5, DIGEST-MD5,
-EXTERNAL, GS2-KRB5, GSSAPI, LOGIN, NTLM, PLAIN, SCRAM-SHA-1, and
-SECURID mechanisms.
+EXTERNAL, GS2-KRB5, GSSAPI, LOGIN, NTLM, PLAIN, SCRAM-SHA-1,
+SCRAM-SHA-1-PLUS, and SECURID mechanisms.
     </para>
 
     <para>
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 95b1ad3..b4e9d3b 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,48 @@
+2010-11-14  Simon Josefsson <address@hidden>
+
+       * NEWS, lib/NEWS: Version 1.5.3.
+
+2010-11-14  Simon Josefsson <address@hidden>
+
+       * .gitignore, NEWS, README, configure.ac, doc/gsasl.texi,
+       doc/reference/gsasl-docs.sgml, lib/NEWS, lib/README,
+       lib/scram/client.c, lib/scram/mechinfo.c, lib/scram/parser.c,
+       lib/scram/printer.c, lib/scram/scram.h, lib/scram/server.c,
+       lib/scram/validate.c, lib/src/error.c, lib/src/gsasl.h,
+       lib/src/init.c, lib/src/internal.h, lib/src/property.c,
+       lib/src/xfinish.c, src/callbacks.c, src/gsasl.c, src/internal.h,
+       tests/Makefile.am, tests/scram.c, tests/scramplus.c: Support
+       SCRAM-SHA-1-PLUS.  Add GSASL_CB_TLS_UNIQUE.  Use GnuTLS for
+       tls-unique CB.
+
+2010-11-13  Simon Josefsson <address@hidden>
+
+       * .gitignore: Ignore more.
+
+2010-11-13  Simon Josefsson <address@hidden>
+
+       * src/gsasl.c, tests/cram-md5.c, tests/digest-md5.c,
+       tests/errors.c, tests/external.c, tests/old-cram-md5.c,
+       tests/old-digest-md5.c, tests/old-md5file.c, tests/old-simple.c,
+       tests/scram.c, tests/simple.c, tests/utils.c: Fix compiler warnings.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * NEWS, configure.ac, lib/NEWS, lib/configure.ac, lib/src/gsasl.h: 
+       Bump versions.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * doc/gsasl.texi: Fix typo.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * ChangeLog: Generated.
+
+2010-09-27  Simon Josefsson <address@hidden>
+
+       * lib/ChangeLog: Generated.
+
 2010-09-27  Simon Josefsson <address@hidden>
 
        * NEWS, lib/NEWS: Version 1.5.2.
diff --git a/lib/NEWS b/lib/NEWS
index e25ef72..94ad7a1 100644
--- a/lib/NEWS
+++ b/lib/NEWS
@@ -2,10 +2,19 @@ GNU SASL LIBRARY NEWS -- History of user-visible changes.
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Simon 
Josefsson
 See the end for copying conditions.
 
-* Version 1.5.3 (unreleased) [beta]
+* Version 1.5.3 (released 2010-11-14) [beta]
+
+** libgsasl: Added property for tls-unique channel binding.
+The new property GSASL_CB_TLS_UNIQUE takes a base64 encoded tls-unique
+channel binding.  New error code GSASL_NO_CB_TLS_UNIQUE is returned
+when application fails to provide a channel binding and the mechanism
+requires it (i.e., in a PLUS server).
+
+** SCRAM: Added support for SCRAM-SHA-1-PLUS with channel bindings.
 
 ** API and ABI modifications.
-No changes since last version.
+GSASL_CB_TLS_UNIQUE: ADDED.
+GSASL_NO_CB_TLS_UNIQUE: ADDED.
 
 * Version 1.5.2 (released 2010-09-27) [beta]
 
diff --git a/lib/README b/lib/README
index 419b5b9..8583957 100644
--- a/lib/README
+++ b/lib/README
@@ -29,11 +29,11 @@ Currently there is some support for the following 
mechanisms:
   - PLAIN (RFC 2595)
   - SECURID (RFC 2808)
   - DIGEST-MD5 (RFC 2831)
+  - SCRAM-SHA-1 and SCRAM-SHA-1-PLUS (RFC 5802)
+  - GS2-KRB5 (RFC 5801, no CB, requires GSS, Heimdal, or MIT Kerberos)
   - LOGIN (non-standard)
   - NTLM (non-standard, client only, requires Libntlm)
   - KERBEROS_V5 (experimental, requires Shishi)
-  - SCRAM (no channel bindings)
-  - GS2-KRB5 (no channel bindings, requires GSS, Heimdal or MIT Kerberos)
 
 The library should be portable to all C89 platforms.
 
diff --git a/lib/scram/client.c b/lib/scram/client.c
index de087cc..dda3255 100644
--- a/lib/scram/client.c
+++ b/lib/scram/client.c
@@ -1,5 +1,5 @@
 /* client.c --- SASL SCRAM client side functions.
- * Copyright (C) 2009  Simon Josefsson
+ * Copyright (C) 2009, 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
  *
@@ -46,27 +46,33 @@
 
 struct scram_client_state
 {
+  int plus;
   int step;
   char *cfmb; /* client first message bare */
   char *serversignature;
   char *authmessage;
+  char *cbtlsunique;
+  size_t cbtlsuniquelen;
   struct scram_client_first cf;
   struct scram_server_first sf;
   struct scram_client_final cl;
   struct scram_server_final sl;
 };
 
-int
-_gsasl_scram_sha1_client_start (Gsasl_session * sctx, void **mech_data)
+static int
+scram_start (Gsasl_session * sctx, void **mech_data, int plus)
 {
   struct scram_client_state *state;
   char buf[CNONCE_ENTROPY_BYTES];
+  const char *p;
   int rc;
 
   state = (struct scram_client_state *) calloc (sizeof (*state), 1);
   if (state == NULL)
     return GSASL_MALLOC_ERROR;
 
+  state->plus = plus;
+
   rc = gsasl_nonce (buf, CNONCE_ENTROPY_BYTES);
   if (rc != GSASL_OK)
     {
@@ -82,11 +88,40 @@ _gsasl_scram_sha1_client_start (Gsasl_session * sctx, void 
**mech_data)
       return rc;
     }
 
+  p = gsasl_property_get (sctx, GSASL_CB_TLS_UNIQUE);
+  if (state->plus && !p)
+    {
+      free (state);
+      return GSASL_NO_CB_TLS_UNIQUE;
+    }
+  if (p)
+    {
+      rc = gsasl_base64_from (p, strlen (p), &state->cbtlsunique,
+                             &state->cbtlsuniquelen);
+      if (rc != GSASL_OK)
+       {
+         free (state);
+         return rc;
+       }
+    }
+
   *mech_data = state;
 
   return GSASL_OK;
 }
 
+int
+_gsasl_scram_sha1_client_start (Gsasl_session * sctx, void **mech_data)
+{
+  return scram_start (sctx, mech_data, 0);
+}
+
+int
+_gsasl_scram_sha1_plus_client_start (Gsasl_session * sctx, void **mech_data)
+{
+  return scram_start (sctx, mech_data, 1);
+}
+
 static char
 hexdigit_to_char (char hexdigit)
 {
@@ -146,14 +181,23 @@ _gsasl_scram_sha1_client_step (Gsasl_session * sctx,
       {
        const char *p;
 
-       /* We don't support channel bindings. */
-       state->cf.cbflag = 'n';
+       if (state->plus)
+         {
+           state->cf.cbflag = 'p';
+           state->cf.cbname = strdup ("tls-unique");
+         }
+       else
+         {
+           if (state->cbtlsuniquelen > 0)
+             state->cf.cbflag = 'y';
+           else
+             state->cf.cbflag = 'n';
+         }
 
        p = gsasl_property_get (sctx, GSASL_AUTHID);
        if (!p)
          return GSASL_NO_AUTHID;
 
-       /* FIXME check that final document uses query strings. */
        rc = gsasl_saslprep (p, GSASL_ALLOW_UNASSIGNED,
                             &state->cf.username, NULL);
        if (rc != GSASL_OK)
@@ -171,7 +215,7 @@ _gsasl_scram_sha1_client_step (Gsasl_session * sctx,
 
        *output_len = strlen (*output);
 
-       /* Save "cbind" and "bare" for next step. */
+       /* Point p to client-first-message-bare. */
        p = strchr (*output, ',');
        if (!p)
            return GSASL_AUTHENTICATION_ERROR;
@@ -180,14 +224,30 @@ _gsasl_scram_sha1_client_step (Gsasl_session * sctx,
        if (!p)
            return GSASL_AUTHENTICATION_ERROR;
        p++;
-       rc = gsasl_base64_to (*output, p - *output, &state->cl.cbind, NULL);
-       if (rc != 0)
-         return rc;
 
+       /* Save "client-first-message-bare" for the next step. */
        state->cfmb = strdup (p);
        if (!state->cfmb)
          return GSASL_MALLOC_ERROR;
 
+       /* Prepare B64("cbind-input") for the next step. */
+       if (state->cf.cbflag == 'p')
+         {
+           size_t len = (p - *output) + state->cbtlsuniquelen;
+           char *cbind_input = malloc (len);
+           if (cbind_input == NULL)
+             return GSASL_MALLOC_ERROR;
+           memcpy (cbind_input, *output, p - *output);
+           memcpy (cbind_input + (p - *output), state->cbtlsunique,
+                   state->cbtlsuniquelen);
+           rc = gsasl_base64_to (cbind_input, len, &state->cl.cbind, NULL);
+           free (cbind_input);
+         }
+       else
+         rc = gsasl_base64_to (*output, p - *output, &state->cl.cbind, NULL);
+       if (rc != 0)
+         return rc;
+
        /* We are done. */
        state->step++;
        return GSASL_NEEDS_MORE;
@@ -213,7 +273,7 @@ _gsasl_scram_sha1_client_step (Gsasl_session * sctx,
        {
          char *str = NULL;
          int n;
-         n = asprintf (&str, "%d", state->sf.iter);
+         n = asprintf (&str, "%lu", (unsigned long) state->sf.iter);
          if (n < 0 || str == NULL)
            return GSASL_MALLOC_ERROR;
          gsasl_property_set (sctx, GSASL_SCRAM_ITER, str);
@@ -280,8 +340,8 @@ _gsasl_scram_sha1_client_step (Gsasl_session * sctx,
            /* Compute AuthMessage */
            n = asprintf (&state->authmessage, "%s,%.*s,%.*s",
                          state->cfmb,
-                         input_len, input,
-                         strlen (cfmwp) - 4,
+                         (int) input_len, input,
+                         (int) (strlen (cfmwp) - 4),
                          cfmwp);
            free (cfmwp);
            if (n <= 0 || !state->authmessage)
@@ -399,6 +459,7 @@ _gsasl_scram_sha1_client_finish (Gsasl_session * sctx, void 
*mech_data)
   free (state->cfmb);
   free (state->serversignature);
   free (state->authmessage);
+  free (state->cbtlsunique);
   scram_free_client_first (&state->cf);
   scram_free_server_first (&state->sf);
   scram_free_client_final (&state->cl);
diff --git a/lib/scram/mechinfo.c b/lib/scram/mechinfo.c
index fb5751d..c83350a 100644
--- a/lib/scram/mechinfo.c
+++ b/lib/scram/mechinfo.c
@@ -1,5 +1,5 @@
 /* mechinfo.c --- Definition of SCRAM mechanism.
- * Copyright (C) 2009  Simon Josefsson
+ * Copyright (C) 2009, 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
  *
@@ -62,3 +62,40 @@ Gsasl_mechanism gsasl_scram_sha1_mechanism = {
   }
 };
 #endif
+
+
+#ifdef USE_SCRAM_SHA1
+Gsasl_mechanism gsasl_scram_sha1_plus_mechanism = {
+  GSASL_SCRAM_SHA1_PLUS_NAME,
+  {
+    NULL,
+    NULL,
+#ifdef USE_CLIENT
+    _gsasl_scram_sha1_plus_client_start,
+    _gsasl_scram_sha1_client_step,
+    _gsasl_scram_sha1_client_finish,
+#else
+    NULL,
+    NULL,
+    NULL,
+#endif
+    NULL,
+    NULL
+  },
+  {
+    NULL,
+    NULL,
+#ifdef USE_SERVER
+    _gsasl_scram_sha1_plus_server_start,
+    _gsasl_scram_sha1_server_step,
+    _gsasl_scram_sha1_server_finish,
+#else
+    NULL,
+    NULL,
+    NULL,
+#endif
+    NULL,
+    NULL
+  }
+};
+#endif
diff --git a/lib/scram/parser.c b/lib/scram/parser.c
index 6b9c5b9..e1b9d1a 100644
--- a/lib/scram/parser.c
+++ b/lib/scram/parser.c
@@ -82,12 +82,31 @@ scram_parse_client_first (const char *str, size_t len,
   if (strnlen (str, len) < 10)
     return -1;
 
-  if (len == 0 || (*str != 'n' && *str != 'y'))
-      /* FIXME support channel bindings */
-      return -1;
+  if (len == 0 || (*str != 'n' && *str != 'y' && *str != 'p'))
+    return -1;
   cf->cbflag = *str;
   str++, len--;
 
+  if (cf->cbflag == 'p')
+    {
+      const char *p;
+
+      if (len == 0 || *str != '=')
+       return -1;
+      str++, len--;
+
+      p = memchr (str, ',', len);
+      if (!p)
+       return -1;
+      cf->cbname = malloc (p - str + 1);
+      if (!cf->cbname)
+       return -1;
+      memcpy (cf->cbname, str, p - str + 1);
+      cf->cbname[p- str] = '\0';
+      str += (p - str);
+      len -= (p - str);
+    }
+
   if (len == 0 || *str != ',')
     return -1;
   str++, len--;
diff --git a/lib/scram/printer.c b/lib/scram/printer.c
index e1690af..95135de 100644
--- a/lib/scram/printer.c
+++ b/lib/scram/printer.c
@@ -131,8 +131,8 @@ scram_print_server_first (struct scram_server_first *sf, 
char **out)
   if (!scram_valid_server_first (sf))
     return -1;
 
-  n = asprintf (out, "r=%s,s=%s,i=%d",
-               sf->nonce, sf->salt, sf->iter);
+  n = asprintf (out, "r=%s,s=%s,i=%lu",
+               sf->nonce, sf->salt, (unsigned long) sf->iter);
   if (n <= 0 || *out == NULL)
     return -1;
 
diff --git a/lib/scram/scram.h b/lib/scram/scram.h
index 9c24ba9..20b157d 100644
--- a/lib/scram/scram.h
+++ b/lib/scram/scram.h
@@ -1,5 +1,5 @@
 /* scram.h --- Prototypes for SCRAM mechanism
- * Copyright (C) 2009  Simon Josefsson
+ * Copyright (C) 2009, 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
  *
@@ -26,13 +26,18 @@
 #include <gsasl.h>
 
 #define GSASL_SCRAM_SHA1_NAME "SCRAM-SHA-1"
+#define GSASL_SCRAM_SHA1_PLUS_NAME "SCRAM-SHA-1-PLUS"
 
 extern Gsasl_mechanism gsasl_scram_sha1_mechanism;
+extern Gsasl_mechanism gsasl_scram_sha1_plus_mechanism;
 
 int
 _gsasl_scram_sha1_client_start (Gsasl_session * sctx, void **mech_data);
 
 int
+_gsasl_scram_sha1_plus_client_start (Gsasl_session * sctx, void **mech_data);
+
+int
 _gsasl_scram_sha1_client_step (Gsasl_session * sctx,
                               void *mech_data,
                               const char *input, size_t input_len,
@@ -46,6 +51,9 @@ int
 _gsasl_scram_sha1_server_start (Gsasl_session * sctx, void **mech_data);
 
 int
+_gsasl_scram_sha1_plus_server_start (Gsasl_session * sctx, void **mech_data);
+
+int
 _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
                               void *mech_data,
                               const char *input,
diff --git a/lib/scram/server.c b/lib/scram/server.c
index 6176243..ea1a5ae 100644
--- a/lib/scram/server.c
+++ b/lib/scram/server.c
@@ -50,6 +50,7 @@
 
 struct scram_server_state
 {
+  int plus;
   int step;
   char *gs2header; /* copy of client first gs2-header */
   char *cfmb_str; /* copy of client first message bare */
@@ -59,23 +60,28 @@ struct scram_server_state
   char *storedkey;
   char *serverkey;
   char *authmessage;
+  char *cbtlsunique;
+  size_t cbtlsuniquelen;
   struct scram_client_first cf;
   struct scram_server_first sf;
   struct scram_client_final cl;
   struct scram_server_final sl;
 };
 
-int
-_gsasl_scram_sha1_server_start (Gsasl_session * sctx, void **mech_data)
+static int
+scram_start (Gsasl_session * sctx, void **mech_data, int plus)
 {
   struct scram_server_state *state;
   char buf[MAX (SNONCE_ENTROPY_BYTES, DEFAULT_SALT_BYTES)];
+  const char *p;
   int rc;
 
   state = (struct scram_server_state *) calloc (sizeof (*state), 1);
   if (state == NULL)
     return GSASL_MALLOC_ERROR;
 
+  state->plus = plus;
+
   rc = gsasl_nonce (buf, SNONCE_ENTROPY_BYTES);
   if (rc != GSASL_OK)
     goto end;
@@ -94,6 +100,20 @@ _gsasl_scram_sha1_server_start (Gsasl_session * sctx, void 
**mech_data)
   if (rc != GSASL_OK)
     goto end;
 
+  p = gsasl_property_get (sctx, GSASL_CB_TLS_UNIQUE);
+  if (plus && !p)
+    {
+      rc = GSASL_NO_CB_TLS_UNIQUE;
+      goto end;
+    }
+  if (p)
+    {
+      rc = gsasl_base64_from (p, strlen (p), &state->cbtlsunique,
+                             &state->cbtlsuniquelen);
+      if (rc != GSASL_OK)
+       goto end;
+    }
+
   *mech_data = state;
 
   return GSASL_OK;
@@ -106,6 +126,18 @@ _gsasl_scram_sha1_server_start (Gsasl_session * sctx, void 
**mech_data)
 }
 
 int
+_gsasl_scram_sha1_server_start (Gsasl_session * sctx, void **mech_data)
+{
+  return scram_start (sctx, mech_data, 0);
+}
+
+int
+_gsasl_scram_sha1_plus_server_start (Gsasl_session * sctx, void **mech_data)
+{
+  return scram_start (sctx, mech_data, 1);
+}
+
+int
 _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
                               void *mech_data,
                               const char *input,
@@ -129,10 +161,17 @@ _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
        if (scram_parse_client_first (input, input_len, &state->cf) < 0)
          return GSASL_MECHANISM_PARSE_ERROR;
 
-       /* We don't support channel bindings. */
-       if (state->cf.cbflag != 'n' && state->cf.cbflag != 'y')
+       /* In PLUS server mode, we require use of channel bindings. */
+       if (state->plus && state->cf.cbflag != 'p')
          return GSASL_AUTHENTICATION_ERROR;
 
+       /* In non-PLUS mode, but where have channel bindings data (and
+          thus advertised PLUS) we reject a client 'y' cbflag. */
+       if (!state->plus
+           && state->cbtlsuniquelen > 0
+           && state->cf.cbflag == 'y')
+           return GSASL_AUTHENTICATION_ERROR;
+
        /* Check that username doesn't fail SASLprep. */
        {
          char *tmp;
@@ -226,7 +265,7 @@ _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
          return GSASL_AUTHENTICATION_ERROR;
 
        /* Base64 decode the c= field and check that it matches
-          client-first. */
+          client-first.  Also check channel binding data. */
        {
          size_t len;
          char *cbind;
@@ -236,11 +275,30 @@ _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
          if (rc != 0)
            return rc;
 
-         if (len != strlen (state->gs2header))
-           return GSASL_AUTHENTICATION_ERROR;
+         if (state->cf.cbflag == 'p')
+           {
+             if (len < strlen (state->gs2header))
+               return GSASL_AUTHENTICATION_ERROR;
 
-         if (memcmp (cbind, state->gs2header, len) != 0)
-           return GSASL_AUTHENTICATION_ERROR;
+             if (memcmp (cbind, state->gs2header,
+                         strlen (state->gs2header)) != 0)
+               return GSASL_AUTHENTICATION_ERROR;
+
+             if (len - strlen (state->gs2header) != state->cbtlsuniquelen)
+               return GSASL_AUTHENTICATION_ERROR;
+
+             if (memcmp (cbind + strlen (state->gs2header),
+                         state->cbtlsunique, state->cbtlsuniquelen) != 0)
+               return GSASL_AUTHENTICATION_ERROR;
+           }
+         else
+           {
+             if (len != strlen (state->gs2header))
+               return GSASL_AUTHENTICATION_ERROR;
+
+             if (memcmp (cbind, state->gs2header, len) != 0)
+               return GSASL_AUTHENTICATION_ERROR;
+           }
        }
 
        /* Base64 decode client proof and check that length matches
@@ -328,8 +386,8 @@ _gsasl_scram_sha1_server_step (Gsasl_session * sctx,
 
            n = asprintf (&state->authmessage, "%s,%.*s,%.*s",
                          state->cfmb_str,
-                         strlen (state->sf_str), state->sf_str,
-                         len, input);
+                         (int) strlen (state->sf_str), state->sf_str,
+                         (int) len, input);
            if (n <= 0 || !state->authmessage)
              return GSASL_MALLOC_ERROR;
          }
diff --git a/lib/scram/validate.c b/lib/scram/validate.c
index 9475473..a25092b 100644
--- a/lib/scram/validate.c
+++ b/lib/scram/validate.c
@@ -1,5 +1,5 @@
 /* validate.c --- Validate consistency of SCRAM tokens.
- * Copyright (C) 2009  Simon Josefsson
+ * Copyright (C) 2009, 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
  *
@@ -51,7 +51,17 @@ scram_valid_client_first (struct scram_client_first *cf)
   else if (cf->cbflag != 'p' && cf->cbname != NULL)
     return false;
 
-  /* FIXME check that cbname matches [A-Za-z0-9.-]. */
+  if (cf->cbname)
+    {
+      const char *p = cf->cbname;
+
+      while (*p && strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                          "abcdefghijklmnopqrstuvwxyz"
+                          "0123456789.-", *p))
+       p++;
+      if (*p)
+       return false;
+    }
 
   /* We require a non-zero username string. */
   if (cf->username == NULL || *cf->username == '\0')
diff --git a/lib/src/error.c b/lib/src/error.c
index 22d3a21..c80c0ac 100644
--- a/lib/src/error.c
+++ b/lib/src/error.c
@@ -195,8 +195,9 @@ static struct {
   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."))
-
+       N_("GSSAPI error releasing OID set.")),
+  ERR (GSASL_NO_CB_TLS_UNIQUE,
+       N_("Authentication failed because a tls-unique CB was not provided."))
 };
 
 /**
diff --git a/lib/src/gsasl.h b/lib/src/gsasl.h
index 4473fcd..a4f2b31 100644
--- a/lib/src/gsasl.h
+++ b/lib/src/gsasl.h
@@ -135,6 +135,7 @@ extern "C"
    * @GSASL_NO_PIN: Could not get required SecurID PIN.
    * @GSASL_NO_SERVICE: Could not get required service name.
    * @GSASL_NO_HOSTNAME: Could not get required hostname.
+   * @GSASL_NO_CB_TLS_UNIQUE: Could not get required tls-unique CB.
    * @GSASL_GSSAPI_RELEASE_BUFFER_ERROR: GSS-API library call error.
    * @GSASL_GSSAPI_IMPORT_NAME_ERROR: GSS-API library call error.
    * @GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR: GSS-API library call error.
@@ -184,6 +185,7 @@ extern "C"
     GSASL_NO_PIN = 57,
     GSASL_NO_SERVICE = 58,
     GSASL_NO_HOSTNAME = 59,
+    GSASL_NO_CB_TLS_UNIQUE = 65,
     /* Mechanism specific errors. */
     GSASL_GSSAPI_RELEASE_BUFFER_ERROR = 37,
     GSASL_GSSAPI_IMPORT_NAME_ERROR = 38,
@@ -297,6 +299,7 @@ extern "C"
    * @GSASL_SCRAM_SALT: Salt for password-to-key hashing.
    * @GSASL_SCRAM_SALTED_PASSWORD: Pre-computed salted SCRAM key,
    *   to avoid re-computation and storing passwords in the clear.
+   * @GSASL_CB_TLS_UNIQUE: Base64 encoded tls-unique channel binding.
    * @GSASL_VALIDATE_SIMPLE: Request for simple validation.
    * @GSASL_VALIDATE_EXTERNAL: Request for validation of EXTERNAL.
    * @GSASL_VALIDATE_ANONYMOUS: Request for validation of ANONYMOUS.
@@ -325,6 +328,7 @@ extern "C"
     GSASL_SCRAM_ITER = 15,
     GSASL_SCRAM_SALT = 16,
     GSASL_SCRAM_SALTED_PASSWORD = 17,
+    GSASL_CB_TLS_UNIQUE = 18,
     /* Server validation callback properties. */
     GSASL_VALIDATE_SIMPLE = 500,
     GSASL_VALIDATE_EXTERNAL = 501,
diff --git a/lib/src/init.c b/lib/src/init.c
index f764bdb..9889b31 100644
--- a/lib/src/init.c
+++ b/lib/src/init.c
@@ -1,5 +1,5 @@
 /* init.c --- Entry point for libgsasl.
- * 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.
  *
@@ -106,6 +106,10 @@ register_builtin_mechs (Gsasl * ctx)
   rc = gsasl_register (ctx, &gsasl_scram_sha1_mechanism);
   if (rc != GSASL_OK)
     return rc;
+
+  rc = gsasl_register (ctx, &gsasl_scram_sha1_plus_mechanism);
+  if (rc != GSASL_OK)
+    return rc;
 #endif /* USE_SCRAM_SHA1 */
 
 #ifdef USE_GSSAPI
diff --git a/lib/src/internal.h b/lib/src/internal.h
index 1e41ea7..d494222 100644
--- a/lib/src/internal.h
+++ b/lib/src/internal.h
@@ -1,5 +1,5 @@
 /* internal.h --- Internal header with hidden library handle structures.
- * 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.
  *
@@ -102,6 +102,7 @@ struct Gsasl_session
   char *scram_iter;
   char *scram_salt;
   char *scram_salted_password;
+  char *cb_tls_unique;
 
 #ifndef GSASL_NO_OBSOLETE
   /* Obsolete stuff. */
diff --git a/lib/src/property.c b/lib/src/property.c
index 1f3825f..4342a19 100644
--- a/lib/src/property.c
+++ b/lib/src/property.c
@@ -1,5 +1,5 @@
 /* property.c --- Callback property handling.
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009  Simon Josefsson
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010  Simon Josefsson
  *
  * This file is part of GNU SASL Library.
  *
@@ -100,6 +100,10 @@ map (Gsasl_session * sctx, Gsasl_property prop)
       p = &sctx->scram_salted_password;
       break;
 
+    case GSASL_CB_TLS_UNIQUE:
+      p = &sctx->cb_tls_unique;
+      break;
+
     default:
       break;
     }
diff --git a/lib/src/xfinish.c b/lib/src/xfinish.c
index 4b963bf..23e49e2 100644
--- a/lib/src/xfinish.c
+++ b/lib/src/xfinish.c
@@ -63,6 +63,7 @@ gsasl_finish (Gsasl_session * sctx)
   free (sctx->scram_iter);
   free (sctx->scram_salt);
   free (sctx->scram_salted_password);
+  free (sctx->cb_tls_unique);
 
   free (sctx);
 }
diff --git a/src/callbacks.c b/src/callbacks.c
index 4b41a2e..52f4767 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -1,5 +1,5 @@
 /* callbacks.c --- Implementation of gsasl callbacks.
- * 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.
  *
@@ -83,6 +83,15 @@ callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property 
prop)
       rc = GSASL_OK;
       break;
 
+    case GSASL_CB_TLS_UNIQUE:
+      if (b64cbtlsunique == NULL && args_info.hostname_arg == NULL)
+       b64cbtlsunique =
+         readutf8line ("Enter base64 encoded tls-unique channel binding: ");
+      if (*b64cbtlsunique)
+       gsasl_property_set (sctx, prop, b64cbtlsunique);
+      rc = GSASL_OK;
+      break;
+
     case GSASL_PASSWORD:
       if (args_info.password_arg == NULL)
        args_info.password_arg = readutf8pass ("Enter password: ");
@@ -191,6 +200,8 @@ callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property 
prop)
       break;
 
     case GSASL_SCRAM_SALTED_PASSWORD:
+    case GSASL_SCRAM_ITER:
+    case GSASL_SCRAM_SALT:
       break;
 
     default:
diff --git a/src/gsasl.c b/src/gsasl.c
index bcd4b16..433c216 100644
--- a/src/gsasl.c
+++ b/src/gsasl.c
@@ -31,6 +31,8 @@ gnutls_session session;
 bool using_tls = false;
 #endif
 
+char *b64cbtlsunique = NULL;
+
 struct gengetopt_args_info args_info;
 int sockfd = 0;
 
@@ -604,6 +606,24 @@ main (int argc, char *argv[])
                   _("could not verify server certificate (rc=%d)"), status);
        }
 
+#if HAVE_GNUTLS_SESSION_CHANNEL_BINDING
+       {
+         gnutls_datum cb;
+
+         res = gnutls_session_channel_binding (session,
+                                               GNUTLS_CB_TLS_UNIQUE,
+                                               &cb);
+         if (res != GNUTLS_E_SUCCESS)
+           error (EXIT_FAILURE, 0, _("getting channel binding failed: %s"),
+                  gnutls_strerror (res));
+
+         res = gsasl_base64_to ((char *) cb.data, cb.size,
+                                &b64cbtlsunique, NULL);
+         if (res != GSASL_OK)
+           error (EXIT_FAILURE, 0, "%s", gsasl_strerror (res));
+       }
+#endif
+
       using_tls = true;
     }
 #endif
diff --git a/src/internal.h b/src/internal.h
index f236945..ef6c8de 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -66,6 +66,7 @@ extern int readln (char **out);
 
 #include "gsasl_cmd.h"
 extern struct gengetopt_args_info args_info;
+extern char *b64cbtlsunique;
 
 /* This feature is available in gcc versions 2.5 and later.  */
 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 58d571c..d34e184 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -42,7 +42,7 @@ TESTS_ENVIRONMENT = \
        $(VALGRIND)
 
 ctests = external cram-md5 digest-md5 md5file name errors suggest      \
-       simple crypto scram symbols readnz gssapi gs2-krb5
+       simple crypto scram scramplus symbols readnz gssapi gs2-krb5
 if OBSOLETE
 ctests += old-simple old-md5file old-cram-md5 old-digest-md5   \
        old-base64
diff --git a/tests/scram.c b/tests/scram.c
index 984b6a6..6e6cf8d 100644
--- a/tests/scram.c
+++ b/tests/scram.c
@@ -107,6 +107,9 @@ callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property 
prop)
        }
       break;
 
+    case GSASL_CB_TLS_UNIQUE:
+      break;
+
     default:
       fail ("Unknown callback property %d\n", prop);
       break;
diff --git a/tests/scram.c b/tests/scramplus.c
similarity index 86%
copy from tests/scram.c
copy to tests/scramplus.c
index 984b6a6..0e1ab28 100644
--- a/tests/scram.c
+++ b/tests/scramplus.c
@@ -1,4 +1,4 @@
-/* scram.c --- Test the SCRAM mechanism.
+/* scramplus.c --- Test the SCRAM-SHA-1-PLUS mechanism.
  * Copyright (C) 2009, 2010  Simon Josefsson
  *
  * This file is part of GNU SASL.
@@ -107,6 +107,11 @@ callback (Gsasl * ctx, Gsasl_session * sctx, 
Gsasl_property prop)
        }
       break;
 
+    case GSASL_CB_TLS_UNIQUE:
+      gsasl_property_set (sctx, prop, "Zm5vcmQ=");
+      rc = GSASL_OK;
+      break;
+
     default:
       fail ("Unknown callback property %d\n", prop);
       break;
@@ -131,11 +136,11 @@ doit (void)
       return;
     }
 
-  if (!gsasl_client_support_p (ctx, "SCRAM-SHA-1")
-      || !gsasl_server_support_p (ctx, "SCRAM-SHA-1"))
+  if (!gsasl_client_support_p (ctx, "SCRAM-SHA-1-PLUS")
+      || !gsasl_server_support_p (ctx, "SCRAM-SHA-1-PLUS"))
     {
       gsasl_done (ctx);
-      fail("No support for SCRAM-SHA-1.\n");
+      fail("No support for SCRAM-SHA-1-PLUS.\n");
       exit(77);
     }
 
@@ -148,14 +153,14 @@ doit (void)
       if (debug)
        printf ("Iteration %d ...\n", i);
 
-      res = gsasl_server_start (ctx, "SCRAM-SHA-1", &server);
+      res = gsasl_server_start (ctx, "SCRAM-SHA-1-PLUS", &server);
       if (res != GSASL_OK)
        {
          fail ("gsasl_server_start() failed (%d):\n%s\n",
                res, gsasl_strerror (res));
          return;
        }
-      res = gsasl_client_start (ctx, "SCRAM-SHA-1", &client);
+      res = gsasl_client_start (ctx, "SCRAM-SHA-1-PLUS", &client);
       if (res != GSASL_OK)
        {
          fail ("gsasl_client_start() failed (%d):\n%s\n",
@@ -196,29 +201,6 @@ doit (void)
          return;
        }
 
-      if (i == 16 || i == 17)
-       s1[0] = 'y';
-
-      if (i == 18)
-       {
-         char *s;
-
-         asprintf (&s, "%s,a=b", s1);
-         gsasl_free (s1);
-         s1 = s;
-         s1len = strlen (s);
-       }
-
-      if (i == 20)
-       {
-         char *s;
-
-         asprintf (&s, "%s,a=b,b=c,c=d", s1);
-         gsasl_free (s1);
-         s1 = s;
-         s1len = strlen (s);
-       }
-
       if (debug)
        printf ("C: %.*s [%c]\n", (int) s1len,
                s1, res == GSASL_OK ? 'O' : 'N');
@@ -249,30 +231,24 @@ doit (void)
          return;
        }
 
+      if (debug)
+       printf ("C: %.*s [%c]\n", (int) s1len,
+               s1, res == GSASL_OK ? 'O' : 'N');
+
+      /* Shorten length of cbdata. */
       if (i == 17)
-       memcpy (s1 + 2, "eS", 2);
+       s1[41] = '=';
 
-      if (i == 19 && s1len > 31)
+      /* Increase length of cbdata. */
+      if (i == 18)
        {
-         char *s;
-
-         asprintf (&s, "%.*s,a=b,%s", (int) (s1len - 31),
-                   s1, s1 + s1len - 31 + 1);
-         gsasl_free (s1);
-         s1 = s;
-         s1len = strlen (s);
+         s1[28] = 'B';
+         s1[29] = 'C';
        }
 
-      if (i == 21 && s1len > 31)
-       {
-         char *s;
-
-         asprintf (&s, "%.*s,a=b,b=c,c=d,%s", (int) (s1len - 31),
-                   s1, s1 + s1len - 31 + 1);
-         gsasl_free (s1);
-         s1 = s;
-         s1len = strlen (s);
-       }
+      /* Modify cbdata. */
+      if (i == 19)
+         s1[30] = 'B';
 
       if (debug)
        printf ("C: %.*s [%c]\n", (int) s1len,
@@ -282,7 +258,7 @@ doit (void)
 
       res = gsasl_step (server, s1, s1len, &s2, &s2len);
       gsasl_free (s1);
-      if (i >= 16 && i <= 21)
+      if (i >= 17 && i <= 19)
        {
          if (res == GSASL_AUTHENTICATION_ERROR)
            {


hooks/post-receive
-- 
GNU gsasl



reply via email to

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