ntlmssp.cpp
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:26k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* ntlmssp.cpp - NT LM security implementation */
  2. /* Copyright (c) 1998 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01s,17dec01,nel  Add include symbol for diab.
  7. 01r,16jul01,dbs  fix unix-build includes
  8. 01q,13jul01,dbs  fix up includes
  9. 01p,09dec99,nel  SPR#33730. Merge T2 OPC fixes into T3 branch.
  10. 01o,09dec99,nel  Mods to DES routines
  11. 01n,19aug99,aim  change assert to VXDCOM_ASSERT
  12. 01m,05aug99,dbs  add mutex around channel-map
  13. 01l,19jul99,dbs  add more knowledge of packet layouts
  14. 01k,13jul99,aim  syslog api changes
  15. 01j,28jun99,dbs  remove defaultInstance method
  16. 01i,24jun99,dbs  implement more of NTLM protocol
  17. 01h,23jun99,dbs  create class for NTLM authn
  18. 01g,26may99,dbs  adding more knowledge of protocol
  19. 01f,26apr99,aim  added TRACE_CALL
  20. 01e,20apr99,dbs  grand renaming
  21. 01d,09apr99,drm  added diagnostic output
  22. 01c,11mar99,dbs  add more hooks for authentication
  23. 01b,02mar99,dbs  remove printf
  24. 01a,15feb99,dbs  created
  25. */
  26. #include <ctype.h>
  27. #include "ntlmssp.h"
  28. #include "SCM.h"
  29. #include "Syslog.h"
  30. #include "TraceCall.h"
  31. #include "private/comMisc.h"
  32. /* Include symbol for diab */
  33. extern "C" int include_vxdcom_ntlmssp (void)
  34.     {
  35.     return 0;
  36.     }
  37. //////////////////////////////////////////////////////////////////////////
  38. //
  39. // Class statics...
  40. //
  41. NTLMSSP::USERTABLE NTLMSSP::s_userTable;
  42. //////////////////////////////////////////////////////////////////////////
  43. BYTE NTLMSSP::s_token [16] =
  44.     { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  45. BYTE NTLMSSP::s_defaultChallenge [] = "GO AWAY";
  46. //////////////////////////////////////////////////////////////////////////
  47. const BYTE NTLMSSP::DES::lmKey [NTLMSSP::DES::lmKeySize] = 
  48.     {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
  49. const BYTE NTLMSSP::DES::pc1 [NTLMSSP::DES::pc1Size] =
  50.     {
  51.     57, 49, 41, 33, 25, 17,  9,
  52.     1, 58, 50, 42, 34, 26, 18,
  53.     10,  2, 59, 51, 43, 35, 27,
  54.     19, 11,  3, 60, 52, 44, 36,
  55.     63, 55, 47, 39, 31, 23, 15,
  56.     7, 62, 54, 46, 38, 30, 22,
  57.     14,  6, 61, 53, 45, 37, 29,
  58.     21, 13,  5, 28, 20, 12,  4
  59.     };
  60. const BYTE NTLMSSP::DES::pc2 [NTLMSSP::DES::pc2Size] =
  61.     {
  62.     14, 17, 11, 24,  1,  5,
  63.     3, 28, 15,  6, 21, 10,
  64.     23, 19, 12,  4, 26,  8,
  65.     16,  7, 27, 20, 13,  2,
  66.     41, 52, 31, 37, 47, 55,
  67.     30, 40, 51, 45, 33, 48,
  68.     44, 49, 39, 56, 34, 53,
  69.     46, 42, 50, 36, 29, 32
  70.     };
  71. const BYTE NTLMSSP::DES::e [NTLMSSP::DES::eSize] = 
  72.     {
  73.     32,  1,  2,  3,  4,  5,
  74.     4,  5,  6,  7,  8,  9,
  75.     8,  9, 10, 11, 12, 13,
  76.     12, 13, 14, 15, 16, 17,
  77.     16, 17, 18, 19, 20, 21,
  78.     20, 21, 22, 23, 24, 25,
  79.     24, 25, 26, 27, 28, 29,
  80.     28, 29, 30, 31, 32,  1
  81.     };
  82. const BYTE NTLMSSP::DES::p [NTLMSSP::DES::pSize] = 
  83.     {
  84.     16,  7, 20, 21,
  85.     29, 12, 28, 17,
  86.     1, 15, 23, 26,
  87.     5, 18, 31, 10,
  88.     2,  8, 24, 14,
  89.     32, 27,  3,  9,
  90.     19, 13, 30,  6,
  91.     22, 11,  4, 25
  92.     };
  93. const BYTE NTLMSSP::DES::ip1 [NTLMSSP::DES::ip1Size] =
  94.     {
  95.     40,  8, 48, 16, 56, 24, 64, 32,
  96.     39,  7, 47, 15, 55, 23, 63, 31,
  97.     38,  6, 46, 14, 54, 22, 62, 30,
  98.     37,  5, 45, 13, 53, 21, 61, 29,
  99.     36,  4, 44, 12, 52, 20, 60, 28,
  100.     35,  3, 43, 11, 51, 19, 59, 27,
  101.     34,  2, 42, 10, 50, 18, 58, 26,
  102.     33,  1, 41,  9, 49, 17, 57, 25
  103.     };
  104. const BYTE NTLMSSP::DES::ip [ipSize] =
  105.     {
  106.     58, 50, 42, 34, 26, 18, 10,  2,
  107.     60, 52, 44, 36, 28, 20, 12,  4,
  108.     62, 54, 46, 38, 30, 22, 14,  6,
  109.     64, 56, 48, 40, 32, 24, 16,  8,
  110.     57, 49, 41, 33, 25, 17,  9,  1,
  111.     59, 51, 43, 35, 27, 19, 11,  3,
  112.     61, 53, 45, 37, 29, 21, 13,  5,
  113.     63, 55, 47, 39, 31, 23, 15,  7
  114.     };
  115. const BYTE NTLMSSP::DES::noOfLeftShifts [NTLMSSP::DES::leftShiftSize] =
  116.     {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
  117. const BYTE NTLMSSP::DES::s [sSize][NTLMSSP::DES::sRowSize][NTLMSSP::DES::sColSize] =
  118.     {
  119.         {
  120.             {14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},
  121.             {0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},
  122.             {4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},
  123.             {15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13}
  124.         },
  125.         {
  126.             {15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10},
  127.             {3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5},
  128.             {0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15},
  129.             {13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9}
  130.         },
  131.         {
  132.             {10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8},
  133.             {13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1},
  134.             {13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7},
  135.             {1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12}
  136.         },
  137.         {
  138.             {7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15},
  139.             {13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9},
  140.             {10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4},
  141.             {3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14}
  142.         },
  143.         {
  144.             {2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9},
  145.             {14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6},
  146.             {4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14},
  147.             {11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3}
  148.         },
  149.         {
  150.             {12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11},
  151.             {10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8},
  152.             {9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6},
  153.             {4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13}
  154.         },
  155.         {
  156.             {4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1},
  157.             {13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6},
  158.             {1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2},
  159.             {6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12}
  160.         },
  161.         {
  162.             {13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7},
  163.             {1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2},
  164.             {7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},
  165.             {2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11}
  166.         }
  167.     };
  168. /////////////////////////////////////////////////////////////////////
  169. // 
  170. // Des :: doHash - produce encrypted data from encryption tables
  171. // 
  172. // This routine takes a key and input data and encypts it using the
  173. // DES algorithm.
  174. // 
  175. // RETURNS: nothing
  176. // 
  177. void NTLMSSP::DES::dohash
  178.     (
  179.     BYTE *          output, // encrypted data
  180.     const BYTE *    input,  // input data
  181.     const BYTE *    key     // encryption key
  182.     )
  183.     {
  184.     int     i;              // various counts
  185.     int     j;
  186.     int     k;
  187.     BYTE    fromPc1 [pc1Size];
  188.     BYTE    firstHalf [pc1Size / 2];
  189.     BYTE    secondHalf [pc1Size / 2];
  190.     BYTE    shiftedPc1 [pc1Size];
  191.     BYTE    fromPc2 [leftShiftSize][pc2Size];
  192.     BYTE    pIp [ipSize];
  193.     BYTE    pIpFirstHalf [ipSize / 2];
  194.     BYTE    pIpSecondHalf [ipSize / 2];
  195.     BYTE    fromIp [ipSize];
  196.     // permute pc1 with supplied key
  197.     permute(fromPc1, key, pc1, pc1Size);
  198.     for (i = 0; i < pc1Size / 2; i++)
  199.         firstHalf [i] = fromPc1 [i];
  200.     for (i = 0; i < pc1Size / 2; i++)
  201.         secondHalf [i] = fromPc1 [i + pc1Size / 2];
  202.     for ( i = 0; i < leftShiftSize; i++)
  203.         {
  204.         lshift(firstHalf, noOfLeftShifts [i], pc1Size / 2);
  205.         lshift(secondHalf, noOfLeftShifts [i], pc1Size / 2);
  206.         // merge two tables together for permute
  207.         memmove (shiftedPc1, firstHalf, pc1Size / 2);
  208.         memmove (shiftedPc1 + pc1Size / 2, secondHalf, pc1Size / 2);
  209.         permute(fromPc2 [i], shiftedPc1, pc2, pc2Size); 
  210.         }
  211.     permute(pIp, input, ip, ipSize);
  212.     for (j = 0; j < ipSize / 2; j++) 
  213.         {
  214.         pIpFirstHalf [j] = pIp [j];
  215.         pIpSecondHalf [j] = pIp [j + ipSize / 2];
  216.         }
  217.     for (i = 0; i < leftShiftSize; i++) 
  218.         {
  219.         BYTE pIpShE [eSize];
  220.         BYTE pIpShEx [eSize];
  221.         BYTE t [8][6];
  222.         BYTE reverseT [pSize];
  223.         BYTE reverseTp [pSize];
  224.         BYTE t2 [pSize];
  225.         int  x;                 // only use for block xor
  226.         permute(pIpShE, pIpSecondHalf, e, eSize);
  227.         for (x = 0; x < eSize; x++)
  228.             pIpShEx [x] = pIpShE [x] ^ fromPc2 [i][x];
  229.         for (j = 0; j < 8; j++)
  230.             {
  231.             for (k = 0; k < 6; k++)
  232.                 t [j][k] = pIpShEx [j * 6 + k];
  233.             }
  234.         for (j = 0; j < 8; j++) 
  235.             {
  236.             int m, n;
  237.             m = (t [j][0] << 1) | t [j][5];
  238.             n = (t [j][1] << 3) | (t [j][2] << 2) | (t [j][3] << 1) | t [j][4]; 
  239.             for (k = 0; k < 4; k++) 
  240.                 t [j][k] = (s [j][m][n] & (1 << (3 - k))) ? 1 : 0; 
  241.             }
  242.         for (j = 0; j < 8; j++)
  243.             {
  244.             for (k = 0; k < 4; k++)
  245.                 reverseT [j * 4 + k] = t [j][k];
  246.             }
  247.         permute(reverseTp, reverseT, p, pSize);
  248.         for (x = 0; x < pSize; x++)
  249.             t2 [x] = pIpFirstHalf [x] ^ reverseTp [x];
  250.         for (j = 0; j < ipSize / 2; j++)
  251.             pIpFirstHalf [j] = pIpSecondHalf [j];
  252.         for (j = 0; j < ipSize / 2; j++)
  253.             pIpSecondHalf [j] = t2 [j];
  254.     }
  255.     // merge two tables together for permute
  256.     memmove (fromIp, pIpSecondHalf, ipSize / 2);
  257.     memmove (fromIp + ipSize / 2, pIpFirstHalf, ipSize / 2);
  258.     permute(output, fromIp, ip1, ip1Size);
  259.     }
  260. /////////////////////////////////////////////////////////////////////
  261. // 
  262. // Des :: hash - prepares key for doHash and compresses resulting
  263. //               data into 64 bit value.
  264. // 
  265. // This routine is a wrapper routine around doHash. It modifies the
  266. // encryption key for use with doHash. It also compresses the resulting
  267. // table into 64 bits.
  268. // 
  269. // RETURNS: nothing
  270. // 
  271. void NTLMSSP::DES::hash 
  272.     (
  273.     BYTE *          output,    // encrypted result
  274.     const BYTE *    input,     // input data
  275.     const BYTE *    key        // encryption key
  276.     )
  277.     {
  278.     int             i;
  279.     BYTE            outputBuffer [bufferSize];
  280.     BYTE            inputBuffer [bufferSize];
  281.     BYTE            keyBuffer [bufferSize];
  282.     BYTE            encryptKey [keySize];
  283.     encryptKey [0] = key [0] >> 1;
  284.     encryptKey [1] = ((key [0] & 0x01) << 6) | (key [1] >> 2);
  285.     encryptKey [2] = ((key [1] & 0x03) << 5) | (key [2] >> 3);
  286.     encryptKey [3] = ((key [2] & 0x07) << 4) | (key [3] >> 4);
  287.     encryptKey [4] = ((key [3] & 0x0F) << 3) | (key [4] >> 5);
  288.     encryptKey [5] = ((key [4] & 0x1F) << 2) | (key [5] >> 6);
  289.     encryptKey [6] = ((key [5] & 0x3F) << 1) | (key [6] >> 7);
  290.     encryptKey [7] = key [6] & 0x7F;
  291.     for (i = 0; i < 8; i++) 
  292.         {
  293.         encryptKey[i] = (encryptKey [i] <<1);
  294.         }
  295.     for (i = 0; i < 64; i++) 
  296.         {
  297.         // Load input and key buffers with cyclic repeat of encrypted key
  298.         inputBuffer [i] = 
  299.             (input [i / keySize] & (1 << (7 - (i % keySize)))) ? 1 : 0;
  300.         keyBuffer [i] = 
  301.             (encryptKey [i / keySize] & (1 << (7 - (i % keySize)))) ? 1 : 0;
  302.         // zero output buffer
  303.         outputBuffer [i] = 0;
  304.         }
  305.     dohash  (outputBuffer, 
  306.             const_cast<const BYTE *> (inputBuffer), 
  307.             const_cast<const BYTE *> (keyBuffer));
  308.     // zero first 8 bytes
  309.     for (i = 0; i < 8; i++) 
  310.         {
  311.         output [i] = 0;
  312.         }
  313.     // compress outputBuffer from 64 bytes to 64 bits
  314.     for (i = 0; i < 64; i++) 
  315.         {
  316.         if (outputBuffer [i])
  317.             output [i / 8] |= (1 << (7 - (i % 8)));
  318.         }
  319.     }
  320. //////////////////////////////////////////////////////////////////////////
  321. static void strupper (unsigned char *s)
  322.     {
  323.     while (*s)
  324. {
  325. if (islower (*s))
  326.     *s = toupper (*s);
  327. s++;
  328. }
  329.     }
  330. //////////////////////////////////////////////////////////////////////////
  331. //
  332. // NTLMSSP ctor -- establishes the authn and impersonation levels for
  333. // this particular instance...
  334. //
  335. NTLMSSP::NTLMSSP
  336.     (
  337.     DWORD authnLvl, // the authentication level
  338.     DWORD impLvl // the impersonation level
  339.     )
  340.       : m_authnLevel (authnLvl),
  341. m_impLevel (impLvl)
  342.     {
  343.     if (m_authnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
  344. m_authnLevel = g_defaultAuthnLevel;
  345.     if (m_impLevel == RPC_C_IMP_LEVEL_DEFAULT)
  346. m_impLevel = g_defaultImpLevel;
  347.     }
  348. //////////////////////////////////////////////////////////////////////////
  349. //
  350. // NTLMSSP dtor...
  351. //
  352. NTLMSSP::~NTLMSSP ()
  353.     {
  354.     }
  355. //////////////////////////////////////////////////////////////////////////
  356. //
  357. // NTLMSSP::channelAdd -- adds an RPC-channel to the record, so its
  358. // status can be maintained when a client attempts to authenticate
  359. // over this channel...
  360. //
  361. void NTLMSSP::channelAdd (int cid)
  362.     {
  363.     // Default to ACCESS DENIED unless we are at lower level
  364.     HRESULT hrAuthn = E_ACCESSDENIED;
  365.     
  366.     if (m_authnLevel == RPC_C_AUTHN_LEVEL_NONE)
  367. hrAuthn = S_OK;
  368.     VxCritSec cs (m_mutex);
  369.     m_channelStatus [cid] = hrAuthn;
  370.     }
  371. //////////////////////////////////////////////////////////////////////////
  372. //
  373. // NTLMSSP::channelRemove -- removes a channel from the records...
  374. //
  375. void NTLMSSP::channelRemove (int cid)
  376.     {
  377.     VxCritSec cs (m_mutex);
  378.     m_channelStatus.erase (cid);
  379.     }
  380. //////////////////////////////////////////////////////////////////////////
  381. //
  382. // NTLMSSP::authTrailerCheck -- checks the auth-trailer of a received
  383. // PDU to ensure its requesting a authn-lvel we can cope with...
  384. //
  385. HRESULT NTLMSSP::authTrailerCheck
  386.     (
  387.     const RpcPdu& pdu // received PDU
  388.     )
  389.     {
  390.     // Make sure its NTLM protocol...
  391.     if (pdu.authTrailer()->authType != RPC_C_AUTHN_WINNT)
  392. return MAKE_HRESULT (SEVERITY_ERROR,
  393.      FACILITY_RPC,
  394.      RPC_S_UNKNOWN_AUTHN_SERVICE);
  395.     // Make sure its CONNECT-level authn being asked for...
  396.     if (pdu.authTrailer()->authLevel != RPC_C_AUTHN_LEVEL_CONNECT)
  397. return MAKE_HRESULT (SEVERITY_ERROR,
  398.      FACILITY_RPC,
  399.      RPC_S_UNSUPPORTED_AUTHN_LEVEL);
  400.     return S_OK;
  401.     }
  402. //////////////////////////////////////////////////////////////////////////
  403. //
  404. // NTLMSSP::serverRequestValidate -- validate the auth-trailer on a
  405. // received RPC REQUEST PDU, which usually contains the 16-byte
  406. // 'token' and nothing else...
  407. //
  408. HRESULT NTLMSSP::serverRequestValidate
  409.     (
  410.     int cid, // channel ID
  411.     const RpcPdu& reqPdu, // rcvd REQUEST packet 
  412.     RpcPdu& reply // reply to be sent
  413.     )
  414.     {
  415.     if (! reqPdu.isRequest ())
  416. return E_FAIL;
  417.     // Is there an auth-trailer?
  418.     if (reqPdu.authLen ())
  419. {
  420. rpc_cn_auth_tlr_t   authTlrOut;
  421. const rpc_cn_auth_tlr_t* pAuthTlrIn = reqPdu.authTrailer ();
  422. // Look for familiar token in REQUEST packets..
  423. if ((reqPdu.authLen () == TOKEN_LEN) &&
  424.     (memcmp (pAuthTlrIn->authValue, s_token, TOKEN_LEN) == 0))
  425.     {
  426.     // Set outbound pre-amble fields...
  427.     authTlrOut.authType = RPC_C_AUTHN_WINNT;
  428.     authTlrOut.authLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  429.     authTlrOut.stubPadLen = 0;
  430.     authTlrOut.reserved = 0;
  431.     authTlrOut.key = pAuthTlrIn->key;
  432.     // Copy 'token' into place...
  433.     memcpy (authTlrOut.authValue,
  434.     s_token,
  435.     TOKEN_LEN);
  436.     reply.authTrailerAppend (authTlrOut, TOKEN_LEN);
  437.     }
  438. }
  439.     
  440.     return S_OK;
  441.     }
  442. //////////////////////////////////////////////////////////////////////////
  443. //
  444. // serverBindValidate -- performs authentication checks on incoming
  445. // BIND (or ALTER-CONTEXT) PDUs received by a server connection. The
  446. // incoming PDU will contain the requesting machine and domain-name.
  447. //
  448. // Currently these fields are ignored, as we don't recognise NT
  449. // domains or do anything with them, so we simply respond by returning
  450. // a challenge. The difference between authenticating or not occurs
  451. // when the AUTH3 PDU arrives, which we process in the method
  452. // serverAuth3Validate().
  453. //
  454. // If we require authenticated connections, but we receive a BIND
  455. // without an auth-trailer, then it must also be rejected, as we
  456. // have been configured not to handle un-authenticated
  457. // connections. Conversely, if we don't *require* authentication, but
  458. // there is a request there in the packet, we still honour it by
  459. // adding a challenge, i.e. we move up to the client's level of authn,
  460. // but when his AUTH3 arrives we will simply accept it.
  461. //
  462. HRESULT NTLMSSP::serverBindValidate
  463.     (
  464.     int cid, // channel ID
  465.     const RpcPdu& bindPdu, // rcvd BIND packet
  466.     RpcPdu& reply // reply to be sent
  467.     )
  468.     {
  469.     TRACE_CALL;
  470.     // Only process BIND packets...
  471.     if (! (bindPdu.isBind ()))
  472. return E_FAIL;
  473.     // Get current status...
  474.     VxCritSec cs (m_mutex);
  475.     HRESULT status = m_channelStatus [cid];
  476.     
  477.     // Check what level we require...
  478.     switch (m_authnLevel)
  479. {
  480.     case RPC_C_AUTHN_LEVEL_NONE:
  481.     case RPC_C_AUTHN_LEVEL_CONNECT:
  482. // This case handles both NONE and CONNECT levels, but treats
  483. // NONE as a special case when a received BIND PDU has an
  484. // auth-trailer, in that we respond to it with a challenge
  485. // (just like we do when we require authentication), but we
  486. // effectively ignore the response in the next AUTH3 packet.
  487. //
  488. // CONNECT-level is supported if the user/application has
  489. // registered some user/password combinations, so we *do*
  490. // require some authentication to be present, so if there's
  491. // none, we reject the PDU.
  492. //
  493. // For CONNECT level, we must defer the status-change (to S_OK
  494. // from ACCESS-DENIED) to the time we get the response to our
  495. // challenge, whereas for the NONE case we can simply let the
  496. // connection continue at S_OK...
  497. if (m_authnLevel == RPC_C_AUTHN_LEVEL_CONNECT)
  498.     status = E_ACCESSDENIED;
  499. else
  500.     status = S_OK;
  501. // Now check there is a trailer to process...
  502. if (bindPdu.authLen ())
  503.     {
  504.     // Check the auth-trailer for correctness...
  505.     HRESULT hr = authTrailerCheck (bindPdu);
  506.     if (FAILED (hr))
  507. status = hr;
  508.     else
  509. {
  510. // Okay -- now we can go ahead and prepare the reply
  511. // trailer for sending the challenge...
  512.     
  513. rpc_cn_auth_tlr_t authTlrOut;
  514. size_t lenTlr=0;
  515. DREP drep = bindPdu.drep ();
  516. const rpc_cn_auth_tlr_t* pAuthTlrIn = bindPdu.authTrailer ();
  517.     
  518. // Set outbound pre-amble fields...
  519. authTlrOut.authType = RPC_C_AUTHN_WINNT;
  520. authTlrOut.authLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  521. authTlrOut.stubPadLen = 0;
  522. authTlrOut.reserved = 0;
  523. authTlrOut.key = pAuthTlrIn->key;
  524. // Find request and challenge structures in PDUs...
  525. request* preq = (request*) pAuthTlrIn->authValue;
  526. challenge* pch = (challenge*) authTlrOut.authValue;
  527.     
  528. // Find received sequence-number
  529. ULONG seq = preq->sequence;
  530. ndr_make_right (seq, drep);
  531.     
  532. // Normal client request -- fill in codename
  533. strcpy (pch->ntlmssp, "NTLMSSP");
  534. // Look for repeated sequence-number 3 in ALTER-CONTEXT PDUs. If
  535. // its one of these then we can get away without putting an
  536. // auth-trailer on the response, and continue...
  537. if ((seq == 3) &&
  538.     (bindPdu.packetType () == RPC_CN_PKT_ALTER_CONTEXT))
  539.     status = S_OK;
  540. else
  541.     {
  542.     // Increment sequence-number...
  543.     pch->sequence = seq + 1;
  544.     ndr_make_right (pch->sequence, drep);
  545.     // Fill in fields and NDR them
  546.     pch->magic1 = NTLM_MAGIC1;
  547.     ndr_make_right (pch->magic1, drep);
  548.     pch->magic2 = NTLM_MAGIC2_BIND;
  549.     ndr_make_right (pch->magic2, drep);
  550.     
  551.     memcpy (pch->chal, s_defaultChallenge, 8);
  552.     pch->mbz1 = 0;
  553.     pch->mbz2 = 0;
  554.     pch->mbz3 = 0;
  555.     lenTlr = sizeof (NTLMSSP::challenge);
  556.     reply.authTrailerAppend (authTlrOut, lenTlr);
  557.     }
  558. }
  559.     }
  560. break;
  561.     default:
  562. // Other levels we simply don't handle...
  563. status = E_ACCESSDENIED;
  564. }
  565.     m_channelStatus [cid] = status;
  566.     return status;
  567.     }
  568. //////////////////////////////////////////////////////////////////////////
  569. //
  570. void NTLMSSP::ndrUnihdr (UNIHDR* puh, DREP drep)
  571.     {
  572.     ndr_make_right (puh->len, drep);
  573.     ndr_make_right (puh->max, drep);
  574.     ndr_make_right (puh->offset, drep);
  575.     }
  576. //////////////////////////////////////////////////////////////////////////
  577. //
  578. // userAdd -- adds a user to the user-table, storing the 16-byte
  579. // LM-hash rather than the plain-text password...
  580. //
  581. void NTLMSSP::userAdd (const char* userName, const char* userPasswd)
  582.     {
  583.     // Compute LM-hash of plain-text password...
  584.     unsigned char ntlmPasswd [16];
  585.    
  586.     // Mangle the user-password into LanMan format (14 chars max, upper case)
  587.     memset (ntlmPasswd, '', sizeof (ntlmPasswd));
  588.     strncpy ((char*) ntlmPasswd, userPasswd, sizeof (ntlmPasswd));
  589.     ntlmPasswd [14] = '';
  590.     strupper (ntlmPasswd);
  591.    
  592.     // Calculate the SMB (lanman) hash function of the password
  593.     NTLMSSP::lmhash ntlmHash;
  594.     
  595.     memset (&ntlmHash, 0, sizeof (ntlmHash));
  596.     NTLMSSP::DES::encrypt16 (ntlmPasswd, ntlmHash.data);
  597.     // Save the hash into the user-table...
  598.     s_userTable [userName] = ntlmHash;
  599.     
  600.     // Erase the hash and plain-text from the stack
  601.     memset (&ntlmHash, 0, 16);
  602.     memset (ntlmPasswd, 0, 16);
  603.     }
  604. //////////////////////////////////////////////////////////////////////////
  605. //
  606. // encrypt -- encrypts the user's password-hash with the 8-byte
  607. // challenge and produces a 24-byte response...
  608. //
  609. void NTLMSSP::encrypt
  610.     (
  611.     const BYTE* pwdHash, // the password-hash
  612.     const BYTE* challenge, // the challenge
  613.     BYTE* p24 // output
  614.     )
  615.     {
  616.     BYTE p21 [21];
  617.  
  618.     memset (p21,'',21);
  619.     memcpy (p21, pwdHash, 16);    
  620.     NTLMSSP::DES::encrypt24 (p21, const_cast<BYTE*> (challenge), p24);
  621.     }
  622. //////////////////////////////////////////////////////////////////////////
  623. //
  624. // serverAuth3Validate -- this function is called when an AUTH3 PDU is
  625. // received at the server-side of a connection. This will happen when
  626. // the client has attempted to open an authenticated connection to
  627. // this machine, and we have sent it a challenge. What we get back is
  628. // the response to that challenge, which must match our calculated
  629. // response if we are bothered about authentication at all. If we
  630. // aren't bothered, (i.e. the authn-level is set to NONE) then we
  631. // simply let the AUTH3 PDU 'pass through' as if it were okay...
  632. //
  633. HRESULT NTLMSSP::serverAuth3Validate
  634.     (
  635.     int cid, // channel ID
  636.     const RpcPdu& auth3Pdu // rcvd AUTH3 packet
  637.     )
  638.     {
  639.     // Get current status...
  640.     VxCritSec cs (m_mutex);
  641.     HRESULT status = m_channelStatus [cid];
  642.     
  643.     // Check how much authn we require...
  644.     switch (m_authnLevel)
  645. {
  646.     case RPC_C_AUTHN_LEVEL_NONE:
  647. // No authn required, we can let this one through...
  648. status = S_OK;
  649. break;
  650.     case RPC_C_AUTHN_LEVEL_CONNECT:
  651. // Connect-level is supported if the user/application has
  652. // registered some user/password combinations, so we must
  653. // continue processing. Check the auth-trailer for
  654. // correctness...
  655. status = authTrailerCheck (auth3Pdu);
  656. if (SUCCEEDED (status))
  657.     {
  658.     // Check there is some data to deal with -- if we get to
  659.     // here then we have received an AUTH3 packet and so there
  660.     // *must* be some, if not we return an error-value and
  661.     // effectively reject the packet...
  662.     if (auth3Pdu.authLen () == 0)
  663. status = E_ACCESSDENIED;
  664.     else
  665. {
  666. // Find the start of the trailer data...
  667. const rpc_cn_auth_tlr_t* pAuthTlr = auth3Pdu.authTrailer ();
  668. response* phdr = (response*) pAuthTlr->authValue;
  669. // NDR the important fields...
  670. ndr_make_right (phdr->sequence, auth3Pdu.drep ());
  671. ndrUnihdr (&phdr->domainName, auth3Pdu.drep ());
  672. ndrUnihdr (&phdr->userName, auth3Pdu.drep ());
  673. ndrUnihdr (&phdr->machineName, auth3Pdu.drep ());
  674. ndr_make_right (phdr->magic2, auth3Pdu.drep ());
  675.     
  676. int textBytes = phdr->domainName.len +
  677. phdr->userName.len +
  678. phdr->machineName.len;
  679. USHORT* pwsText = (USHORT*) (phdr+1);
  680. for (int t=0; t < textBytes / 2; ++t)
  681.     ndr_make_right (pwsText [t], auth3Pdu.drep ());
  682. // Extract user-name as ASCII string...
  683. char userName [32];
  684. int n = phdr->userName.len / 2;
  685. pwsText += (phdr->domainName.len / 2);
  686. for (int i=0; i < n; ++i)
  687.     userName [i] = (char) pwsText [i];
  688. userName [n] = 0;
  689. // Find the 'response' data block in the PDU
  690. BYTE* pdata = ((BYTE*) (phdr+1)) + textBytes;
  691. // Calculate what the response should be...
  692. BYTE calculatedResult[24];
  693. memset (calculatedResult, 0, 24);
  694. encrypt (s_userTable [userName].data,
  695.  s_defaultChallenge,
  696.  calculatedResult);
  697. // Did the encrypted response come out right?
  698. if (memcmp (pdata, calculatedResult, 24) != 0)
  699.     {
  700.     S_INFO (LOG_AUTH, "AUTH3:access denied:" << userName);
  701.     status = E_ACCESSDENIED;
  702.     }
  703. else
  704.     {
  705.     S_INFO (LOG_AUTH, "AUTH3:access granted:" << userName);
  706.     status = S_OK;
  707.     }
  708. }
  709.     }
  710. break;
  711.     case RPC_C_AUTHN_LEVEL_CALL:
  712.     case RPC_C_AUTHN_LEVEL_PKT:
  713.     case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
  714.     case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
  715. // These levels are not supported...
  716. status = MAKE_HRESULT (SEVERITY_ERROR,
  717.        FACILITY_RPC,
  718.        RPC_S_UNSUPPORTED_AUTHN_LEVEL);
  719.     case RPC_C_AUTHN_LEVEL_DEFAULT:
  720.     default:
  721. // Unknown errors!
  722. COM_ASSERT (0);
  723. status = E_FAIL;
  724. }
  725.     m_channelStatus [cid] = status;
  726.     return status;
  727.     }
  728. //////////////////////////////////////////////////////////////////////////
  729. //
  730. // clientAuthnRequestAdd -- empty stub for now.
  731. //
  732. HRESULT NTLMSSP::clientAuthnRequestAdd
  733.     (
  734.     int  channelId,
  735.     RpcPdu& bindPdu
  736.     )
  737.     {
  738.     return S_OK;
  739.     }
  740. //////////////////////////////////////////////////////////////////////////
  741. //
  742. // clientAuthnResponse -- empty stub for now.
  743. //
  744. HRESULT NTLMSSP::clientAuthnResponse
  745.     (
  746.     int  channelId,
  747.     const RpcPdu& bindAckPdu,
  748.     bool* pbSendAuth3,
  749.     RpcPdu& auth3Pdu
  750.     )
  751.     {
  752.     *pbSendAuth3 = false;
  753.     return S_OK;
  754.     }
  755. //////////////////////////////////////////////////////////////////////////
  756. //
  757. // clientAuthn -- empty stub for now.
  758. //
  759. HRESULT NTLMSSP::clientAuthn
  760.     (
  761.     int  channelId,
  762.     RpcPdu& reqPdu
  763.     )
  764.     {
  765.     return S_OK;
  766.     }
  767.