offset += (hostLen + LM_RESP_LEN + NTLM_RESP_LEN); cursor = WriteSecBuf(cursor, 0, offset);
cursor = WriteSecBuf(cursor, 0, 0);
GenerateType3Msg(const nsString &domain,                 const nsString &username,                 const nsString &password,                 const void     *inBuf,                 PRUint32        inLen,                 void          **outBuf,                 PRUint32       *outLen){  // inBuf contains Type-2 msg (the challenge) from server  nsresult rv;  Type2Msg msg;  rv = ParseType2Msg(inBuf, inLen, &msg);  if (NS_FAILED(rv))    return rv;  PRBool unicode = (msg.flags & NTLM_NegotiateUnicode);  // temporary buffers for unicode strings#ifdef IS_BIG_ENDIAN  nsAutoString ucsDomainBuf, ucsUserBuf;#endif  nsAutoString ucsHostBuf;   // temporary buffers for oem strings  nsCAutoString oemDomainBuf, oemUserBuf, oemHostBuf;  // pointers and lengths for the string buffers; encoding is unicode if  // the "negotiate unicode" flag was set in the Type-2 message.  const void *domainPtr, *userPtr, *hostPtr;  PRUint32 domainLen, userLen, hostLen;  //  // get domain name  //  if (unicode)  {#ifdef IS_BIG_ENDIAN    ucsDomainBuf = domain;    domainPtr = ucsDomainBuf.get();    domainLen = ucsDomainBuf.Length() * 2;    WriteUnicodeLE((void *) domainPtr, (const PRUnichar *) domainPtr, domainLen);#else    domainPtr = domain.get();    domainLen = domain.Length() * 2;#endif  }  else  {    NS_CopyUnicodeToNative(domain, oemDomainBuf);    domainPtr = oemDomainBuf.get();    domainLen = oemDomainBuf.Length();  }  //  // get user name  //  if (unicode)  {#ifdef IS_BIG_ENDIAN    ucsUserBuf = username;    userPtr = ucsUserBuf.get();    userLen = ucsUserBuf.Length() * 2;    WriteUnicodeLE((void *) userPtr, (const PRUnichar *) userPtr, userLen);#else    userPtr = username.get();    userLen = username.Length() * 2;#endif  }  else  {    NS_CopyUnicodeToNative(username, oemUserBuf);    userPtr = oemUserBuf.get();    userLen = oemUserBuf.Length();  }  //  // get workstation name (use local machine's hostname)  //  char hostBuf[SYS_INFO_BUFFER_LENGTH];  if (PR_GetSystemInfo(PR_SI_HOSTNAME, hostBuf, sizeof(hostBuf)) == PR_FAILURE)    return NS_ERROR_UNEXPECTED;  hostLen = strlen(hostBuf);  if (unicode)  {    // hostname is ASCII, so we can do a simple zero-pad expansion:    CopyASCIItoUCS2(nsDependentCString(hostBuf, hostLen), ucsHostBuf);    hostPtr = ucsHostBuf.get();    hostLen = ucsHostBuf.Length() * 2;#ifdef IS_BIG_ENDIAN    WriteUnicodeLE((void *) hostPtr, (const PRUnichar *) hostPtr, hostLen);#endif  }  else    hostPtr = hostBuf;  //  // now that we have generated all of the strings, we can allocate outBuf.  //  *outLen = NTLM_TYPE3_HEADER_LEN + hostLen + domainLen + userLen +            LM_RESP_LEN + NTLM_RESP_LEN;  *outBuf = nsMemory::Alloc(*outLen);  if (!*outBuf)    return NS_ERROR_OUT_OF_MEMORY;  //  // next, we compute the LM and NTLM responses.  //  PRUint8 lmResp[LM_RESP_LEN], ntlmResp[NTLM_RESP_LEN], ntlmHash[NTLM_HASH_LEN];  if (msg.flags & NTLM_NegotiateNTLM2Key)  {    // compute NTLM2 session response    PRUint8 sessionHash[16], temp[16];    PK11_GenerateRandom(lmResp, 8);    memset(lmResp + 8, 0, LM_RESP_LEN - 8);    memcpy(temp, msg.challenge, 8);    memcpy(temp + 8, lmResp, 8);    md5sum(temp, 16, sessionHash);    NTLM_Hash(password, ntlmHash);    LM_Response(ntlmHash, sessionHash, ntlmResp);  }  else  {    PRUint8 lmHash[LM_HASH_LEN];    LM_Hash(password, lmHash);    LM_Response(lmHash, msg.challenge, lmResp);    NTLM_Hash(password, ntlmHash);    LM_Response(ntlmHash, msg.challenge, ntlmResp);  }  //  // finally, we assemble the Type-3 msg :-)  //  void *cursor = *outBuf;  PRUint32 offset;  // 0 : signature  cursor = WriteBytes(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE));  // 8 : marker  cursor = WriteBytes(cursor, NTLM_TYPE3_MARKER, sizeof(NTLM_TYPE3_MARKER));  // 12 : LM response sec buf  offset = NTLM_TYPE3_HEADER_LEN + domainLen + userLen + hostLen;  cursor = WriteSecBuf(cursor, LM_RESP_LEN, offset);  memcpy((PRUint8 *) *outBuf + offset, lmResp, LM_RESP_LEN);  // 20 : NTLM response sec buf  offset += LM_RESP_LEN;  cursor = WriteSecBuf(cursor, NTLM_RESP_LEN, offset);  memcpy((PRUint8 *) *outBuf + offset, ntlmResp, NTLM_RESP_LEN);  // 28 : domain name sec buf  offset = NTLM_TYPE3_HEADER_LEN;  cursor = WriteSecBuf(cursor, domainLen, offset);  memcpy((PRUint8 *) *outBuf + offset, domainPtr, domainLen);  // 36 : user name sec buf  offset += domainLen;  cursor = WriteSecBuf(cursor, userLen, offset);  memcpy((PRUint8 *) *outBuf + offset, userPtr, userLen);  // 44 : workstation (host) name sec buf  offset += userLen;  cursor = WriteSecBuf(cursor, hostLen, offset);  memcpy((PRUint8 *) *outBuf + offset, hostPtr, hostLen);  // 52 : session key sec buf (not used)  offset += (hostLen + LM_RESP_LEN + NTLM_RESP_LEN);  cursor = WriteSecBuf(cursor, 0, offset);  // 60 : negotiated flags  cursor = WriteDWORD(cursor, msg.flags & NTLM_TYPE1_FLAGS);  return NS_OK;}