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