Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

818 lines
26 KiB

  1. /***************************************************************************
  2. Name : BCNSF.C
  3. Comment : Routines for encoding/encrypting and decoding/decrypting
  4. NSF/NSC/NSS frames
  5. Copyright (c) 1993 Microsoft Corp.
  6. This source code is absolutely confidential, and cannot be viewed
  7. by anyone outside Microsoft (even under NDA) without specific
  8. written permission.
  9. Revision Log
  10. Num Date Name Description
  11. --- -------- ---------- -----------------------------------------------
  12. ***************************************************************************/
  13. #ifdef PUREDATA
  14. #include <memory.h>
  15. #include <string.h>
  16. #define PORTABLE
  17. #define EXTERNAL
  18. #define NOGETTICK
  19. #endif
  20. #ifndef PORTABLE
  21. # include "defs.h"
  22. # include <ifaxos.h>
  23. # include "tipes.h"
  24. # define MODID MODID_AWNSF
  25. # define FILEID 1
  26. #else
  27. #ifdef DEBUG
  28. # include <assert.h>
  29. # include <string.h>
  30. #endif
  31. # define _export
  32. # define FALSE 0
  33. # define TRUE 1
  34. # define min(a,b) (((a) < (b)) ? (a) : (b))
  35. # ifdef DEBUG
  36. # define DEBUGMSG(cond,exp) ((cond)?((printf exp),1):0)
  37. # define BG_CHK(x) (fflush(stdout), assert(x))
  38. # else
  39. # define DEBUGMSG(cond,exp)
  40. # define BG_CHK(x)
  41. # endif
  42. # define _fmemset memset
  43. # define _fmemcpy memcpy
  44. # define _fstrlen strlen
  45. # define _fmemcmp memcmp
  46. # define ERRMSG(m) DEBUGMSG(1, m)
  47. #endif
  48. #include "prep.h"
  49. #include "nsfmacro.h"
  50. ///RSL
  51. #include "glbproto.h"
  52. #ifdef NOCHALL
  53. #define bChallResp bPass
  54. #define wChallRespLen wPassLen
  55. #endif
  56. /***********************************************************************
  57. * *
  58. * NOTICE: This file has to be ANSI compilable, under GCC on UNIX *
  59. * and other ANSI compiles. Be sure to use no MS C specific features *
  60. * In particular, don't use // for comments!!!! *
  61. * *
  62. ***********************************************************************/
  63. /* #define DEBUG2 */
  64. /* #define DEBUG3 */
  65. #define SZMOD "AwNsf: "
  66. #define TRACE(m) DEBUGMSG(1, m)
  67. #ifdef DEBUG
  68. # define DEBUGSTMT(x) x
  69. #else
  70. # define DEBUGSTMT(x) (0)
  71. #endif
  72. #ifdef DEBUG2
  73. # define faxTlog(m) DEBUGMSG(1, m)
  74. #else
  75. # define faxTlog(m)
  76. #endif
  77. #ifdef DEBUG3
  78. # define faxT3log(m) DEBUGMSG(1, m)
  79. #else
  80. # define faxT3log(m)
  81. #endif
  82. typedef char FAR* LPSTR;
  83. typedef unsigned long ULONG;
  84. #ifdef DEBUG
  85. void D_PrintBytes(LPSTR lpstr, LPBYTE lpb, USHORT cb, BOOL f);
  86. void DiffIt(PThrdGlbl pTG, LPBYTE lpb1, LPBYTE lpb2, USHORT cb);
  87. #else
  88. # define D_PrintBytes(lpstr, lpb, cb, f)
  89. # define DiffIt(lpb1, lpb2, cb)
  90. #endif
  91. LPBYTE Permute(PThrdGlbl pTG, LPBYTE lpbIn, USHORT cb, BOOL fReverse);
  92. USHORT ParseNSx(PThrdGlbl pTG, LPBYTE lpb, USHORT uLen, LPBC lpbcOut, USHORT uMaxSize);
  93. BOOL EXPORTAWBC IsAtWorkNSx( LPBYTE lpb, WORD wSize)
  94. {
  95. BG_CHK((GRPSIZE_STD==sizeof(BCSTD)) &&
  96. (GRPSIZE_FAX==sizeof(BCFAX)) &&
  97. (GRPSIZE_NSS==sizeof(BCNSS)) &&
  98. (GRPSIZE_IMAGE==sizeof(BCIMAGE)) &&
  99. (GRPSIZE_POLLCAPS==sizeof(BCPOLLCAPS)));
  100. /* this should be tautological */
  101. #ifdef DEBUG
  102. #ifdef PORTABLE
  103. BG_CHK(BC_SIZE == (sizeof(BCwithHUGE)-BCEXTRA_HUGE-4));
  104. faxT3log(("BC_SIZE=%d actual=%d\r\n", BC_SIZE, (sizeof(BCwithHUGE)-BCEXTRA_HUGE-4)));
  105. #else
  106. BG_CHK(BC_SIZE == sizeof(BC));
  107. faxT3log(("BC_SIZE=%d sizeof(BC)=%d\r\n", BC_SIZE, sizeof(BC)));
  108. #endif /* PORTABLE */
  109. #endif /* DEBUG */
  110. if( (wSize > 3) && (wSize < MAXNSFFRAMESIZE) &&
  111. (lpb[0]==SIG_USA) &&
  112. (lpb[1]==SIG_ATWORK1) &&
  113. (lpb[2]==SIG_ATWORK2) )
  114. {
  115. return TRUE;
  116. }
  117. else
  118. {
  119. (MyDebugPrint(0, LOG_ALL, "Non-Microsoft At Work NSx l=%d (%02x %02x %02x)\r\n",
  120. wSize, lpb[0], lpb[1], lpb[2]));
  121. return FALSE;
  122. }
  123. }
  124. WORD EXPORTBC NSxtoBC(PThrdGlbl pTG, IFR ifr, LPLPFR rglpfr, WORD wNumFrame,
  125. LPBC lpbcOut, WORD wBCSize)
  126. {
  127. BYTE bSalt[3];
  128. BOOL fGotSalt;
  129. WORD wRet = AWERROR_NOTAWFRAME;
  130. USHORT iFrame;
  131. BOOL fStripFCS = TRUE;
  132. BG_CHK(ifr==ifrNSF || ifr==ifrNSS || ifr==ifrNSC);
  133. tryagain:
  134. fGotSalt = FALSE;
  135. /* zero out BC, but _not_ header parts */
  136. _fmemset(&(lpbcOut->Std),
  137. 0,
  138. BC_SIZE - (ULONG)(((LPBYTE)(&(lpbcOut->Std))) - ((LPBYTE)lpbcOut)));
  139. lpbcOut->wTotalSize = BC_SIZE;
  140. fGotSalt = FALSE;
  141. for(iFrame=0; iFrame<wNumFrame; iFrame++)
  142. {
  143. LPBYTE lpbIn;
  144. USHORT uLen;
  145. LPBYTE lpbTemp;
  146. lpbIn = rglpfr[iFrame]->fif;
  147. if (fStripFCS)
  148. {
  149. if (rglpfr[iFrame]->cb >= 5 ) {
  150. uLen = rglpfr[iFrame]->cb - 2; /* Subtract 2 to lop off the FCS */
  151. }
  152. else
  153. { /* Must not have the FCS */
  154. fStripFCS = FALSE;
  155. (MyDebugPrint(pTG, LOG_ALL, "<<<WRN>>> NSx frame too short, trying again without stripping FCS\r\n"));
  156. goto tryagain;
  157. }
  158. }
  159. else
  160. uLen = rglpfr[iFrame]->cb;
  161. if(!IsAtWorkNSx(lpbIn, uLen))
  162. {
  163. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> skipping non-MAW-NSx frame (%d)\r\n", iFrame));
  164. DEBUGSTMT(D_PrintBytes("SkippedFrame", lpbIn, uLen, 0));
  165. goto skipframe;
  166. }
  167. else
  168. {
  169. USHORT uRet1;
  170. DEBUGSTMT(D_PrintBytes("BytesRecvd", lpbIn, uLen, 0));
  171. BG_CHK(uLen > 3);
  172. uLen -= 3;
  173. lpbIn += 3;
  174. /** unswap salt/data bytes around (except the NSF signature) **/
  175. lpbTemp = Permute(pTG, lpbIn, uLen, TRUE);
  176. DEBUGSTMT(D_PrintBytes("AfterPermute", lpbTemp, uLen, 0));
  177. if(!fGotSalt)
  178. {
  179. BG_CHK(wRet == AWERROR_NOTAWFRAME); /* not yet parsed a frame */
  180. /* Snowball can't handle NSF frames longer than 38 bytes */
  181. BG_CHK((ifr==ifrNSF) ? (uLen <= (MAXFIRSTNSFSIZE-3)) : TRUE);
  182. if(uLen < 3)
  183. {
  184. (MyDebugPrint(pTG, LOG_ERR, "SZMOD <<WARNING>> skipping too-short MAW frame (%d) len=%d\r\n", iFrame, uLen));
  185. goto skipframe;
  186. }
  187. _fmemcpy(bSalt, lpbTemp, 3);
  188. lpbTemp += 3;
  189. uLen -= 3;
  190. fGotSalt = TRUE;
  191. }
  192. DEBUGSTMT(D_PrintBytes("AfterDecrypt", lpbTemp, uLen, 0));
  193. if((uRet1=ParseNSx(pTG, lpbTemp, uLen, lpbcOut, wBCSize))==0xFFFF)
  194. {
  195. /* Some modems don't send the FCS, so if we fail, try again without lopping off the FCS */
  196. if ((fStripFCS) && (iFrame==0)) {
  197. fStripFCS = FALSE;
  198. (MyDebugPrint(pTG, LOG_ALL, "<<<WRN>>> Failed to parse NSx frame, trying again without stripping FCS\r\n"));
  199. goto tryagain;
  200. }
  201. else {
  202. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Failed to parse NSx frame (%d)\r\n", iFrame));
  203. goto skipframe;
  204. }
  205. }
  206. else
  207. {
  208. wRet = AWERROR_OK;
  209. (MyDebugPrint(pTG, LOG_ALL, "Parsed NSx frame (%d) skipped %d\r\n", iFrame, uRet1));
  210. }
  211. }
  212. skipframe:
  213. ;
  214. }
  215. return wRet;
  216. }
  217. USHORT CopyGroupFromFrame(PThrdGlbl pTG, LPBYTE lpbHdrIn, USHORT cbOut, LPBYTE lpbOut)
  218. {
  219. USHORT uCopyLen;
  220. uCopyLen = min(GroupLength(lpbHdrIn), cbOut);
  221. _fmemset(lpbOut, 0, cbOut);
  222. _fmemcpy(lpbOut, lpbHdrIn, uCopyLen);
  223. SetGroupLength(lpbHdrIn, uCopyLen);
  224. return uCopyLen;
  225. }
  226. USHORT CopyIdGroupFromFrame(PThrdGlbl pTG, LPBYTE lpbHdrIn, LPBYTE lpbOut, USHORT cbMaxOut)
  227. {
  228. USHORT uCopyLen;
  229. uCopyLen = min(GroupLength(lpbHdrIn)-2, cbMaxOut-1);
  230. _fmemcpy(lpbOut, lpbHdrIn+2, uCopyLen); /** copy id only! **/
  231. lpbOut[uCopyLen++] = 0;
  232. return uCopyLen;
  233. }
  234. /** returns 0xFFFF on failure and 0 or +ve number == total number
  235. of bytes skipped in "not understood" or "no-space" groups. **/
  236. USHORT ParseNSx(PThrdGlbl pTG, LPBYTE lpb, USHORT uLen, LPBC lpbcOut, USHORT uMaxSize)
  237. {
  238. USHORT uGroupLength;
  239. USHORT uRet, uLenOriginal;
  240. BG_CHK(uMaxSize >= BC_SIZE);
  241. /*** Don't zero BC here! This can be called multiple times to decode
  242. multiple NSx frames into a single BC structure! **/
  243. uRet = 0;
  244. uLenOriginal = uLen;
  245. // RSL
  246. return (uRet);
  247. while(uLen)
  248. {
  249. uGroupLength = GroupLength(lpb);
  250. if(uGroupLength < 2 || uGroupLength > uLen)
  251. {
  252. /** If we hit a garbage group-len, we can't continue **/
  253. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Bad NSF format GroupLen=%d wLen=%d\r\n", uGroupLength, uLen));
  254. return 0xFFFF;
  255. }
  256. switch(GroupNum(lpb))
  257. {
  258. case GROUPNUM_STD:
  259. CopyGroupFromFrame(pTG, lpb, GRPSIZE_STD, (LPBYTE)(&(lpbcOut->Std)));
  260. break;
  261. case GROUPNUM_TEXTID:
  262. if(lpbcOut->wTotalSize < uMaxSize)
  263. {
  264. lpbcOut->wszTextId = lpbcOut->wTotalSize;
  265. lpbcOut->wTextEncoding = TextEncoding( (LPBC)lpb);
  266. lpbcOut->wTextIdLen = CopyIdGroupFromFrame(pTG, lpb, (((LPBYTE)lpbcOut) + lpbcOut->wTotalSize), (USHORT)(uMaxSize - lpbcOut->wTotalSize));
  267. lpbcOut->wTotalSize += lpbcOut->wTextIdLen;
  268. lpbcOut->wTextIdLen--; /** trailing 0 not included in length **/
  269. BG_CHK(lpbcOut->wTotalSize <= uMaxSize);
  270. }
  271. else
  272. {
  273. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> No space for Text Id wSize=%d wMax=%d\r\n", lpbcOut->wTotalSize, uMaxSize));
  274. uRet += uGroupLength;
  275. }
  276. break;
  277. case GROUPNUM_MACHINEID:
  278. if(lpbcOut->wTotalSize < uMaxSize)
  279. {
  280. lpbcOut->wrgbMachineId = lpbcOut->wTotalSize;
  281. lpbcOut->wMachineIdLen = CopyIdGroupFromFrame(pTG, lpb, (((LPBYTE)lpbcOut) + lpbcOut->wTotalSize), (USHORT)(uMaxSize - lpbcOut->wTotalSize));
  282. lpbcOut->wTotalSize += lpbcOut->wMachineIdLen;
  283. lpbcOut->wMachineIdLen--; /** trailing 0 not included in length **/
  284. BG_CHK(lpbcOut->wTotalSize <= uMaxSize);
  285. }
  286. else
  287. {
  288. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> No space for Machine Id wSize=%d wMax=%d\r\n", lpbcOut->wTotalSize, uMaxSize));
  289. uRet += uGroupLength;
  290. }
  291. break;
  292. case GROUPNUM_IMAGE:
  293. CopyGroupFromFrame(pTG, lpb, GRPSIZE_IMAGE, (LPBYTE)(&(lpbcOut->Image)));
  294. break;
  295. case GROUPNUM_POLLCAPS:
  296. CopyGroupFromFrame(pTG, lpb, GRPSIZE_POLLCAPS, (LPBYTE)(&(lpbcOut->PollCaps)));
  297. break;
  298. case GROUPNUM_POLLREQ:
  299. if((lpbcOut->wNumPollReq > MAXNSCPOLLREQ) || (lpbcOut->wTotalSize >= uMaxSize))
  300. {
  301. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> No space for PollReq wNum=%d wSize=%d wMax=%d\r\n", lpbcOut->wNumPollReq, lpbcOut->wTotalSize, uMaxSize));
  302. uRet += uGroupLength;
  303. }
  304. else
  305. {
  306. USHORT uTemp;
  307. lpbcOut->rgwPollReq[lpbcOut->wNumPollReq] = lpbcOut->wTotalSize;
  308. uTemp = CopyGroupFromFrame(pTG, lpb, (USHORT)(uMaxSize-1-lpbcOut->wTotalSize), (((LPBYTE)lpbcOut) + lpbcOut->wTotalSize));
  309. (((LPBYTE)lpbcOut) + lpbcOut->wTotalSize)[uTemp++] = 0;
  310. lpbcOut->wTotalSize += uTemp;
  311. lpbcOut->wNumPollReq++;
  312. }
  313. break;
  314. case GROUPNUM_NSS:
  315. CopyGroupFromFrame(pTG, lpb, GRPSIZE_NSS, (LPBYTE)(&(lpbcOut->NSS)));
  316. faxT3log((SZMOD "ParseNSS: Msg=0x%02x Inter=0x%02x\r\n",
  317. lpbcOut->NSS.vMsgProtocol, lpbcOut->NSS.vInteractive));
  318. break;
  319. default:
  320. (MyDebugPrint(pTG, LOG_ALL, "<<WARNING>> Got unknown %d member (size=%d) in NSF -- ignoring\r\n",
  321. GroupNum(lpb), uGroupLength));
  322. uRet += uGroupLength;
  323. break;
  324. }
  325. (MyDebugPrint(pTG, LOG_ALL, "Decoded grp=%d len=%d\r\n", GroupNum(lpb), uGroupLength));
  326. lpb += uGroupLength;
  327. uLen -= uGroupLength;
  328. }
  329. if(uRet == uLenOriginal)
  330. {
  331. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> Skipped over entire frame!\r\n"));
  332. uRet = 0xFFFF;
  333. }
  334. return uRet;
  335. }
  336. USHORT AddGroupToFrame(PThrdGlbl pTG, LPBYTE lpbIn, USHORT cbIn, LPBYTE lpbOut, USHORT cbOut)
  337. {
  338. USHORT uGroupNum, uGroupLength, cbCopy;
  339. BG_CHK(cbIn>=2 && cbIn<64);
  340. BG_CHK(cbOut >= 2);
  341. uGroupNum = GroupNum(lpbIn);
  342. uGroupLength = GroupLength(lpbIn);
  343. faxT3log((SZMOD "cbIn=%d cbOut=%d grplen=%d\r\n", cbIn, cbOut, uGroupLength));
  344. if( uGroupNum >= GROUPNUM_FIRST &&
  345. uGroupNum <= GROUPNUM_LAST
  346. && uGroupLength && cbIn>=2 && cbIn<64 && cbOut>=2)
  347. {
  348. BG_CHK(uGroupLength <= cbIn);
  349. cbIn = min(uGroupLength, cbIn);
  350. if(uGroupNum != GROUPNUM_MACHINEID && uGroupNum != GROUPNUM_POLLREQ)
  351. {
  352. /** find last non-zero byte **/
  353. for( ;cbIn>2 && lpbIn[cbIn-1]==0; cbIn--)
  354. ;
  355. BG_CHK(cbIn==2 || lpbIn[cbIn-1]!=0);
  356. if(cbIn==2 && (lpbIn[1] == (lpbIn[1] & 0x07)))
  357. {
  358. (MyDebugPrint(pTG, LOG_ALL, "Found Group (%d %d) only 11bits long. Not sending\r\n", lpbIn[0], lpbIn[1]));
  359. return 0;
  360. }
  361. }
  362. BG_CHK(cbIn>=2 && cbIn<=63);
  363. cbCopy = min(cbIn, cbOut);
  364. _fmemcpy(lpbOut, lpbIn, cbCopy);
  365. SetGroupLength(lpbOut, cbCopy); /** set GroupLength correctly **/
  366. (MyDebugPrint(pTG, LOG_ALL, "Encoded grp=%d len=%d\r\n", GroupNum(lpbOut), GroupLength(lpbOut)));
  367. return cbCopy;
  368. }
  369. BG_CHK(uGroupNum == 0);
  370. BG_CHK(uGroupLength == 0);
  371. return 0;
  372. }
  373. USHORT AddIdGroupToFrame(PThrdGlbl pTG, USHORT uGroupNum, USHORT cbIn, USHORT uTextEncoding, LPBYTE lpbIn, LPBYTE lpbOut, USHORT cbOut)
  374. {
  375. USHORT cbCopy;
  376. /** if(!cbIn) cbIn = _fstrlen((LPSTR)lpbIn); **/
  377. BG_CHK(cbIn>0);
  378. BG_CHK(cbIn<=MAXTOTALIDLEN);
  379. BG_CHK(cbOut >= 2);
  380. BG_CHK(uGroupNum==GROUPNUM_TEXTID || uGroupNum==GROUPNUM_MACHINEID);
  381. if( (uGroupNum==GROUPNUM_TEXTID || uGroupNum==GROUPNUM_MACHINEID) &&
  382. cbIn>0 && cbIn<=MAXTOTALIDLEN && cbOut>=2)
  383. {
  384. cbCopy = min(cbIn, cbOut-2);
  385. _fmemcpy(lpbOut+2, lpbIn, cbCopy);
  386. SetupTextIdHdr(lpbOut, cbCopy+2, uGroupNum, uTextEncoding);
  387. (MyDebugPrint(pTG, LOG_ALL, "Encoded grp=%d len=%d\r\n", GroupNum(lpbOut), GroupLength(lpbOut)));
  388. return cbCopy+2;
  389. }
  390. return 0;
  391. }
  392. WORD CreateNewFrame(PThrdGlbl pTG, IFR ifr, LPFR lpfr, WORD wMaxOut, BOOL fFirst)
  393. {
  394. BYTE bSendSalt[4];
  395. if(wMaxOut <= (sizeof(FRBASE)+3 + (fFirst ? 3 : 0)))
  396. return 0;
  397. lpfr->ifr = ifr;
  398. lpfr->fif[0] = SIG_USA;
  399. lpfr->fif[1] = SIG_ATWORK1;
  400. lpfr->fif[2] = SIG_ATWORK2;
  401. lpfr->cb = 3;
  402. if(fFirst)
  403. {
  404. DWORD lTemp;
  405. lTemp = 1; /* get random salt */
  406. _fmemcpy(bSendSalt, (LPBYTE)(&lTemp), 3); /* don't care if we get low 3 or high 3 */
  407. _fmemcpy(lpfr->fif+lpfr->cb, bSendSalt, 3); /* only low 3 bytes of salt sent **/
  408. lpfr->cb += 3;
  409. }
  410. return lpfr->cb;
  411. }
  412. /** Make sure lpilpfr always points to _current_ lpfr entry **/
  413. BOOL AddToFrames(PThrdGlbl pTG, IFR ifr, LPLPFR rglpfr, LPWORD lpilpfr, LPBYTE lpbGrp, WORD grpsize, LPWORD lpwMaxOut, BOOL fID, WORD GrpNum, WORD TextEncoding)
  414. {
  415. LPFR lpfr;
  416. USHORT uTemp;
  417. redo:
  418. lpfr = rglpfr[*lpilpfr];
  419. BG_CHK(lpfr);
  420. if(*lpwMaxOut < grpsize) return FALSE;
  421. if(!fID)
  422. uTemp = AddGroupToFrame(pTG, lpbGrp, grpsize, lpfr->fif+lpfr->cb, *lpwMaxOut);
  423. else
  424. uTemp = AddIdGroupToFrame(pTG, GrpNum, grpsize, TextEncoding, lpbGrp, lpfr->fif+lpfr->cb, *lpwMaxOut);
  425. if((int)(lpfr->cb+uTemp) > (((*lpilpfr==0) && (ifr==ifrNSF)) ? MAXFIRSTNSFSIZE : MAXNEXTNSFSIZE))
  426. {
  427. WORD wTemp;
  428. if((*lpilpfr)+1 >= MAXNSFFRAMES)
  429. return FALSE;
  430. lpfr = (LPFR) (((LPBYTE)(lpfr->fif))+lpfr->cb);
  431. if(!(wTemp = CreateNewFrame(pTG, ifr, lpfr, *lpwMaxOut, FALSE)))
  432. return FALSE;
  433. BG_CHK(*lpwMaxOut >= wTemp);
  434. *lpwMaxOut -= wTemp;
  435. (*lpilpfr) += 1;
  436. rglpfr[*lpilpfr] = lpfr; \
  437. goto redo;
  438. }
  439. lpfr->cb += uTemp;
  440. *lpwMaxOut -= uTemp;
  441. return TRUE;
  442. }
  443. WORD EXPORTBC BCtoNSx(PThrdGlbl pTG, IFR ifr, LPBC lpbcIn,
  444. LPBYTE lpbOut, WORD wMaxOut, LPWORD lpwNumFrame)
  445. {
  446. LPLPFR rglpfr;
  447. USHORT ilpfr, i;
  448. LPFR lpfr;
  449. WORD wTemp;
  450. LPBYTE lpbTemp;
  451. BG_CHK(ifr==ifrNSF || ifr==ifrNSS || ifr==ifrNSC);
  452. BG_CHK(lpbcIn->wTotalSize >= BC_SIZE);
  453. BG_CHK(lpbcIn->bctype==SEND_CAPS || lpbcIn->bctype==SEND_PARAMS ||
  454. lpbcIn->bctype==SEND_POLLREQ || lpbcIn->bctype==RECV_CAPS);
  455. /* server-->client cap reporting passes in a RECV_CAPS */
  456. DEBUGSTMT(D_PrintBytes("SendBC", (LPBYTE)lpbcIn, lpbcIn->wTotalSize, 0));
  457. /* init return values */
  458. _fmemset(lpbOut, 0, wMaxOut);
  459. *lpwNumFrame = 0;
  460. /* set up array of LPFR pointers */
  461. if(wMaxOut <= (sizeof(LPFR) * MAXNSFFRAMES)) goto nospace;
  462. rglpfr = (LPLPFR)lpbOut;
  463. ilpfr = 0;
  464. lpbOut += (sizeof(LPFR) * MAXNSFFRAMES);
  465. wMaxOut -= (sizeof(LPFR) * MAXNSFFRAMES);
  466. lpfr = (LPFR)lpbOut;
  467. if(!(wTemp = CreateNewFrame(pTG, ifr, lpfr, wMaxOut, TRUE)))
  468. goto nospace;
  469. BG_CHK(wMaxOut >= wTemp);
  470. wMaxOut -= wTemp;
  471. rglpfr[ilpfr] = lpfr;
  472. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, (LPBYTE)(&(lpbcIn->NSS)), GRPSIZE_NSS, &wMaxOut, 0,0,0))
  473. goto nospace;
  474. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, (LPBYTE)(&(lpbcIn->Std)), GRPSIZE_STD, &wMaxOut, 0,0,0))
  475. goto nospace;
  476. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, (LPBYTE)(&(lpbcIn->Image)), GRPSIZE_IMAGE, &wMaxOut, 0,0,0))
  477. goto nospace;
  478. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, (LPBYTE)(&(lpbcIn->PollCaps)), GRPSIZE_POLLCAPS, &wMaxOut, 0,0,0))
  479. goto nospace;
  480. #if !defined(EXTERNAL) || defined(TEST)
  481. if(lpbcIn->wszTextId)
  482. {
  483. BG_CHK(lpbcIn->wszTextId < lpbcIn->wTotalSize);
  484. BG_CHK(lpbcIn->wTextIdLen);
  485. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, (((LPBYTE)lpbcIn) + lpbcIn->wszTextId),
  486. lpbcIn->wTextIdLen, &wMaxOut, TRUE, GROUPNUM_TEXTID, lpbcIn->wTextEncoding))
  487. goto nospace;
  488. }
  489. if(lpbcIn->wrgbMachineId)
  490. {
  491. BG_CHK(lpbcIn->wrgbMachineId < lpbcIn->wTotalSize);
  492. BG_CHK(lpbcIn->wMachineIdLen);
  493. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, (((LPBYTE)lpbcIn) + lpbcIn->wrgbMachineId),
  494. lpbcIn->wMachineIdLen, &wMaxOut, TRUE, GROUPNUM_MACHINEID, 0))
  495. goto nospace;
  496. }
  497. for(i=0; i<lpbcIn->wNumPollReq; i++)
  498. {
  499. LPBYTE lpGrp;
  500. USHORT uGrpLen;
  501. lpGrp = (((LPBYTE)lpbcIn) + lpbcIn->rgwPollReq[i]);
  502. uGrpLen = GroupLength(lpGrp);
  503. if(!AddToFrames(pTG, ifr, rglpfr, &ilpfr, lpGrp, uGrpLen, &wMaxOut, 0,0,0))
  504. goto nospace;
  505. }
  506. #endif /* !EXTERNAL || TEST */
  507. /** done with last frame. Increment ilpfr **/
  508. ilpfr += 1;
  509. for(i=0; i<ilpfr; i++)
  510. {
  511. USHORT uMin;
  512. (MyDebugPrint(pTG, LOG_ALL, "Frame %d of %d. Len=%d\r\n", i, ilpfr, rglpfr[i]->cb));
  513. DEBUGSTMT(D_PrintBytes("BeforeEncrypt", rglpfr[i]->fif, rglpfr[i]->cb, 0));
  514. uMin = (i ? 3 : 6); /* first frame must have sig + salt = 3+3 */
  515. if (0) /// RSL (rglpfr[i]->cb < uMin+2)
  516. {
  517. /** has to have at least 3 + (3) + 2 bytes **/
  518. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>> Empty frame\r\n"));
  519. /* zap return values so the bogus frame doesnt get used */
  520. _fmemset(lpbOut, 0, wMaxOut);
  521. *lpwNumFrame = 0;
  522. return AWERROR_NULLFRAME;
  523. }
  524. DEBUGSTMT(D_PrintBytes("AfterEncrypt", rglpfr[i]->fif, rglpfr[i]->cb, 0));
  525. /** swap salt/data bytes around **/
  526. lpbTemp = Permute(pTG, rglpfr[i]->fif+3, (USHORT)(rglpfr[i]->cb-3), FALSE);
  527. _fmemcpy(rglpfr[i]->fif+3, lpbTemp, rglpfr[i]->cb-3);
  528. DEBUGSTMT(D_PrintBytes("AfterPermute", rglpfr[i]->fif, rglpfr[i]->cb, 0));
  529. }
  530. BG_CHK(wMaxOut >= 0);
  531. *lpwNumFrame = ilpfr;
  532. return 0;
  533. nospace:
  534. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> no space\r\n"));
  535. /* zap return values so the bogus frame(s) dont get used */
  536. _fmemset(lpbOut, 0, wMaxOut);
  537. *lpwNumFrame = 0;
  538. return AWERROR_NOSPACE;
  539. }
  540. LPBYTE Permute(PThrdGlbl pTG, LPBYTE lpbIn, USHORT cb, BOOL fReverse)
  541. {
  542. USHORT v, n, i, choice;
  543. LPBYTE lpbOut=pTG->bOut;
  544. if(cb < 1 || cb > 255)
  545. {
  546. BG_CHK(FALSE);
  547. return 0;
  548. }
  549. v = lpbOut[0] = lpbIn[0]; /** anchor **/
  550. lpbOut++, lpbIn++; /** anchor **/
  551. cb--;
  552. for(i=0; i<MAXNSFFRAMESIZE; pTG->bRem[i]=(BYTE)i, i++)
  553. ;
  554. /** bOut[1] = bOut[2] = bOut[3] = bOut[4] = bOut[5] =' '; **/
  555. for(i=0, n=cb; n; n--, i++)
  556. {
  557. choice = v % n;
  558. if(!fReverse)
  559. {
  560. lpbOut[i] = lpbIn[pTG->bRem[choice]];
  561. v = (v / n) ^ lpbOut[i];
  562. }
  563. else
  564. {
  565. lpbOut[pTG->bRem[choice]] = lpbIn[i];
  566. v = (v / n) ^ lpbIn[i];
  567. }
  568. pTG->bRem[choice] = pTG->bRem[n-1];
  569. /** printf("%c%c%c%c%c%c\n\r",bOut[0],bOut[1],bOut[2],bOut[3],bOut[4],bOut[5]); **/
  570. }
  571. return lpbOut-1;
  572. }
  573. #ifdef DEBUG
  574. void D_PrintBytes(LPSTR lpstr, LPBYTE lpb, USHORT cb, BOOL fAlways)
  575. {
  576. USHORT i;
  577. #ifndef DEBUG2
  578. if(fAlways)
  579. #endif /** DEBUG2 **/
  580. {
  581. (MyDebugPrint(0, LOG_ALL, "[%s]\r\n", (LPSTR)lpstr));
  582. for(i=0; i<cb; i++)
  583. {
  584. TRACE(("%02x ", (USHORT)lpb[i]));
  585. if(((i+1) % 20) == 0)
  586. TRACE(("\r\n"));
  587. }
  588. TRACE(("\r\n"));
  589. }
  590. }
  591. #endif /** DEBUG **/
  592. #ifdef DEBUG
  593. void DiffIt(PThrdGlbl pTG, LPBYTE lpb1, LPBYTE lpb2, USHORT cb)
  594. {
  595. int i;
  596. TRACE(("DiffIt:\r\n"));
  597. for(i=0; i<(int)cb; i++)
  598. {
  599. if(lpb1[i] != lpb2[i])
  600. {
  601. TRACE(("(%d %02x %02x)\r\n", i, lpb1[i], lpb2[i]));
  602. }
  603. }
  604. }
  605. #endif