<HTML><FONT FACE=arial,helvetica><FONT COLOR="#000000" FACE="Geneva" FAMILY="SANSSERIF" SIZE="2" STYLE="BACKGROUND-COLOR: #FFFFFF">I can assure you it's possible... cause I've done it!<BR>
<BR>
I'd have to do some serious editing to post a complete implementation, but here are a few of the important handlers I came up with. The checkPassword() handler has been edited heavily from my original code, so it may need some fixing. Also note that the nonce / opaque values are not implemented ideally in authenticateHeader(). You'll need a basic understanding of the RFC to make good use of these.<BR>
<BR>
Hope this helps!<BR>
<BR>
function checkPassword theSocket,requestHeader,@replyHeader,@userName<BR>
   global server_opaque,server_nonce,nonce_time, loggedInIDs, loggedInNames, xfactor<BR>
<BR>
   put "WebCF Registered Users" into realm -- default<BR>
   <BR>
   put lineOffset("Authorization:", requestHeader) into theLine<BR>
   <BR>
   if (theLine > 0) then<BR>
     -- check the authorization<BR>
     put word 1 of requestHeader into method<BR>
     put line theLine of requestHeader into authLine<BR>
     <BR>
     replace "Authorization: Digest" with empty in authLine<BR>
     set the itemDelimiter to comma<BR>
     repeat for each item theItem in authLine<BR>
       set the itemDelimiter to "="<BR>
       put item 1 of theItem into theName<BR>
       repeat until (char 1 of theName <> " ")<BR>
         delete char 1 of theName<BR>
       end repeat<BR>
       replace (theName&"=") with (theName&"◊") in theItem<BR>
       set the itemDelimiter to "◊"<BR>
       put item 2 of theItem into theValue<BR>
       replace quote with empty in theValue<BR>
       set the itemDelimiter to comma<BR>
       switch(theName)<BR>
       case "userName"<BR>
         put theValue into userName<BR>
         exit switch<BR>
       case "realm"<BR>
         put theValue into realm<BR>
         exit switch<BR>
       case "nonce"<BR>
         put theValue into nonce<BR>
         exit switch<BR>
       case "uri"<BR>
         put theValue into theURL<BR>
         exit switch<BR>
       case "qop"<BR>
         put theValue into qop<BR>
         exit switch<BR>
       case "nc"<BR>
         put theValue into nc<BR>
         exit switch<BR>
       case "cnonce"<BR>
         put theValue into cnonce<BR>
         exit switch<BR>
       case "response"<BR>
         put theValue into digestValue<BR>
         exit switch<BR>
       case "opaque"<BR>
         put theValue into opaque<BR>
         exit switch<BR>
       end switch<BR>
     end repeat<BR>
   else<BR>
     put authenticateHeader(realm,"auth",empty,"default") into replyHeader<BR>
     return FALSE<BR>
   end if<BR>
<BR>
   ## edit this to lookup the correct password<BR>
   put empty into userID<BR>
   put lookupPassword(userName, userID) into password<BR>
   if (password is empty) then<BR>
     put authenticateHeader(realm,"auth",empty,"default") into replyHeader<BR>
     return FALSE<BR>
   end if<BR>
   <BR>
   put makeDigest(userName,password,realm,method,theURL,nonce,nc,cnonce,qop) into actualValue<BR>
   <BR>
   put char 1 to length(actualValue) of digestValue into digestValue<BR>
   if ((digestValue = actualValue) AND (opaque = server_opaque)) then<BR>
       put authenticateInfoHeader(userName,password,realm,method,theURL,server_nonce[userName]) into replyHeader<BR>
       put userID into loggedInIDs[theSocket]<BR>
       put userName into loggedInNames[theSocket]<BR>
       <BR>
       put base64Encode(userName&tab&thePassword) into loginValue<BR>
       SetCookie theSocket,"webcf_entry",loginValue<BR>
       return TRUE<BR>
   else<BR>
     -- failed<BR>
     put authenticateHeader(realm,"auth",empty) into replyHeader<BR>
     return FALSE<BR>
   end if<BR>
