Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/sasl/ChangeLog,v
retrieving revision 1.20
diff -u -r1.20 ChangeLog
--- ChangeLog	25 Mar 2007 01:29:28 -0000	1.20
+++ ChangeLog	26 Aug 2007 00:15:53 -0000
@@ -1,3 +1,8 @@
+2007-08-26  Pat Thoyts  <patthoyts@users.sourceforge.net>
+
+	* sasl.tcl: Fix bug #1545306 noncecount mishandled in DIGEST-MD5.
+	Enable support for re-authentication in client via SASL::reset
+
 2007-03-21  Andreas Kupries  <andreas_kupries@users.sourceforge.net>
 
 	* sasl.man: Fixed all warnings due to use of now deprecated
@@ -107,4 +112,4 @@
 	* sasl.tcl: Initial version (DIGEST-MD5, CRAM-MD5, PLAIN, LOGIN)
 	* ntlm.tcl: Implementation of Microsoft NTLM as SASL mechanism.
 	* saslclient.tcl: SMTP-SASL test harness.
-	
\ No newline at end of file
+	
Index: sasl.tcl
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/sasl/sasl.tcl,v
retrieving revision 1.11
diff -u -r1.11 sasl.tcl
--- sasl.tcl	2 Oct 2006 21:21:57 -0000	1.11
+++ sasl.tcl	26 Aug 2007 00:11:40 -0000
@@ -106,9 +106,9 @@
 #	Reset the SASL state. This permits the same instance to be reused
 #	for a new round of authentication.
 #
-proc ::SASL::reset {context} {
+proc ::SASL::reset {context {step 0}} {
     upvar #0 $context ctx
-    array set ctx [list step 0 response "" valid false count 0]
+    array set ctx [list step $step response "" valid false count 0]
     return $context
 }
 
@@ -442,25 +442,29 @@
 # Comments:
 #
 proc ::SASL::DIGEST-MD5:client {context challenge args} {
-    variable digest_md5_noncecount
     upvar #0 $context ctx
     md5_init
     if {$ctx(step) == 0 && [string length $challenge] == 0} {
-        set ctx(response) ""
-        return 1
+        if {[info exists ctx(challenge)]} {
+            set challenge $ctx(challenge)
+        } else {
+            set ctx(response) ""
+            return 1
+        }
     }
     incr ctx(step)
     set result 0
     switch -exact -- $ctx(step) {
         1 {
+            set ctx(challenge) $challenge
             array set params [DigestParameters $challenge]
             
-            if {![info exists digest_md5_noncecount]} {
-                set digest_md5_noncecount 0
+            if {![info exists ctx(noncecount)]} {
+                set ctx(noncecount) 0
             }
             set nonce $params(nonce)
             set cnonce [CreateNonce]
-            set noncecount [format %08u [incr digest_md5_noncecount]]
+            set noncecount [format %08u [incr ctx(noncecount)]]
             set qop auth
             
             set username [eval $ctx(callback) [list $context username]]
@@ -491,7 +495,6 @@
 }
 
 proc ::SASL::DIGEST-MD5:server {context challenge args} {
-    variable digest_md5_noncecount
     upvar #0 $context ctx
     md5_init
     incr ctx(step)
@@ -500,6 +503,7 @@
         1 {
             set realm [eval $ctx(callback) [list $context realm]]
             set ctx(nonce) [CreateNonce]
+            set ctx(nc) 0
             set ctx(response) "realm=\"$realm\",nonce=\"$ctx(nonce)\",qop=\"auth\",charset=utf-8,algorithm=md5-sess"
             set result 1
         }
@@ -509,13 +513,14 @@
             set password [eval $ctx(callback)\
                               [list $context password $params(username) $realm]]
             set uri "$ctx(service)/$realm"
+            set nc [format %08u [expr {$ctx(nc) + 1}]]
             set R [DigestResponse $params(username) $realm $password \
-                       $uri auth $ctx(nonce) $params(nc) $params(cnonce)]
+                       $uri auth $ctx(nonce) $nc $params(cnonce)]
             if {[string equal $R $params(response)]} {
                 set R2 [DigestResponse $params(username) $realm $password \
-                        $uri auth $ctx(nonce) $params(nc) $params(cnonce)]
+                        $uri auth $ctx(nonce) $nc $params(cnonce)]
                 set ctx(response) "rspauth=$R2"
-                set ctx(nc) $params(nc)
+                incr ctx(nc)
                 set result 1
             } else {
                 return -code error "authentication failed"
