]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/sspi.c
Import CUPS v2.0b1
[thirdparty/cups.git] / cups / sspi.c
diff --git a/cups/sspi.c b/cups/sspi.c
deleted file mode 100644 (file)
index ba66f72..0000000
+++ /dev/null
@@ -1,1468 +0,0 @@
-/*
- * "$Id: sspi.c 11760 2014-03-28 12:58:24Z msweet $"
- *
- * Windows SSPI SSL implementation for CUPS.
- *
- * Copyright 2010-2014 by Apple Inc.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file.  If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "sspi-private.h"
-#include "debug-private.h"
-
-
-/* required to link this library for certificate functions */
-#pragma comment(lib, "Crypt32.lib")
-#pragma comment(lib, "Secur32.lib")
-#pragma comment(lib, "Ws2_32.lib")
-
-
-#if !defined(SECURITY_FLAG_IGNORE_UNKNOWN_CA)
-#  define SECURITY_FLAG_IGNORE_UNKNOWN_CA         0x00000100 /* Untrusted root */
-#endif
-
-#if !defined(SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)
-#  define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID  0x00002000 /* Expired X509 Cert. */
-#endif
-
-static DWORD sspi_verify_certificate(PCCERT_CONTEXT  serverCert,
-                                     const CHAR      *serverName,
-                                     DWORD           dwCertFlags);
-
-
-/*
- * 'sspi_alloc()' - Allocate SSPI ssl object
- */
-_sspi_struct_t*                                /* O  - New SSPI/SSL object */
-_sspiAlloc(void)
-{
-  _sspi_struct_t *conn = calloc(sizeof(_sspi_struct_t), 1);
-
-  if (conn)
-    conn->sock = INVALID_SOCKET;
-
-  return (conn);
-}
-
-
-/*
- * '_sspiGetCredentials()' - Retrieve an SSL/TLS certificate from the system store
- *                              If one cannot be found, one is created.
- */
-BOOL                                   /* O - 1 on success, 0 on failure */
-_sspiGetCredentials(_sspi_struct_t *conn,
-                                       /* I - Client connection */
-                    const LPWSTR   container,
-                                       /* I - Cert container name */
-                    const TCHAR    *cn,        /* I - Common name of certificate */
-                    BOOL           isServer)
-                                       /* I - Is caller a server? */
-{
-  HCERTSTORE           store = NULL;   /* Certificate store */
-  PCCERT_CONTEXT       storedContext = NULL;
-                                       /* Context created from the store */
-  PCCERT_CONTEXT       createdContext = NULL;
-                                       /* Context created by us */
-  DWORD                        dwSize = 0;     /* 32 bit size */
-  PBYTE                        p = NULL;       /* Temporary storage */
-  HCRYPTPROV           hProv = (HCRYPTPROV) NULL;
-                                       /* Handle to a CSP */
-  CERT_NAME_BLOB       sib;            /* Arbitrary array of bytes */
-  SCHANNEL_CRED                SchannelCred;   /* Schannel credential data */
-  TimeStamp            tsExpiry;       /* Time stamp */
-  SECURITY_STATUS      Status;         /* Status */
-  HCRYPTKEY            hKey = (HCRYPTKEY) NULL;
-                                       /* Handle to crypto key */
-  CRYPT_KEY_PROV_INFO  kpi;            /* Key container info */
-  SYSTEMTIME           et;             /* System time */
-  CERT_EXTENSIONS      exts;           /* Array of cert extensions */
-  CRYPT_KEY_PROV_INFO  ckp;            /* Handle to crypto key */
-  BOOL                 ok = TRUE;      /* Return value */
-
-
-  DEBUG_printf(("_sspiGetCredentials(conn=%p, container=%p, cn=\"%s\", isServer=%d)", conn, container, cn, isServer));
-
-  if (!conn)
-    return (FALSE);
-  if (!cn)
-    return (FALSE);
-
-  if (!CryptAcquireContextW(&hProv, (LPWSTR) container, MS_DEF_PROV_W,
-                           PROV_RSA_FULL,
-                           CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
-  {
-    if (GetLastError() == NTE_EXISTS)
-    {
-      if (!CryptAcquireContextW(&hProv, (LPWSTR) container, MS_DEF_PROV_W,
-                               PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
-      {
-        DEBUG_printf(("_sspiGetCredentials: CryptAcquireContext failed: %x\n",
-                      GetLastError()));
-        ok = FALSE;
-        goto cleanup;
-      }
-    }
-  }
-
-  store = CertOpenStore(CERT_STORE_PROV_SYSTEM,
-                        X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,
-                        hProv,
-                        CERT_SYSTEM_STORE_LOCAL_MACHINE |
-                        CERT_STORE_NO_CRYPT_RELEASE_FLAG |
-                        CERT_STORE_OPEN_EXISTING_FLAG,
-                        L"MY");
-
-  if (!store)
-  {
-    DEBUG_printf(("_sspiGetCredentials: CertOpenSystemStore failed: %x\n",
-                  GetLastError()));
-    ok = FALSE;
-    goto cleanup;
-  }
-
-  dwSize = 0;
-
-  if (!CertStrToName(X509_ASN_ENCODING, cn, CERT_OID_NAME_STR,
-                     NULL, NULL, &dwSize, NULL))
-  {
-    DEBUG_printf(("_sspiGetCredentials: CertStrToName failed: %x\n",
-                   GetLastError()));
-    ok = FALSE;
-    goto cleanup;
-  }
-
-  p = (PBYTE) malloc(dwSize);
-
-  if (!p)
-  {
-    DEBUG_printf(("_sspiGetCredentials: malloc failed for %d bytes", dwSize));
-    ok = FALSE;
-    goto cleanup;
-  }
-
-  if (!CertStrToName(X509_ASN_ENCODING, cn, CERT_OID_NAME_STR, NULL,
-                     p, &dwSize, NULL))
-  {
-    DEBUG_printf(("_sspiGetCredentials: CertStrToName failed: %x",
-                 GetLastError()));
-    ok = FALSE;
-    goto cleanup;
-  }
-
-  sib.cbData = dwSize;
-  sib.pbData = p;
-
-  storedContext = CertFindCertificateInStore(store, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,
-                                             0, CERT_FIND_SUBJECT_NAME, &sib, NULL);
-
-  if (!storedContext)
-  {
-   /*
-    * If we couldn't find the context, then we'll
-    * create a new one
-    */
-    if (!CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey))
-    {
-      DEBUG_printf(("_sspiGetCredentials: CryptGenKey failed: %x",
-                    GetLastError()));
-      ok = FALSE;
-      goto cleanup;
-    }
-
-    ZeroMemory(&kpi, sizeof(kpi));
-    kpi.pwszContainerName = (LPWSTR) container;
-    kpi.pwszProvName = MS_DEF_PROV_W;
-    kpi.dwProvType = PROV_RSA_FULL;
-    kpi.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
-    kpi.dwKeySpec = AT_KEYEXCHANGE;
-
-    GetSystemTime(&et);
-    et.wYear += 10;
-
-    ZeroMemory(&exts, sizeof(exts));
-
-    createdContext = CertCreateSelfSignCertificate(hProv, &sib, 0, &kpi, NULL, NULL,
-                                                   &et, &exts);
-
-    if (!createdContext)
-    {
-      DEBUG_printf(("_sspiGetCredentials: CertCreateSelfSignCertificate failed: %x",
-                   GetLastError()));
-      ok = FALSE;
-      goto cleanup;
-    }
-
-    if (!CertAddCertificateContextToStore(store, createdContext,
-                                          CERT_STORE_ADD_REPLACE_EXISTING,
-                                          &storedContext))
-    {
-      DEBUG_printf(("_sspiGetCredentials: CertAddCertificateContextToStore failed: %x",
-                    GetLastError()));
-      ok = FALSE;
-      goto cleanup;
-    }
-
-    ZeroMemory(&ckp, sizeof(ckp));
-    ckp.pwszContainerName = (LPWSTR) container;
-    ckp.pwszProvName = MS_DEF_PROV_W;
-    ckp.dwProvType = PROV_RSA_FULL;
-    ckp.dwFlags = CRYPT_MACHINE_KEYSET;
-    ckp.dwKeySpec = AT_KEYEXCHANGE;
-
-    if (!CertSetCertificateContextProperty(storedContext,
-                                           CERT_KEY_PROV_INFO_PROP_ID,
-                                           0, &ckp))
-    {
-      DEBUG_printf(("_sspiGetCredentials: CertSetCertificateContextProperty failed: %x",
-                    GetLastError()));
-      ok = FALSE;
-      goto cleanup;
-    }
-  }
-
-  ZeroMemory(&SchannelCred, sizeof(SchannelCred));
-
-  SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
-  SchannelCred.cCreds = 1;
-  SchannelCred.paCred = &storedContext;
-
- /*
-  * SSPI doesn't seem to like it if grbitEnabledProtocols
-  * is set for a client
-  */
-  if (isServer)
-    SchannelCred.grbitEnabledProtocols = SP_PROT_SSL3TLS1;
-
- /*
-  * Create an SSPI credential.
-  */
-  Status = AcquireCredentialsHandle(NULL, UNISP_NAME,
-                                    isServer ? SECPKG_CRED_INBOUND:SECPKG_CRED_OUTBOUND,
-                                    NULL, &SchannelCred, NULL, NULL, &conn->creds,
-                                    &tsExpiry);
-  if (Status != SEC_E_OK)
-  {
-    DEBUG_printf(("_sspiGetCredentials: AcquireCredentialsHandle failed: %x", Status));
-    ok = FALSE;
-    goto cleanup;
-  }
-
-cleanup:
-
- /*
-  * Cleanup
-  */
-  if (hKey)
-    CryptDestroyKey(hKey);
-
-  if (createdContext)
-    CertFreeCertificateContext(createdContext);
-
-  if (storedContext)
-    CertFreeCertificateContext(storedContext);
-
-  if (p)
-    free(p);
-
-  if (store)
-    CertCloseStore(store, 0);
-
-  if (hProv)
-    CryptReleaseContext(hProv, 0);
-
-  return (ok);
-}
-
-
-/*
- * '_sspiConnect()' - Make an SSL connection. This function
- *                    assumes a TCP/IP connection has already
- *                    been successfully made
- */
-BOOL                                   /* O - 1 on success, 0 on failure */
-_sspiConnect(_sspi_struct_t *conn,     /* I - Client connection */
-             const CHAR *hostname)     /* I - Server hostname */
-{
-  PCCERT_CONTEXT       serverCert;     /* Server certificate */
-  DWORD                        dwSSPIFlags;    /* SSL connection attributes we want */
-  DWORD                        dwSSPIOutFlags; /* SSL connection attributes we got */
-  TimeStamp            tsExpiry;       /* Time stamp */
-  SECURITY_STATUS      scRet;          /* Status */
-  DWORD                        cbData;         /* Data count */
-  SecBufferDesc                inBuffer;       /* Array of SecBuffer structs */
-  SecBuffer            inBuffers[2];   /* Security package buffer */
-  SecBufferDesc                outBuffer;      /* Array of SecBuffer structs */
-  SecBuffer            outBuffers[1];  /* Security package buffer */
-  BOOL                 ok = TRUE;      /* Return value */
-
-  serverCert  = NULL;
-
-  dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT   |
-                ISC_REQ_REPLAY_DETECT     |
-                ISC_REQ_CONFIDENTIALITY   |
-                ISC_RET_EXTENDED_ERROR    |
-                ISC_REQ_ALLOCATE_MEMORY   |
-                ISC_REQ_STREAM;
-
- /*
-  * Initiate a ClientHello message and generate a token.
-  */
-  outBuffers[0].pvBuffer   = NULL;
-  outBuffers[0].BufferType = SECBUFFER_TOKEN;
-  outBuffers[0].cbBuffer   = 0;
-
-  outBuffer.cBuffers = 1;
-  outBuffer.pBuffers = outBuffers;
-  outBuffer.ulVersion = SECBUFFER_VERSION;
-
-  scRet = InitializeSecurityContext(&conn->creds, NULL, TEXT(""), dwSSPIFlags,
-                                    0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
-                                    &outBuffer, &dwSSPIOutFlags, &tsExpiry);
-
-  if (scRet != SEC_I_CONTINUE_NEEDED)
-  {
-    DEBUG_printf(("_sspiConnect: InitializeSecurityContext(1) failed: %x", scRet));
-    ok = FALSE;
-    goto cleanup;
-  }
-
- /*
-  * Send response to server if there is one.
-  */
-  if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
-  {
-    cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
-
-    if ((cbData == SOCKET_ERROR) || !cbData)
-    {
-      DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError()));
-      FreeContextBuffer(outBuffers[0].pvBuffer);
-      DeleteSecurityContext(&conn->context);
-      ok = FALSE;
-      goto cleanup;
-    }
-
-    DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData));
-
-   /*
-    * Free output buffer.
-    */
-    FreeContextBuffer(outBuffers[0].pvBuffer);
-    outBuffers[0].pvBuffer = NULL;
-  }
-
-  dwSSPIFlags = ISC_REQ_MANUAL_CRED_VALIDATION |
-                   ISC_REQ_SEQUENCE_DETECT        |
-                ISC_REQ_REPLAY_DETECT          |
-                ISC_REQ_CONFIDENTIALITY        |
-                ISC_RET_EXTENDED_ERROR         |
-                ISC_REQ_ALLOCATE_MEMORY        |
-                ISC_REQ_STREAM;
-
-  conn->decryptBufferUsed = 0;
-
- /*
-  * Loop until the handshake is finished or an error occurs.
-  */
-  scRet = SEC_I_CONTINUE_NEEDED;
-
-  while(scRet == SEC_I_CONTINUE_NEEDED        ||
-        scRet == SEC_E_INCOMPLETE_MESSAGE     ||
-        scRet == SEC_I_INCOMPLETE_CREDENTIALS)
-  {
-    if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE))
-    {
-      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
-      {
-        conn->decryptBufferLength += 4096;
-        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer, conn->decryptBufferLength);
-
-        if (!conn->decryptBuffer)
-        {
-          DEBUG_printf(("_sspiConnect: unable to allocate %d byte decrypt buffer",
-                        conn->decryptBufferLength));
-          SetLastError(E_OUTOFMEMORY);
-          ok = FALSE;
-          goto cleanup;
-        }
-      }
-
-      cbData = recv(conn->sock, conn->decryptBuffer + conn->decryptBufferUsed,
-                    (int) (conn->decryptBufferLength - conn->decryptBufferUsed), 0);
-
-      if (cbData == SOCKET_ERROR)
-      {
-        DEBUG_printf(("_sspiConnect: recv failed: %d", WSAGetLastError()));
-        ok = FALSE;
-        goto cleanup;
-      }
-      else if (cbData == 0)
-      {
-        DEBUG_printf(("_sspiConnect: server unexpectedly disconnected"));
-        ok = FALSE;
-        goto cleanup;
-      }
-
-      DEBUG_printf(("_sspiConnect: %d bytes of handshake data received",
-                    cbData));
-
-      conn->decryptBufferUsed += cbData;
-    }
-
-   /*
-    * Set up the input buffers. Buffer 0 is used to pass in data
-    * received from the server. Schannel will consume some or all
-    * of this. Leftover data (if any) will be placed in buffer 1 and
-    * given a buffer type of SECBUFFER_EXTRA.
-    */
-    inBuffers[0].pvBuffer   = conn->decryptBuffer;
-    inBuffers[0].cbBuffer   = (unsigned long) conn->decryptBufferUsed;
-    inBuffers[0].BufferType = SECBUFFER_TOKEN;
-
-    inBuffers[1].pvBuffer   = NULL;
-    inBuffers[1].cbBuffer   = 0;
-    inBuffers[1].BufferType = SECBUFFER_EMPTY;
-
-    inBuffer.cBuffers       = 2;
-    inBuffer.pBuffers       = inBuffers;
-    inBuffer.ulVersion      = SECBUFFER_VERSION;
-
-   /*
-    * Set up the output buffers. These are initialized to NULL
-    * so as to make it less likely we'll attempt to free random
-    * garbage later.
-    */
-    outBuffers[0].pvBuffer  = NULL;
-    outBuffers[0].BufferType= SECBUFFER_TOKEN;
-    outBuffers[0].cbBuffer  = 0;
-
-    outBuffer.cBuffers      = 1;
-    outBuffer.pBuffers      = outBuffers;
-    outBuffer.ulVersion     = SECBUFFER_VERSION;
-
-   /*
-    * Call InitializeSecurityContext.
-    */
-    scRet = InitializeSecurityContext(&conn->creds, &conn->context, NULL, dwSSPIFlags,
-                                      0, SECURITY_NATIVE_DREP, &inBuffer, 0, NULL,
-                                      &outBuffer, &dwSSPIOutFlags, &tsExpiry);
-
-   /*
-    * If InitializeSecurityContext was successful (or if the error was
-    * one of the special extended ones), send the contends of the output
-    * buffer to the server.
-    */
-    if (scRet == SEC_E_OK                ||
-        scRet == SEC_I_CONTINUE_NEEDED   ||
-        FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
-    {
-      if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
-      {
-        cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
-
-        if ((cbData == SOCKET_ERROR) || !cbData)
-        {
-          DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError()));
-          FreeContextBuffer(outBuffers[0].pvBuffer);
-          DeleteSecurityContext(&conn->context);
-          ok = FALSE;
-          goto cleanup;
-        }
-
-        DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData));
-
-       /*
-        * Free output buffer.
-        */
-        FreeContextBuffer(outBuffers[0].pvBuffer);
-        outBuffers[0].pvBuffer = NULL;
-      }
-    }
-
-   /*
-    * If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE,
-    * then we need to read more data from the server and try again.
-    */
-    if (scRet == SEC_E_INCOMPLETE_MESSAGE)
-      continue;
-
-   /*
-    * If InitializeSecurityContext returned SEC_E_OK, then the
-    * handshake completed successfully.
-    */
-    if (scRet == SEC_E_OK)
-    {
-     /*
-      * If the "extra" buffer contains data, this is encrypted application
-      * protocol layer stuff. It needs to be saved. The application layer
-      * will later decrypt it with DecryptMessage.
-      */
-      DEBUG_printf(("_sspiConnect: Handshake was successful"));
-
-      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
-      {
-        if (conn->decryptBufferLength < inBuffers[1].cbBuffer)
-        {
-          conn->decryptBuffer = realloc(conn->decryptBuffer, inBuffers[1].cbBuffer);
-
-          if (!conn->decryptBuffer)
-          {
-            DEBUG_printf(("_sspiConnect: unable to allocate %d bytes for decrypt buffer",
-                          inBuffers[1].cbBuffer));
-            SetLastError(E_OUTOFMEMORY);
-            ok = FALSE;
-            goto cleanup;
-          }
-        }
-
-        memmove(conn->decryptBuffer,
-                conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer),
-                inBuffers[1].cbBuffer);
-
-        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
-
-        DEBUG_printf(("_sspiConnect: %d bytes of app data was bundled with handshake data",
-                      conn->decryptBufferUsed));
-      }
-      else
-        conn->decryptBufferUsed = 0;
-
-     /*
-      * Bail out to quit
-      */
-      break;
-    }
-
-   /*
-    * Check for fatal error.
-    */
-    if (FAILED(scRet))
-    {
-      DEBUG_printf(("_sspiConnect: InitializeSecurityContext(2) failed: %x", scRet));
-      ok = FALSE;
-      break;
-    }
-
-   /*
-    * If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS,
-    * then the server just requested client authentication.
-    */
-    if (scRet == SEC_I_INCOMPLETE_CREDENTIALS)
-    {
-     /*
-      * Unimplemented
-      */
-      DEBUG_printf(("_sspiConnect: server requested client credentials"));
-      ok = FALSE;
-      break;
-    }
-
-   /*
-    * Copy any leftover data from the "extra" buffer, and go around
-    * again.
-    */
-    if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
-    {
-      memmove(conn->decryptBuffer,
-              conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer),
-              inBuffers[1].cbBuffer);
-
-      conn->decryptBufferUsed = inBuffers[1].cbBuffer;
-    }
-    else
-    {
-      conn->decryptBufferUsed = 0;
-    }
-  }
-
-  if (ok)
-  {
-    conn->contextInitialized = TRUE;
-
-   /*
-    * Get the server cert
-    */
-    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (VOID*) &serverCert );
-
-    if (scRet != SEC_E_OK)
-    {
-      DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_REMOTE_CERT_CONTEXT): %x", scRet));
-      ok = FALSE;
-      goto cleanup;
-    }
-
-    scRet = sspi_verify_certificate(serverCert, hostname, conn->certFlags);
-
-    if (scRet != SEC_E_OK)
-    {
-      DEBUG_printf(("_sspiConnect: sspi_verify_certificate failed: %x", scRet));
-      ok = FALSE;
-      goto cleanup;
-    }
-
-   /*
-    * Find out how big the header/trailer will be:
-    */
-    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes);
-
-    if (scRet != SEC_E_OK)
-    {
-      DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_STREAM_SIZES): %x", scRet));
-      ok = FALSE;
-    }
-  }
-
-cleanup:
-
-  if (serverCert)
-    CertFreeCertificateContext(serverCert);
-
-  return (ok);
-}
-
-
-/*
- * '_sspiAccept()' - Accept an SSL/TLS connection
- */
-BOOL                                   /* O - 1 on success, 0 on failure */
-_sspiAccept(_sspi_struct_t *conn)      /* I  - Client connection */
-{
-  DWORD                        dwSSPIFlags;    /* SSL connection attributes we want */
-  DWORD                        dwSSPIOutFlags; /* SSL connection attributes we got */
-  TimeStamp            tsExpiry;       /* Time stamp */
-  SECURITY_STATUS      scRet;          /* SSPI Status */
-  SecBufferDesc                inBuffer;       /* Array of SecBuffer structs */
-  SecBuffer            inBuffers[2];   /* Security package buffer */
-  SecBufferDesc                outBuffer;      /* Array of SecBuffer structs */
-  SecBuffer            outBuffers[1];  /* Security package buffer */
-  DWORD                        num = 0;        /* 32 bit status value */
-  BOOL                 fInitContext = TRUE;
-                                       /* Has the context been init'd? */
-  BOOL                 ok = TRUE;      /* Return value */
-
-  if (!conn)
-    return (FALSE);
-
-  dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT  |
-                ASC_REQ_REPLAY_DETECT    |
-                ASC_REQ_CONFIDENTIALITY  |
-                ASC_REQ_EXTENDED_ERROR   |
-                ASC_REQ_ALLOCATE_MEMORY  |
-                ASC_REQ_STREAM;
-
-  conn->decryptBufferUsed = 0;
-
- /*
-  * Set OutBuffer for AcceptSecurityContext call
-  */
-  outBuffer.cBuffers = 1;
-  outBuffer.pBuffers = outBuffers;
-  outBuffer.ulVersion = SECBUFFER_VERSION;
-
-  scRet = SEC_I_CONTINUE_NEEDED;
-
-  while (scRet == SEC_I_CONTINUE_NEEDED    ||
-         scRet == SEC_E_INCOMPLETE_MESSAGE ||
-         scRet == SEC_I_INCOMPLETE_CREDENTIALS)
-  {
-    if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE))
-    {
-      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
-      {
-        conn->decryptBufferLength += 4096;
-        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer,
-                                              conn->decryptBufferLength);
-
-        if (!conn->decryptBuffer)
-        {
-          DEBUG_printf(("_sspiAccept: unable to allocate %d byte decrypt buffer",
-                        conn->decryptBufferLength));
-          ok = FALSE;
-          goto cleanup;
-        }
-      }
-
-      for (;;)
-      {
-        num = recv(conn->sock,
-                   conn->decryptBuffer + conn->decryptBufferUsed,
-                   (int)(conn->decryptBufferLength - conn->decryptBufferUsed),
-                   0);
-
-        if ((num == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
-          Sleep(1);
-        else
-          break;
-      }
-
-      if (num == SOCKET_ERROR)
-      {
-        DEBUG_printf(("_sspiAccept: recv failed: %d", WSAGetLastError()));
-        ok = FALSE;
-        goto cleanup;
-      }
-      else if (num == 0)
-      {
-        DEBUG_printf(("_sspiAccept: client disconnected"));
-        ok = FALSE;
-        goto cleanup;
-      }
-
-      DEBUG_printf(("_sspiAccept: received %d (handshake) bytes from client",
-                    num));
-      conn->decryptBufferUsed += num;
-    }
-
-   /*
-    * InBuffers[1] is for getting extra data that
-    * SSPI/SCHANNEL doesn't proccess on this
-    * run around the loop.
-    */
-    inBuffers[0].pvBuffer   = conn->decryptBuffer;
-    inBuffers[0].cbBuffer   = (unsigned long) conn->decryptBufferUsed;
-    inBuffers[0].BufferType = SECBUFFER_TOKEN;
-
-    inBuffers[1].pvBuffer   = NULL;
-    inBuffers[1].cbBuffer   = 0;
-    inBuffers[1].BufferType = SECBUFFER_EMPTY;
-
-    inBuffer.cBuffers       = 2;
-    inBuffer.pBuffers       = inBuffers;
-    inBuffer.ulVersion      = SECBUFFER_VERSION;
-
-   /*
-    * Initialize these so if we fail, pvBuffer contains NULL,
-    * so we don't try to free random garbage at the quit
-    */
-    outBuffers[0].pvBuffer   = NULL;
-    outBuffers[0].BufferType = SECBUFFER_TOKEN;
-    outBuffers[0].cbBuffer   = 0;
-
-    scRet = AcceptSecurityContext(&conn->creds, (fInitContext?NULL:&conn->context),
-                                  &inBuffer, dwSSPIFlags, SECURITY_NATIVE_DREP,
-                                  (fInitContext?&conn->context:NULL), &outBuffer,
-                                  &dwSSPIOutFlags, &tsExpiry);
-
-    fInitContext = FALSE;
-
-    if (scRet == SEC_E_OK              ||
-        scRet == SEC_I_CONTINUE_NEEDED ||
-        (FAILED(scRet) && ((dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR) != 0)))
-    {
-      if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
-      {
-       /*
-        * Send response to server if there is one
-        */
-        num = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
-
-        if ((num == SOCKET_ERROR) || (num == 0))
-        {
-          DEBUG_printf(("_sspiAccept: handshake send failed: %d", WSAGetLastError()));
-          ok = FALSE;
-          goto cleanup;
-        }
-
-        DEBUG_printf(("_sspiAccept: send %d handshake bytes to client",
-                     outBuffers[0].cbBuffer));
-
-        FreeContextBuffer(outBuffers[0].pvBuffer);
-        outBuffers[0].pvBuffer = NULL;
-      }
-    }
-
-    if (scRet == SEC_E_OK)
-    {
-     /*
-      * If there's extra data then save it for
-      * next time we go to decrypt
-      */
-      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
-      {
-        memcpy(conn->decryptBuffer,
-               (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)),
-               inBuffers[1].cbBuffer);
-        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
-      }
-      else
-      {
-        conn->decryptBufferUsed = 0;
-      }
-
-      ok = TRUE;
-      break;
-    }
-    else if (FAILED(scRet) && (scRet != SEC_E_INCOMPLETE_MESSAGE))
-    {
-      DEBUG_printf(("_sspiAccept: AcceptSecurityContext failed: %x", scRet));
-      ok = FALSE;
-      break;
-    }
-
-    if (scRet != SEC_E_INCOMPLETE_MESSAGE &&
-        scRet != SEC_I_INCOMPLETE_CREDENTIALS)
-    {
-      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
-      {
-        memcpy(conn->decryptBuffer,
-               (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)),
-               inBuffers[1].cbBuffer);
-        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
-      }
-      else
-      {
-        conn->decryptBufferUsed = 0;
-      }
-    }
-  }
-
-  if (ok)
-  {
-    conn->contextInitialized = TRUE;
-
-   /*
-    * Find out how big the header will be:
-    */
-    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes);
-
-    if (scRet != SEC_E_OK)
-    {
-      DEBUG_printf(("_sspiAccept: QueryContextAttributes failed: %x", scRet));
-      ok = FALSE;
-    }
-  }
-
-cleanup:
-
-  return (ok);
-}
-
-
-/*
- * '_sspiSetAllowsAnyRoot()' - Set the client cert policy for untrusted root certs
- */
-void
-_sspiSetAllowsAnyRoot(_sspi_struct_t *conn,
-                                       /* I  - Client connection */
-                      BOOL           allow)
-                                       /* I  - Allow any root */
-{
-  conn->certFlags = (allow) ? conn->certFlags | SECURITY_FLAG_IGNORE_UNKNOWN_CA :
-                              conn->certFlags & ~SECURITY_FLAG_IGNORE_UNKNOWN_CA;
-}
-
-
-/*
- * '_sspiSetAllowsExpiredCerts()' - Set the client cert policy for expired root certs
- */
-void
-_sspiSetAllowsExpiredCerts(_sspi_struct_t *conn,
-                                       /* I  - Client connection */
-                           BOOL           allow)
-                                       /* I  - Allow expired certs */
-{
-  conn->certFlags = (allow) ? conn->certFlags | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID :
-                              conn->certFlags & ~SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
-}
-
-
-/*
- * '_sspiWrite()' - Write a buffer to an ssl socket
- */
-int                                    /* O  - Bytes written or SOCKET_ERROR */
-_sspiWrite(_sspi_struct_t *conn,       /* I  - Client connection */
-           void           *buf,                /* I  - Buffer */
-           size_t         len)         /* I  - Buffer length */
-{
-  SecBufferDesc        message;                /* Array of SecBuffer struct */
-  SecBuffer    buffers[4] = { 0 };     /* Security package buffer */
-  BYTE         *buffer = NULL;         /* Scratch buffer */
-  int          bufferLen;              /* Buffer length */
-  size_t       bytesLeft;              /* Bytes left to write */
-  int          index = 0;              /* Index into buffer */
-  int          num = 0;                /* Return value */
-
-  if (!conn || !buf || !len)
-  {
-    WSASetLastError(WSAEINVAL);
-    num = SOCKET_ERROR;
-    goto cleanup;
-  }
-
-  bufferLen = conn->streamSizes.cbMaximumMessage +
-              conn->streamSizes.cbHeader +
-              conn->streamSizes.cbTrailer;
-
-  buffer = (BYTE*) malloc(bufferLen);
-
-  if (!buffer)
-  {
-    DEBUG_printf(("_sspiWrite: buffer alloc of %d bytes failed", bufferLen));
-    WSASetLastError(E_OUTOFMEMORY);
-    num = SOCKET_ERROR;
-    goto cleanup;
-  }
-
-  bytesLeft = len;
-
-  while (bytesLeft)
-  {
-    size_t chunk = min(conn->streamSizes.cbMaximumMessage,     /* Size of data to write */
-                       bytesLeft);
-    SECURITY_STATUS scRet;                                     /* SSPI status */
-
-   /*
-    * Copy user data into the buffer, starting
-    * just past the header
-    */
-    memcpy(buffer + conn->streamSizes.cbHeader,
-           ((BYTE*) buf) + index,
-           chunk);
-
-   /*
-    * Setup the SSPI buffers
-    */
-    message.ulVersion = SECBUFFER_VERSION;
-    message.cBuffers = 4;
-    message.pBuffers = buffers;
-    buffers[0].pvBuffer = buffer;
-    buffers[0].cbBuffer = conn->streamSizes.cbHeader;
-    buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
-    buffers[1].pvBuffer = buffer + conn->streamSizes.cbHeader;
-    buffers[1].cbBuffer = (unsigned long) chunk;
-    buffers[1].BufferType = SECBUFFER_DATA;
-    buffers[2].pvBuffer = buffer + conn->streamSizes.cbHeader + chunk;
-    buffers[2].cbBuffer = conn->streamSizes.cbTrailer;
-    buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
-    buffers[3].BufferType = SECBUFFER_EMPTY;
-
-   /*
-    * Encrypt the data
-    */
-    scRet = EncryptMessage(&conn->context, 0, &message, 0);
-
-    if (FAILED(scRet))
-    {
-      DEBUG_printf(("_sspiWrite: EncryptMessage failed: %x", scRet));
-      WSASetLastError(WSASYSCALLFAILURE);
-      num = SOCKET_ERROR;
-      goto cleanup;
-    }
-
-   /*
-    * Send the data. Remember the size of
-    * the total data to send is the size
-    * of the header, the size of the data
-    * the caller passed in and the size
-    * of the trailer
-    */
-    num = send(conn->sock,
-               buffer,
-               buffers[0].cbBuffer + buffers[1].cbBuffer + buffers[2].cbBuffer,
-               0);
-
-    if ((num == SOCKET_ERROR) || (num == 0))
-    {
-      DEBUG_printf(("_sspiWrite: send failed: %ld", WSAGetLastError()));
-      goto cleanup;
-    }
-
-    bytesLeft -= (int) chunk;
-    index += (int) chunk;
-  }
-
-  num = (int) len;
-
-cleanup:
-
-  if (buffer)
-    free(buffer);
-
-  return (num);
-}
-
-
-/*
- * '_sspiRead()' - Read a buffer from an ssl socket
- */
-int                                    /* O  - Bytes read or SOCKET_ERROR */
-_sspiRead(_sspi_struct_t *conn,                /* I  - Client connection */
-          void           *buf,         /* I  - Buffer */
-          size_t         len)          /* I  - Buffer length */
-{
-  SecBufferDesc        message;                /* Array of SecBuffer struct */
-  SecBuffer    buffers[4] = { 0 };     /* Security package buffer */
-  int          num = 0;                /* Return value */
-
-  if (!conn)
-  {
-    WSASetLastError(WSAEINVAL);
-    num = SOCKET_ERROR;
-    goto cleanup;
-  }
-
- /*
-  * If there are bytes that have already been
-  * decrypted and have not yet been read, return
-  * those
-  */
-  if (buf && (conn->readBufferUsed > 0))
-  {
-    int bytesToCopy = (int) min(conn->readBufferUsed, len);    /* Amount of bytes to copy */
-                                                               /* from read buffer */
-
-    memcpy(buf, conn->readBuffer, bytesToCopy);
-    conn->readBufferUsed -= bytesToCopy;
-
-    if (conn->readBufferUsed > 0)
-     /*
-      * If the caller didn't request all the bytes
-      * we have in the buffer, then move the unread
-      * bytes down
-      */
-      memmove(conn->readBuffer,
-              conn->readBuffer + bytesToCopy,
-              conn->readBufferUsed);
-
-    num = bytesToCopy;
-  }
-  else
-  {
-    PSecBuffer         pDataBuffer;    /* Data buffer */
-    PSecBuffer         pExtraBuffer;   /* Excess data buffer */
-    SECURITY_STATUS    scRet;          /* SSPI status */
-    int                        i;              /* Loop control variable */
-
-   /*
-    * Initialize security buffer structs
-    */
-    message.ulVersion = SECBUFFER_VERSION;
-    message.cBuffers = 4;
-    message.pBuffers = buffers;
-
-    do
-    {
-     /*
-      * If there is not enough space in the
-      * buffer, then increase it's size
-      */
-      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
-      {
-        conn->decryptBufferLength += 4096;
-        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer,
-                                              conn->decryptBufferLength);
-
-        if (!conn->decryptBuffer)
-        {
-          DEBUG_printf(("_sspiRead: unable to allocate %d byte buffer",
-                        conn->decryptBufferLength));
-          WSASetLastError(E_OUTOFMEMORY);
-          num = SOCKET_ERROR;
-          goto cleanup;
-        }
-      }
-
-      buffers[0].pvBuffer      = conn->decryptBuffer;
-      buffers[0].cbBuffer      = (unsigned long) conn->decryptBufferUsed;
-      buffers[0].BufferType    = SECBUFFER_DATA;
-      buffers[1].BufferType    = SECBUFFER_EMPTY;
-      buffers[2].BufferType    = SECBUFFER_EMPTY;
-      buffers[3].BufferType    = SECBUFFER_EMPTY;
-
-      scRet = DecryptMessage(&conn->context, &message, 0, NULL);
-
-      if (scRet == SEC_E_INCOMPLETE_MESSAGE)
-      {
-        if (buf)
-        {
-          num = recv(conn->sock,
-                     conn->decryptBuffer + conn->decryptBufferUsed,
-                     (int)(conn->decryptBufferLength - conn->decryptBufferUsed),
-                     0);
-          if (num == SOCKET_ERROR)
-          {
-            DEBUG_printf(("_sspiRead: recv failed: %d", WSAGetLastError()));
-            goto cleanup;
-          }
-          else if (num == 0)
-          {
-            DEBUG_printf(("_sspiRead: server disconnected"));
-            goto cleanup;
-          }
-
-          conn->decryptBufferUsed += num;
-        }
-        else
-        {
-          num = (int) conn->readBufferUsed;
-          goto cleanup;
-        }
-      }
-    }
-    while (scRet == SEC_E_INCOMPLETE_MESSAGE);
-
-    if (scRet == SEC_I_CONTEXT_EXPIRED)
-    {
-      DEBUG_printf(("_sspiRead: context expired"));
-      WSASetLastError(WSAECONNRESET);
-      num = SOCKET_ERROR;
-      goto cleanup;
-    }
-    else if (scRet != SEC_E_OK)
-    {
-      DEBUG_printf(("_sspiRead: DecryptMessage failed: %lx", scRet));
-      WSASetLastError(WSASYSCALLFAILURE);
-      num = SOCKET_ERROR;
-      goto cleanup;
-    }
-
-   /*
-    * The decryption worked.  Now, locate data buffer.
-    */
-    pDataBuffer  = NULL;
-    pExtraBuffer = NULL;
-    for (i = 1; i < 4; i++)
-    {
-      if (buffers[i].BufferType == SECBUFFER_DATA)
-        pDataBuffer = &buffers[i];
-      else if (!pExtraBuffer && (buffers[i].BufferType == SECBUFFER_EXTRA))
-        pExtraBuffer = &buffers[i];
-    }
-
-   /*
-    * If a data buffer is found, then copy
-    * the decrypted bytes to the passed-in
-    * buffer
-    */
-    if (pDataBuffer)
-    {
-      int bytesToCopy = min(pDataBuffer->cbBuffer, (int) len);
-                                       /* Number of bytes to copy into buf */
-      int bytesToSave = pDataBuffer->cbBuffer - bytesToCopy;
-                                       /* Number of bytes to save in our read buffer */
-
-      if (bytesToCopy)
-        memcpy(buf, pDataBuffer->pvBuffer, bytesToCopy);
-
-     /*
-      * If there are more decrypted bytes than can be
-      * copied to the passed in buffer, then save them
-      */
-      if (bytesToSave)
-      {
-        if ((int)(conn->readBufferLength - conn->readBufferUsed) < bytesToSave)
-        {
-          conn->readBufferLength = conn->readBufferUsed + bytesToSave;
-          conn->readBuffer = realloc(conn->readBuffer,
-                                     conn->readBufferLength);
-
-          if (!conn->readBuffer)
-          {
-            DEBUG_printf(("_sspiRead: unable to allocate %d bytes", conn->readBufferLength));
-            WSASetLastError(E_OUTOFMEMORY);
-            num = SOCKET_ERROR;
-            goto cleanup;
-          }
-        }
-
-        memcpy(((BYTE*) conn->readBuffer) + conn->readBufferUsed,
-               ((BYTE*) pDataBuffer->pvBuffer) + bytesToCopy,
-               bytesToSave);
-
-        conn->readBufferUsed += bytesToSave;
-      }
-
-      num = (buf) ? bytesToCopy : (int) conn->readBufferUsed;
-    }
-    else
-    {
-      DEBUG_printf(("_sspiRead: unable to find data buffer"));
-      WSASetLastError(WSASYSCALLFAILURE);
-      num = SOCKET_ERROR;
-      goto cleanup;
-    }
-
-   /*
-    * If the decryption process left extra bytes,
-    * then save those back in decryptBuffer. They will
-    * be processed the next time through the loop.
-    */
-    if (pExtraBuffer)
-    {
-      memmove(conn->decryptBuffer, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
-      conn->decryptBufferUsed = pExtraBuffer->cbBuffer;
-    }
-    else
-    {
-      conn->decryptBufferUsed = 0;
-    }
-  }
-
-cleanup:
-
-  return (num);
-}
-
-
-/*
- * '_sspiPending()' - Returns the number of available bytes
- */
-int                                    /* O  - Number of available bytes */
-_sspiPending(_sspi_struct_t *conn)     /* I  - Client connection */
-{
-  return (_sspiRead(conn, NULL, 0));
-}
-
-
-/*
- * '_sspiFree()' - Close a connection and free resources
- */
-void
-_sspiFree(_sspi_struct_t *conn)                /* I  - Client connection */
-{
-  if (!conn)
-    return;
-
-  if (conn->contextInitialized)
-  {
-    SecBufferDesc      message;        /* Array of SecBuffer struct */
-    SecBuffer          buffers[1] = { 0 };
-                                       /* Security package buffer */
-    DWORD              dwType;         /* Type */
-    DWORD              status;         /* Status */
-
-  /*
-   * Notify schannel that we are about to close the connection.
-   */
-   dwType = SCHANNEL_SHUTDOWN;
-
-   buffers[0].pvBuffer   = &dwType;
-   buffers[0].BufferType = SECBUFFER_TOKEN;
-   buffers[0].cbBuffer   = sizeof(dwType);
-
-   message.cBuffers  = 1;
-   message.pBuffers  = buffers;
-   message.ulVersion = SECBUFFER_VERSION;
-
-   status = ApplyControlToken(&conn->context, &message);
-
-   if (SUCCEEDED(status))
-   {
-     PBYTE     pbMessage;              /* Message buffer */
-     DWORD     cbMessage;              /* Message buffer count */
-     DWORD     cbData;                 /* Data count */
-     DWORD     dwSSPIFlags;            /* SSL attributes we requested */
-     DWORD     dwSSPIOutFlags;         /* SSL attributes we received */
-     TimeStamp tsExpiry;               /* Time stamp */
-
-     dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT     |
-                   ASC_REQ_REPLAY_DETECT       |
-                   ASC_REQ_CONFIDENTIALITY     |
-                   ASC_REQ_EXTENDED_ERROR      |
-                   ASC_REQ_ALLOCATE_MEMORY     |
-                   ASC_REQ_STREAM;
-
-     buffers[0].pvBuffer   = NULL;
-     buffers[0].BufferType = SECBUFFER_TOKEN;
-     buffers[0].cbBuffer   = 0;
-
-     message.cBuffers  = 1;
-     message.pBuffers  = buffers;
-     message.ulVersion = SECBUFFER_VERSION;
-
-     status = AcceptSecurityContext(&conn->creds, &conn->context, NULL,
-                                    dwSSPIFlags, SECURITY_NATIVE_DREP, NULL,
-                                    &message, &dwSSPIOutFlags, &tsExpiry);
-
-      if (SUCCEEDED(status))
-      {
-        pbMessage = buffers[0].pvBuffer;
-        cbMessage = buffers[0].cbBuffer;
-
-       /*
-        * Send the close notify message to the client.
-        */
-        if (pbMessage && cbMessage)
-        {
-          cbData = send(conn->sock, pbMessage, cbMessage, 0);
-          if ((cbData == SOCKET_ERROR) || (cbData == 0))
-          {
-            status = WSAGetLastError();
-            DEBUG_printf(("_sspiFree: sending close notify failed: %d", status));
-          }
-          else
-          {
-            FreeContextBuffer(pbMessage);
-          }
-        }
-      }
-      else
-      {
-        DEBUG_printf(("_sspiFree: AcceptSecurityContext failed: %x", status));
-      }
-    }
-    else
-    {
-      DEBUG_printf(("_sspiFree: ApplyControlToken failed: %x", status));
-    }
-
-    DeleteSecurityContext(&conn->context);
-    conn->contextInitialized = FALSE;
-  }
-
-  if (conn->decryptBuffer)
-  {
-    free(conn->decryptBuffer);
-    conn->decryptBuffer = NULL;
-  }
-
-  if (conn->readBuffer)
-  {
-    free(conn->readBuffer);
-    conn->readBuffer = NULL;
-  }
-
-  if (conn->sock != INVALID_SOCKET)
-  {
-    closesocket(conn->sock);
-    conn->sock = INVALID_SOCKET;
-  }
-
-  free(conn);
-}
-
-
-/*
- * 'sspi_verify_certificate()' - Verify a server certificate
- */
-static DWORD                           /* 0  - Error code (0 == No error) */
-sspi_verify_certificate(PCCERT_CONTEXT  serverCert,
-                                       /* I  - Server certificate */
-                        const CHAR      *serverName,
-                                       /* I  - Server name */
-                        DWORD           dwCertFlags)
-                                       /* I  - Verification flags */
-{
-  HTTPSPolicyCallbackData      httpsPolicy;
-                                       /* HTTPS Policy Struct */
-  CERT_CHAIN_POLICY_PARA       policyPara;
-                                       /* Cert chain policy parameters */
-  CERT_CHAIN_POLICY_STATUS     policyStatus;
-                                       /* Cert chain policy status */
-  CERT_CHAIN_PARA              chainPara;
-                                       /* Used for searching and matching criteria */
-  PCCERT_CHAIN_CONTEXT         chainContext = NULL;
-                                       /* Certificate chain */
-  PWSTR                                serverNameUnicode = NULL;
-                                       /* Unicode server name */
-  LPSTR                                rgszUsages[] = { szOID_PKIX_KP_SERVER_AUTH,
-                                                 szOID_SERVER_GATED_CRYPTO,
-                                                 szOID_SGC_NETSCAPE };
-                                       /* How are we using this certificate? */
-  DWORD                                cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
-                                       /* Number of ites in rgszUsages */
-  DWORD                                count;  /* 32 bit count variable */
-  DWORD                                status; /* Return value */
-
-  if (!serverCert)
-  {
-    status = SEC_E_WRONG_PRINCIPAL;
-    goto cleanup;
-  }
-
- /*
-  *  Convert server name to unicode.
-  */
-  if (!serverName || (strlen(serverName) == 0))
-  {
-    status = SEC_E_WRONG_PRINCIPAL;
-    goto cleanup;
-  }
-
-  count = MultiByteToWideChar(CP_ACP, 0, serverName, -1, NULL, 0);
-  serverNameUnicode = LocalAlloc(LMEM_FIXED, count * sizeof(WCHAR));
-  if (!serverNameUnicode)
-  {
-    status = SEC_E_INSUFFICIENT_MEMORY;
-    goto cleanup;
-  }
-  count = MultiByteToWideChar(CP_ACP, 0, serverName, -1, serverNameUnicode, count);
-  if (count == 0)
-  {
-    status = SEC_E_WRONG_PRINCIPAL;
-    goto cleanup;
-  }
-
- /*
-  * Build certificate chain.
-  */
-  ZeroMemory(&chainPara, sizeof(chainPara));
-  chainPara.cbSize                                     = sizeof(chainPara);
-  chainPara.RequestedUsage.dwType                      = USAGE_MATCH_TYPE_OR;
-  chainPara.RequestedUsage.Usage.cUsageIdentifier      = cUsages;
-  chainPara.RequestedUsage.Usage.rgpszUsageIdentifier  = rgszUsages;
-
-  if (!CertGetCertificateChain(NULL, serverCert, NULL, serverCert->hCertStore,
-                               &chainPara, 0, NULL, &chainContext))
-  {
-    status = GetLastError();
-    DEBUG_printf(("CertGetCertificateChain returned 0x%x\n", status));
-    goto cleanup;
-  }
-
- /*
-  * Validate certificate chain.
-  */
-  ZeroMemory(&httpsPolicy, sizeof(HTTPSPolicyCallbackData));
-  httpsPolicy.cbStruct         = sizeof(HTTPSPolicyCallbackData);
-  httpsPolicy.dwAuthType       = AUTHTYPE_SERVER;
-  httpsPolicy.fdwChecks                = dwCertFlags;
-  httpsPolicy.pwszServerName   = serverNameUnicode;
-
-  memset(&policyPara, 0, sizeof(policyPara));
-  policyPara.cbSize            = sizeof(policyPara);
-  policyPara.pvExtraPolicyPara = &httpsPolicy;
-
-  memset(&policyStatus, 0, sizeof(policyStatus));
-  policyStatus.cbSize = sizeof(policyStatus);
-
-  if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, chainContext,
-                                        &policyPara, &policyStatus))
-  {
-    status = GetLastError();
-    DEBUG_printf(("CertVerifyCertificateChainPolicy returned %d", status));
-    goto cleanup;
-  }
-
-  if (policyStatus.dwError)
-  {
-    status = policyStatus.dwError;
-    goto cleanup;
-  }
-
-  status = SEC_E_OK;
-
-cleanup:
-
-  if (chainContext)
-    CertFreeCertificateChain(chainContext);
-
-  if (serverNameUnicode)
-    LocalFree(serverNameUnicode);
-
-  return (status);
-}
-
-
-/*
- * End of "$Id: sspi.c 11760 2014-03-28 12:58:24Z msweet $".
- */