end checkPassword<BR>
<BR>
<BR>
function authenticateInfoHeader userName,_password,realm,method,theURL,nonce<BR>
   put makeDigest(userName,_password,realm,empty,theURL,nonce) into response<BR>
   return "Authentication-Info: next-nonce="&quote&nonce&quote&comma&"qop="&quote&auth&quote&comma&"rspauth="&quote&response&quote<BR>
end authenticateInfoHeader<BR>
<BR>
function authenticateHeader theRealm,authMethods,isStale,userName,forceNonce<BR>
   global server_opaque,server_nonce,cfLF<BR>
   if (userName is empty) then put "default" into userName<BR>
   if (server_opaque is empty) then put base64Encode(random(4*(the ticks))&md5Digest(the ticks)) into server_opaque<BR>
   if (server_nonce is empty) OR (forceNonce) then<BR>
     put base64Encode("Dummy") into server_nonce<BR>
   end if<BR>
   if (isStale is empty) then return "HTTP/1.1 401 Unauthorized"&crLF&"WWW-Authenticate: Digest"&&"realm="&quote&theRealm&quote&comma&"qop="&quote&authMethods&quote&comma&"nonce="&quote&server_nonce&quote&comma&"opaque="&quote&server_opaque&quote&comma&"algorithm="&quote&"MD5"&quote&crLF<BR>
   else<BR>
     return "HTTP/1.1 401 Unauthorized"&crLF&"Connection: close"&crLF&"WWW-Authenticate: Digest"&&"realm="&quote&theRealm&quote&comma&"qop="&quote&authMethods&quote&comma&"nonce="&quote&server_nonce&quote&comma&"opaque="&quote&server_opaque&quote&comma&"stale="&isStale&",algorithm="&quote&"MD5"&quote&crLF<BR>
   end if<BR>
end authenticateHeader<BR>
<BR>
function makeDigest userName,_password,realm,method,theURL,nonce,nc,cnonce,qop<BR>
   put md5Digest(userName&colon&realm&colon&_password) into A1<BR>
   get binaryDecode("H*",A1,A1)<BR>
   put md5Digest(method&colon&theURL) into A2<BR>
   get binaryDecode("H*",A2,A2)<BR>
   if (qop is empty) then<BR>
     put md5Digest(A1&colon&nonce&colon&A2) into actualValue<BR>
   else<BR>
     put md5Digest(A1&colon&nonce&colon&nc&colon&cnonce&colon&qop&colon&A2) into actualValue<BR>
   end if<BR>
   get binaryDecode("H*",actualValue,actualValue)<BR>
   return actualvalue<BR>
end makeDigest<BR>
<BR>
<BR>
<BLOCKQUOTE CITE STYLE="BORDER-LEFT: #0000ff 2px solid; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px; PADDING-LEFT: 5px" TYPE="CITE"></FONT><FONT COLOR="#000000" FACE="Geneva" FAMILY="SANSSERIF" SIZE="2" STYLE="BACKGROUND-COLOR: #FFFFFF"><BR>
I'm sure it'll be a piece of cake, Rob. :)  But please let us know <BR>
what you come up with. The truth is I just want someone else to <BR>
interpret section 3.2.2 of the rfc on digest authorization. I'm <BR>
trying to preserve what few brain cells I have remaining.<BR>
</BLOCKQUOTE></FONT><FONT COLOR="#000000" FACE="Geneva" FAMILY="SANSSERIF" SIZE="2" STYLE="BACKGROUND-COLOR: #FFFFFF"><BR>
<BR>
</FONT><FONT COLOR="#000000" FACE="Geneva" FAMILY="SANSSERIF" SIZE="2" STYLE="BACKGROUND-COLOR: #FFFFFF"></FONT></HTML>