home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / security / winnt / sockauth / security.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-09  |  9.8 KB  |  480 lines

  1. /*++
  2.  
  3. Copyright 1996-1997 Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     security.c
  8.  
  9. Abstract:
  10.  
  11.     Handles communication with the SSP package.
  12.  
  13. Revision History:
  14.  
  15. --*/
  16.  
  17. #include <windows.h>
  18. #include <winsock.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #define SECURITY_WIN32
  22. #include "sspi.h"
  23. #include "issperr.h"
  24. #include "security.h"
  25. #include "collect.h"
  26.  
  27. static HINSTANCE g_hLib;
  28. static DWORD g_cbMaxToken;
  29. static PSecurityFunctionTable g_pFuncs;
  30.  
  31. // structure storing the state of the authentication sequence
  32. //
  33. typedef struct _AUTH_SEQ {
  34.     BOOL _fNewConversation;
  35.     CredHandle _hcred;
  36.     BOOL _fHaveCredHandle;
  37.     BOOL _fHaveCtxtHandle;
  38.     struct _SecHandle  _hctxt;
  39. } AUTH_SEQ, *PAUTH_SEQ;
  40.  
  41. #define SEC_SUCCESS(Status) ((Status) >= 0)
  42.  
  43. #define PACKAGE_NAME    "NTLM"
  44. #define NT_DLL_NAME        "security.dll"
  45.  
  46. // Target name for the security package
  47. //
  48. #define TOKEN_SOURCE_NAME       "AuthSamp"
  49.  
  50.  
  51. BOOL InitPackage (DWORD *pcbMaxMessage)
  52. /*++
  53.  
  54.  Routine Description:
  55.  
  56.     Finds, loads and initializes the security package
  57.  
  58.  Return Value:
  59.  
  60.     Returns TRUE is successful; otherwise FALSE is returned.
  61.  
  62. --*/
  63. {
  64.     FARPROC pInit;
  65.     SECURITY_STATUS ss;
  66.     PSecPkgInfo pkgInfo;
  67.  
  68.     // load and initialize the ntlm ssp
  69.     //
  70.     g_hLib = LoadLibrary (NT_DLL_NAME);
  71.     if (NULL == g_hLib)  {
  72.         fprintf (stderr, "Couldn't load dll: %u\n", GetLastError ());
  73.         return(FALSE);
  74.     }
  75.  
  76.     pInit = GetProcAddress (g_hLib, SECURITY_ENTRYPOINT);
  77.     if (NULL == pInit)  {
  78.         fprintf (stderr, "Couldn't get sec init routine: %u\n", GetLastError ());
  79.         return(FALSE);
  80.     }
  81.  
  82.     g_pFuncs = (PSecurityFunctionTable) pInit ();
  83.     if (NULL == g_pFuncs)  {
  84.         fprintf (stderr, "Couldn't init package\n");
  85.         return(FALSE);
  86.     }
  87.  
  88.     // Query for the package we're interested in
  89.     //
  90.     ss = g_pFuncs->QuerySecurityPackageInfo (PACKAGE_NAME, &pkgInfo);
  91.     if (!SEC_SUCCESS(ss))  {
  92.         fprintf (stderr, "Couldn't query package info for %s, error %u\n",
  93.                     PACKAGE_NAME, ss);
  94.         return(FALSE);
  95.     }
  96.  
  97.     g_cbMaxToken = pkgInfo->cbMaxToken;
  98.  
  99.     g_pFuncs->FreeContextBuffer (pkgInfo);
  100.  
  101.     *pcbMaxMessage = g_cbMaxToken;
  102.  
  103.     return TRUE;
  104. }
  105.  
  106. BOOL TermPackage ()
  107. {
  108.     FreeLibrary (g_hLib);
  109.  
  110.     return(TRUE);
  111. }
  112.  
  113. BOOL GenClientContext (
  114.             DWORD dwKey,
  115.             BYTE *pIn,
  116.             DWORD cbIn,
  117.             BYTE *pOut,
  118.             DWORD *pcbOut,
  119.             BOOL *pfDone)
  120. /*++
  121.  
  122.  Routine Description:
  123.  
  124.     Optionally takes an input buffer coming from the server and returns
  125.     a buffer of information to send back to the server.  Also returns
  126.     an indication of whether or not the context is complete.
  127.  
  128.  Return Value:
  129.  
  130.     Returns TRUE is successful; otherwise FALSE is returned.
  131.  
  132. --*/
  133. {
  134.     SECURITY_STATUS    ss;
  135.     TimeStamp        Lifetime;
  136.     SecBufferDesc    OutBuffDesc;
  137.     SecBuffer        OutSecBuff;
  138.     SecBufferDesc    InBuffDesc;
  139.     SecBuffer        InSecBuff;
  140.     ULONG            ContextAttributes;
  141.     PAUTH_SEQ        pAS;
  142.  
  143.     // Lookup pAS based on Key
  144.     //
  145.     if (!GetEntry (dwKey, (PVOID*) &pAS))
  146.         return(FALSE);
  147.  
  148.     if (pAS->_fNewConversation)  {
  149.         ss = g_pFuncs->AcquireCredentialsHandle (
  150.                             NULL,    // principal
  151.                             PACKAGE_NAME,
  152.                             SECPKG_CRED_OUTBOUND,
  153.                             NULL,    // LOGON id
  154.                             NULL,    // auth data
  155.                             NULL,    // get key fn
  156.                             NULL,    // get key arg
  157.                             &pAS->_hcred,
  158.                             &Lifetime
  159.                             );
  160.         if (SEC_SUCCESS (ss))
  161.             pAS->_fHaveCredHandle = TRUE;
  162.         else {
  163.             fprintf (stderr, "AcquireCreds failed: %u\n", ss);
  164.             return(FALSE);
  165.         }
  166.     }
  167.  
  168.     // prepare output buffer
  169.     //
  170.     OutBuffDesc.ulVersion = 0;
  171.     OutBuffDesc.cBuffers = 1;
  172.     OutBuffDesc.pBuffers = &OutSecBuff;
  173.  
  174.     OutSecBuff.cbBuffer = *pcbOut;
  175.     OutSecBuff.BufferType = SECBUFFER_TOKEN;
  176.     OutSecBuff.pvBuffer = pOut;
  177.  
  178.     // prepare input buffer
  179.     //
  180.     if (!pAS->_fNewConversation)  {
  181.         InBuffDesc.ulVersion = 0;
  182.         InBuffDesc.cBuffers = 1;
  183.         InBuffDesc.pBuffers = &InSecBuff;
  184.  
  185.         InSecBuff.cbBuffer = cbIn;
  186.         InSecBuff.BufferType = SECBUFFER_TOKEN;
  187.         InSecBuff.pvBuffer = pIn;
  188.     }
  189.  
  190.     ss = g_pFuncs->InitializeSecurityContext (
  191.                         &pAS->_hcred,
  192.                         pAS->_fNewConversation ? NULL : &pAS->_hctxt,
  193.                         TOKEN_SOURCE_NAME,
  194.                         0,    // context requirements
  195.                         0,    // reserved1
  196.                         SECURITY_NATIVE_DREP,
  197.                         pAS->_fNewConversation ? NULL : &InBuffDesc,
  198.                         0,    // reserved2
  199.                         &pAS->_hctxt,
  200.                         &OutBuffDesc,
  201.                         &ContextAttributes,
  202.                         &Lifetime
  203.                         );
  204.     if (!SEC_SUCCESS (ss))  {
  205.         fprintf (stderr, "init context failed: %u\n", ss);
  206.         return FALSE;
  207.     }
  208.  
  209.     pAS->_fHaveCtxtHandle = TRUE;
  210.  
  211.     // Complete token -- if applicable
  212.     //
  213.     if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))  {
  214.         if (g_pFuncs->CompleteAuthToken) {
  215.             ss = g_pFuncs->CompleteAuthToken (&pAS->_hctxt, &OutBuffDesc);
  216.             if (!SEC_SUCCESS(ss))  {
  217.                 fprintf (stderr, "complete failed: %u\n", ss);
  218.                 return FALSE;
  219.             }
  220.         }
  221.         else {
  222.             fprintf (stderr, "Complete not supported.\n");
  223.             return FALSE;
  224.         }
  225.     }
  226.  
  227.     *pcbOut = OutSecBuff.cbBuffer;
  228.  
  229.     if (pAS->_fNewConversation)
  230.         pAS->_fNewConversation = FALSE;
  231.  
  232.     *pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
  233.                 (SEC_I_COMPLETE_AND_CONTINUE == ss));
  234.  
  235.     return TRUE;
  236. }
  237.  
  238. BOOL GenServerContext (
  239.             DWORD dwKey,
  240.             BYTE *pIn,
  241.             DWORD cbIn,
  242.             BYTE *pOut,
  243.             DWORD *pcbOut,
  244.             BOOL *pfDone)
  245. /*++
  246.  
  247.  Routine Description:
  248.  
  249.     Takes an input buffer coming from the client and returns a buffer
  250.     to be sent to the client.  Also returns an indication of whether or
  251.     not the context is complete.
  252.  
  253.  Return Value:
  254.  
  255.     Returns TRUE is successful; otherwise FALSE is returned.
  256.  
  257. --*/
  258. {
  259.     SECURITY_STATUS    ss;
  260.     TimeStamp        Lifetime;
  261.     SecBufferDesc    OutBuffDesc;
  262.     SecBuffer        OutSecBuff;
  263.     SecBufferDesc    InBuffDesc;
  264.     SecBuffer        InSecBuff;
  265.     ULONG            ContextAttributes;
  266.     PAUTH_SEQ        pAS;
  267.  
  268.     // Lookup pAS based on Key
  269.     //
  270.     if (!GetEntry (dwKey, (PVOID*) &pAS))
  271.         return(FALSE);
  272.  
  273.     if (pAS->_fNewConversation)  {
  274.         ss = g_pFuncs->AcquireCredentialsHandle (
  275.                             NULL,    // principal
  276.                             PACKAGE_NAME,
  277.                             SECPKG_CRED_INBOUND,
  278.                             NULL,    // LOGON id
  279.                             NULL,    // auth data
  280.                             NULL,    // get key fn
  281.                             NULL,    // get key arg
  282.                             &pAS->_hcred,
  283.                             &Lifetime
  284.                             );
  285.         if (SEC_SUCCESS (ss))
  286.             pAS->_fHaveCredHandle = TRUE;
  287.         else {
  288.             fprintf (stderr, "AcquireCreds failed: %u\n", ss);
  289.             return(FALSE);
  290.         }
  291.     }
  292.  
  293.     // prepare output buffer
  294.     //
  295.     OutBuffDesc.ulVersion = 0;
  296.     OutBuffDesc.cBuffers = 1;
  297.     OutBuffDesc.pBuffers = &OutSecBuff;
  298.  
  299.     OutSecBuff.cbBuffer = *pcbOut;
  300.     OutSecBuff.BufferType = SECBUFFER_TOKEN;
  301.     OutSecBuff.pvBuffer = pOut;
  302.  
  303.     // prepare input buffer
  304.     //
  305.     InBuffDesc.ulVersion = 0;
  306.     InBuffDesc.cBuffers = 1;
  307.     InBuffDesc.pBuffers = &InSecBuff;
  308.  
  309.     InSecBuff.cbBuffer = cbIn;
  310.     InSecBuff.BufferType = SECBUFFER_TOKEN;
  311.     InSecBuff.pvBuffer = pIn;
  312.  
  313.     ss = g_pFuncs->AcceptSecurityContext (
  314.                         &pAS->_hcred,
  315.                         pAS->_fNewConversation ? NULL : &pAS->_hctxt,
  316.                         &InBuffDesc,
  317.                         0,    // context requirements
  318.                         SECURITY_NATIVE_DREP,
  319.                         &pAS->_hctxt,
  320.                         &OutBuffDesc,
  321.                         &ContextAttributes,
  322.                         &Lifetime
  323.                         );
  324.     if (!SEC_SUCCESS (ss))  {
  325.         fprintf (stderr, "init context failed: %u\n", ss);
  326.         return FALSE;
  327.     }
  328.  
  329.     pAS->_fHaveCtxtHandle = TRUE;
  330.  
  331.     // Complete token -- if applicable
  332.     //
  333.     if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))  {
  334.         if (g_pFuncs->CompleteAuthToken) {
  335.             ss = g_pFuncs->CompleteAuthToken (&pAS->_hctxt, &OutBuffDesc);
  336.             if (!SEC_SUCCESS(ss))  {
  337.                 fprintf (stderr, "complete failed: %u\n", ss);
  338.                 return FALSE;
  339.             }
  340.         }
  341.         else {
  342.             fprintf (stderr, "Complete not supported.\n");
  343.             return FALSE;
  344.         }
  345.     }
  346.  
  347.     *pcbOut = OutSecBuff.cbBuffer;
  348.  
  349.     if (pAS->_fNewConversation)
  350.         pAS->_fNewConversation = FALSE;
  351.  
  352.     *pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
  353.                 (SEC_I_COMPLETE_AND_CONTINUE == ss));
  354.  
  355.     return TRUE;
  356. }
  357.  
  358. BOOL ImpersonateContext (DWORD dwKey)
  359. /*++
  360.  
  361.  Routine Description:
  362.  
  363.     Impersonates the client whose context is associated with the
  364.     supplied key.
  365.  
  366.  Return Value:
  367.  
  368.     Returns TRUE is successful; otherwise FALSE is returned.
  369.  
  370. --*/
  371. {
  372.     SECURITY_STATUS    ss;
  373.     PAUTH_SEQ        pAS;
  374.  
  375.     // Lookup pAS based on Key
  376.     //
  377.     if (!GetEntry (dwKey, (PVOID*) &pAS))
  378.         return(FALSE);
  379.  
  380.     ss = g_pFuncs->ImpersonateSecurityContext (&pAS->_hctxt);
  381.     if (!SEC_SUCCESS(ss)) {
  382.         fprintf (stderr, "Impersonate failed: %u\n", ss);
  383.         return(FALSE);
  384.     }
  385.  
  386.     return(TRUE);
  387. }
  388.  
  389. BOOL RevertContext (DWORD dwKey)
  390. /*++
  391.  
  392.  Routine Description:
  393.  
  394.     Reverts to the original server context.
  395.  
  396.  Return Value:
  397.  
  398.     Returns TRUE is successful; otherwise FALSE is returned.
  399.  
  400. --*/
  401. {
  402.     SECURITY_STATUS ss;
  403.     PAUTH_SEQ        pAS;
  404.  
  405.     // Lookup pAS based on Key
  406.     //
  407.     if (!GetEntry (dwKey, (PVOID*) &pAS))
  408.         return(FALSE);
  409.  
  410.     ss = g_pFuncs->RevertSecurityContext (&pAS->_hctxt);
  411.     if (!SEC_SUCCESS(ss)) {
  412.         fprintf (stderr, "Revert failed: %u\n", ss);
  413.         return(FALSE);
  414.     }
  415.  
  416.     return(TRUE);
  417. }
  418.  
  419. BOOL InitSession (DWORD dwKey)
  420. /*++
  421.  
  422.  Routine Description:
  423.  
  424.     Initializes the context associated with a key and adds it to the
  425.     collection.
  426.  
  427.  Return Value:
  428.  
  429.     Returns TRUE is successful; otherwise FALSE is returned.
  430.  
  431. --*/
  432. {
  433.     PAUTH_SEQ pAS;
  434.  
  435.     pAS = (PAUTH_SEQ) malloc (sizeof (AUTH_SEQ));
  436.     if (NULL == pAS)
  437.         return(FALSE);
  438.  
  439.     pAS->_fNewConversation = TRUE;
  440.     pAS->_fHaveCredHandle = FALSE;
  441.     pAS->_fHaveCtxtHandle = FALSE;
  442.         
  443.     if (!AddEntry (dwKey, (PVOID)pAS))  {
  444.         free (pAS);
  445.         return(FALSE);
  446.     }
  447.  
  448.     return(TRUE);
  449. }
  450.  
  451. BOOL TermSession (DWORD dwKey)
  452. /*++
  453.  
  454.  Routine Description:
  455.  
  456.     Releases the resources associated with a key and removes it from
  457.     the collection.
  458.  
  459.  Return Value:
  460.  
  461.     Returns TRUE is successful; otherwise FALSE is returned.
  462.  
  463. --*/
  464. {
  465.     PAUTH_SEQ pAS;
  466.  
  467.     if (!DeleteEntry (dwKey, (LPVOID*)&pAS))    
  468.         return(FALSE);
  469.  
  470.     if (pAS->_fHaveCtxtHandle)
  471.         g_pFuncs->DeleteSecurityContext (&pAS->_hctxt);
  472.  
  473.     if (pAS->_fHaveCredHandle)
  474.         g_pFuncs->FreeCredentialHandle (&pAS->_hcred);
  475.  
  476.     free (pAS);
  477.     
  478.     return(TRUE);
  479. }    
  480.