]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Set last error string to Windows error message.
authorMichael R Sweet <michael.r.sweet@gmail.com>
Fri, 4 Mar 2022 00:56:45 +0000 (19:56 -0500)
committerMichael R Sweet <michael.r.sweet@gmail.com>
Fri, 4 Mar 2022 00:57:34 +0000 (19:57 -0500)
cups/tls-sspi.c

index 6c3dd0158035c1dd00d8ef1492acc101887e75cc..f3fb0f1e24c68cc2cd90f2a3a325f0c24a7e2b60 100644 (file)
@@ -64,16 +64,13 @@ static BOOL http_sspi_find_credentials(http_t *http, const LPWSTR containerName,
 static void    http_sspi_free(_http_sspi_t *sspi);
 static BOOL    http_sspi_make_credentials(_http_sspi_t *sspi, const LPWSTR containerName, const char *common_name, _http_mode_t mode, int years);
 static int     http_sspi_server(http_t *http, const char *hostname);
-static void    http_sspi_set_allows_any_root(_http_sspi_t *sspi, BOOL allow);
-static void    http_sspi_set_allows_expired_certs(_http_sspi_t *sspi, BOOL allow);
+static void    http_sspi_set_error(const char *title);
 static const char *http_sspi_strerror(char *buffer, size_t bufsize, DWORD code);
 static DWORD   http_sspi_verify(PCCERT_CONTEXT cert, const char *common_name, DWORD dwCertFlags);
 
 
 /*
  * 'cupsMakeServerCredentials()' - Make a self-signed certificate and private key pair.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -108,8 +105,6 @@ cupsMakeServerCredentials(
  *
  * Note: The server credentials are used by all threads in the running process.
  * This function is threadsafe.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -131,8 +126,6 @@ cupsSetServerCredentials(
 /*
  * 'httpCopyCredentials()' - Copy the credentials associated with the peer in
  *                           an encrypted connection.
- *
- * @since CUPS 1.5/macOS 10.7@
  */
 
 int                                    /* O - Status of call (0 = success) */
@@ -171,8 +164,6 @@ _httpCreateCredentials(
 
 /*
  * 'httpCredentialsAreValidForName()' - Return whether the credentials are valid for the given name.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 int                                    /* O - 1 if valid, 0 otherwise */
@@ -236,8 +227,6 @@ httpCredentialsAreValidForName(
 
 /*
  * 'httpCredentialsGetTrust()' - Return the trust of credentials.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 http_trust_t                           /* O - Level of trust */
@@ -281,8 +270,6 @@ httpCredentialsGetTrust(
 
 /*
  * 'httpCredentialsGetExpiration()' - Return the expiration date of the credentials.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 time_t                                 /* O - Expiration date of credentials */
@@ -318,8 +305,6 @@ httpCredentialsGetExpiration(
 
 /*
  * 'httpCredentialsString()' - Return a string representing the credentials.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 size_t                                 /* O - Total size of credentials string */
@@ -405,8 +390,6 @@ _httpFreeCredentials(
 
 /*
  * 'httpLoadCredentials()' - Load X.509 credentials from a keychain file.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 int                                    /* O - 0 on success, -1 on error */
@@ -454,6 +437,7 @@ httpLoadCredentials(
       if (!CryptAcquireContextW(&hProv, L"RememberedContainer", MS_DEF_PROV_W, PROV_RSA_FULL, 0 /*CRYPT_MACHINE_KEYSET*/))
       {
         DEBUG_printf(("1httpLoadCredentials: CryptAcquireContext failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+        http_sspi_set_error("CryptAquireContext");
         goto cleanup;
       }
     }
@@ -464,6 +448,7 @@ httpLoadCredentials(
   if (!store)
   {
     DEBUG_printf(("1httpLoadCredentials: CertOpenSystemStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertOpenSystemStore");
     goto cleanup;
   }
 
@@ -472,6 +457,7 @@ httpLoadCredentials(
   if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
   {
     DEBUG_printf(("1httpLoadCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertStrToName");
     goto cleanup;
   }
 
@@ -480,12 +466,14 @@ httpLoadCredentials(
   if (!p)
   {
     DEBUG_printf(("1httpLoadCredentials: malloc failed for %d bytes.", dwSize));
+    _cupsSetHTTPError(HTTP_STATUS_ERROR);
     goto cleanup;
   }
 
   if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
   {
     DEBUG_printf(("1httpLoadCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertStrToName");
     goto cleanup;
   }
 
@@ -529,8 +517,6 @@ cleanup:
 
 /*
  * 'httpSaveCredentials()' - Save X.509 credentials to a keychain file.
- *
- * @since CUPS 2.0/OS 10.10@
  */
 
 int                                    /* O - -1 on error, 0 on success */
@@ -577,6 +563,7 @@ httpSaveCredentials(
       if (!CryptAcquireContextW(&hProv, L"RememberedContainer", MS_DEF_PROV_W, PROV_RSA_FULL, 0 /*CRYPT_MACHINE_KEYSET*/))
       {
         DEBUG_printf(("1httpSaveCredentials: CryptAcquireContext failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+        http_sspi_set_error("CryptAquireContext");
         goto cleanup;
       }
     }
@@ -587,6 +574,7 @@ httpSaveCredentials(
   if (!store)
   {
     DEBUG_printf(("1httpSaveCredentials: CertOpenSystemStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertOpenSystemStore");
     goto cleanup;
   }
 
@@ -595,6 +583,7 @@ httpSaveCredentials(
   if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
   {
     DEBUG_printf(("1httpSaveCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertStrToName");
     goto cleanup;
   }
 
@@ -603,12 +592,14 @@ httpSaveCredentials(
   if (!p)
   {
     DEBUG_printf(("1httpSaveCredentials: malloc failed for %d bytes.", dwSize));
+    _cupsSetHTTPError(HTTP_STATUS_ERROR);
     goto cleanup;
   }
 
   if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
   {
     DEBUG_printf(("1httpSaveCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertToToName");
     goto cleanup;
   }
 
@@ -620,6 +611,7 @@ httpSaveCredentials(
   if (!CertAddCertificateContextToStore(store, createdContext, CERT_STORE_ADD_REPLACE_EXISTING, &storedContext))
   {
     DEBUG_printf(("1httpSaveCredentials: CertAddCertificateContextToStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertAddCertificateContextToStore");
     goto cleanup;
   }
 
@@ -633,6 +625,7 @@ httpSaveCredentials(
   if (!CertSetCertificateContextProperty(storedContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &ckp))
   {
     DEBUG_printf(("1httpSaveCredentials: CertSetCertificateContextProperty failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+    http_sspi_set_error("CertSetCertificateContextProperty");
     goto cleanup;
   }
 
@@ -811,12 +804,14 @@ _httpTLSRead(http_t *http,                /* I - HTTP connection */
 
   if (scRet == SEC_I_CONTEXT_EXPIRED)
   {
+    http_sspi_set_error("DecryptMessage");
     DEBUG_puts("5_httpTLSRead: Context expired.");
     WSASetLastError(WSAECONNRESET);
     return (-1);
   }
   else if (scRet != SEC_E_OK)
   {
+    http_sspi_set_error("DecryptMessage");
     DEBUG_printf(("5_httpTLSRead: DecryptMessage failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
     WSASetLastError(WSASYSCALLFAILURE);
     return (-1);
@@ -865,6 +860,7 @@ _httpTLSRead(http_t *http,          /* I - HTTP connection */
 
         if ((temp = realloc(sspi->readBuffer, sspi->readBufferUsed + bytesToSave)) == NULL)
        {
+         _cupsSetHTTPError(HTTP_STATUS_ERROR);
          DEBUG_printf(("5_httpTLSRead: Unable to allocate %d bytes.", sspi->readBufferUsed + bytesToSave));
          WSASetLastError(E_OUTOFMEMORY);
          return (-1);
@@ -884,6 +880,7 @@ _httpTLSRead(http_t *http,          /* I - HTTP connection */
   else
   {
     DEBUG_puts("5_httpTLSRead: Unable to find data buffer.");
+    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, "Unable to find data buffer.", 0);
     WSASetLastError(WSASYSCALLFAILURE);
     return (-1);
   }
@@ -1104,11 +1101,13 @@ _httpTLSStop(http_t *http)              /* I - HTTP connection */
       }
       else
       {
+       http_sspi_set_error("AcceptSecurityContext");
         DEBUG_printf(("4_httpTLSStop: AcceptSecurityContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), status)));
       }
     }
     else
     {
+      http_sspi_set_error("ApplyControlToken");
       DEBUG_printf(("4_httpTLSStop: ApplyControlToken failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), status)));
     }
   }
@@ -1145,6 +1144,7 @@ _httpTLSWrite(http_t     *http,           /* I - HTTP connection */
 
     if ((temp = (BYTE *)realloc(sspi->writeBuffer, bufferLen)) == NULL)
     {
+      _cupsSetHTTPError(HTTP_STATUS_ERROR);
       DEBUG_printf(("5_httpTLSWrite: Unable to allocate buffer of %d bytes.", bufferLen));
       WSASetLastError(E_OUTOFMEMORY);
       return (-1);
@@ -1196,6 +1196,7 @@ _httpTLSWrite(http_t     *http,           /* I - HTTP connection */
 
     if (FAILED(scRet))
     {
+      http_sspi_set_error("EncryptMessage");
       DEBUG_printf(("5_httpTLSWrite: EncryptMessage failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
       WSASetLastError(WSASYSCALLFAILURE);
       return (-1);
@@ -1223,94 +1224,6 @@ _httpTLSWrite(http_t     *http,          /* I - HTTP connection */
 }
 
 
-#if 0
-/*
- * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
- */
-
-static int                             /* O - 0 on success, -1 on failure */
-http_setup_ssl(http_t *http)           /* I - Connection to server */
-{
-  char                 hostname[256],  /* Hostname */
-                       *hostptr;       /* Pointer into hostname */
-
-  TCHAR                        username[256];  /* Username returned from GetUserName() */
-  TCHAR                        commonName[256];/* Common name for certificate */
-  DWORD                        dwSize;         /* 32 bit size */
-
-
-  DEBUG_printf(("7http_setup_ssl(http=%p)", http));
-
- /*
-  * Get the hostname to use for SSL...
-  */
-
-  if (httpAddrLocalhost(http->hostaddr))
-  {
-    strlcpy(hostname, "localhost", sizeof(hostname));
-  }
-  else
-  {
-   /*
-    * Otherwise make sure the hostname we have does not end in a trailing dot.
-    */
-
-    strlcpy(hostname, http->hostname, sizeof(hostname));
-    if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
-        *hostptr == '.')
-      *hostptr = '\0';
-  }
-
-  http->tls = http_sspi_alloc();
-
-  if (!http->tls)
-  {
-    _cupsSetHTTPError(HTTP_STATUS_ERROR);
-    return (-1);
-  }
-
-  dwSize          = sizeof(username) / sizeof(TCHAR);
-  GetUserName(username, &dwSize);
-  _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
-               sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
-
-  if (!_sspiGetCredentials(http->tls, L"ClientContainer",
-                           commonName, FALSE))
-  {
-    _sspiFree(http->tls);
-    http->tls = NULL;
-
-    http->error  = EIO;
-    http->status = HTTP_STATUS_ERROR;
-
-    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
-                  _("Unable to establish a secure connection to host."), 1);
-
-    return (-1);
-  }
-
-  _sspiSetAllowsAnyRoot(http->tls, TRUE);
-  _sspiSetAllowsExpiredCerts(http->tls, TRUE);
-
-  if (!_sspiConnect(http->tls, hostname))
-  {
-    _sspiFree(http->tls);
-    http->tls = NULL;
-
-    http->error  = EIO;
-    http->status = HTTP_STATUS_ERROR;
-
-    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
-                  _("Unable to establish a secure connection to host."), 1);
-
-    return (-1);
-  }
-
-  return (0);
-}
-#endif // 0
-
-
 /*
  * 'http_sspi_alloc()' - Allocate SSPI object.
  */
@@ -1378,6 +1291,7 @@ http_sspi_client(http_t     *http,        /* I - Client connection */
 
   if (scRet != SEC_I_CONTINUE_NEEDED)
   {
+    http_sspi_set_error("InitializeSecurityContext");
     DEBUG_printf(("5http_sspi_client: InitializeSecurityContext(1) failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
     return (-1);
   }
@@ -1437,6 +1351,7 @@ http_sspi_client(http_t     *http,        /* I - Client connection */
 
        if ((temp = realloc(sspi->decryptBuffer, sspi->decryptBufferLength + 4096)) == NULL)
        {
+         _cupsSetHTTPError(HTTP_STATUS_ERROR);
          DEBUG_printf(("5http_sspi_client: Unable to allocate %d byte buffer.", sspi->decryptBufferLength + 4096));
          WSASetLastError(E_OUTOFMEMORY);
          return (-1);
@@ -1582,6 +1497,7 @@ http_sspi_client(http_t     *http,        /* I - Client connection */
 
     if (FAILED(scRet))
     {
+      http_sspi_set_error("InitializeSecurityContext");
       DEBUG_printf(("5http_sspi_client: InitializeSecurityContext(2) failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
       ret = -1;
       break;
@@ -1598,6 +1514,7 @@ http_sspi_client(http_t     *http,        /* I - Client connection */
       * Unimplemented
       */
 
+      _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, "Need client credentials.", 0);
       DEBUG_printf(("5http_sspi_client: server requested client credentials."));
       ret = -1;
       break;
@@ -1631,6 +1548,7 @@ http_sspi_client(http_t     *http,        /* I - Client connection */
 
     if (scRet != SEC_E_OK)
     {
+      http_sspi_set_error("QueryContextAttributes");
       DEBUG_printf(("5http_sspi_client: QueryContextAttributes failed(SECPKG_ATTR_REMOTE_CERT_CONTEXT): %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
       return (-1);
     }
@@ -1643,6 +1561,7 @@ http_sspi_client(http_t     *http,        /* I - Client connection */
 
     if (scRet != SEC_E_OK)
     {
+      http_sspi_set_error("QueryContextAttributes");
       DEBUG_printf(("5http_sspi_client: QueryContextAttributes failed(SECPKG_ATTR_STREAM_SIZES): %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
       ret = -1;
     }
@@ -1697,6 +1616,7 @@ http_sspi_find_credentials(
     {
       if (!CryptAcquireContextW(&hProv, (LPWSTR)container, MS_DEF_PROV_W, PROV_RSA_FULL, 0 /*CRYPT_MACHINE_KEYSET*/))
       {
+       http_sspi_set_error("CryptAquireContext");
         DEBUG_printf(("5http_sspi_find_credentials: CryptAcquireContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
         ok = FALSE;
         goto cleanup;
@@ -1708,6 +1628,7 @@ http_sspi_find_credentials(
 
   if (!store)
   {
+    http_sspi_set_error("CertOpenSystemStore");
     DEBUG_printf(("5http_sspi_find_credentials: CertOpenSystemStore failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
     ok = FALSE;
     goto cleanup;
@@ -1719,6 +1640,7 @@ http_sspi_find_credentials(
 
     if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
     {
+      http_sspi_set_error("CertStrToName");
       DEBUG_printf(("5http_sspi_find_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
       ok = FALSE;
       goto cleanup;
@@ -1728,6 +1650,7 @@ http_sspi_find_credentials(
 
     if (!p)
     {
+      _cupsSetHTTPError(HTTP_STATUS_ERROR);
       DEBUG_printf(("5http_sspi_find_credentials: malloc failed for %d bytes.", dwSize));
       ok = FALSE;
       goto cleanup;
@@ -1735,6 +1658,7 @@ http_sspi_find_credentials(
 
     if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
     {
+      http_sspi_set_error("CertStrToName");
       DEBUG_printf(("5http_sspi_find_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
       ok = FALSE;
       goto cleanup;
@@ -1747,6 +1671,7 @@ http_sspi_find_credentials(
 
     if (!storedContext)
     {
+      http_sspi_set_error("CertFindCertificateInStore");
       DEBUG_printf(("5http_sspi_find_credentials: Unable to find credentials for \"%s\".", common_name));
       ok = FALSE;
       goto cleanup;
@@ -1817,6 +1742,7 @@ http_sspi_find_credentials(
   Status = AcquireCredentialsHandle(NULL, UNISP_NAME, http->mode == _HTTP_MODE_SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &sspi->creds, &tsExpiry);
   if (Status != SEC_E_OK)
   {
+    http_sspi_set_error("AcquireCredentialsHandle");
     DEBUG_printf(("5http_sspi_find_credentials: AcquireCredentialsHandle failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), Status)));
     ok = FALSE;
     goto cleanup;
@@ -1915,6 +1841,7 @@ http_sspi_make_credentials(
     {
       if (!CryptAcquireContextW(&hProv, (LPWSTR)container, MS_DEF_PROV_W, PROV_RSA_FULL, 0 /*CRYPT_MACHINE_KEYSET*/))
       {
+       http_sspi_set_error("CryptAquireContext");
         DEBUG_printf(("5http_sspi_make_credentials: CryptAcquireContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
 //        fprintf(stderr, "5http_sspi_make_credentials: CryptAcquireContext failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
         ok = FALSE;
@@ -1927,6 +1854,7 @@ http_sspi_make_credentials(
 
   if (!store)
   {
+    http_sspi_set_error("CertOpenSystemStore");
     DEBUG_printf(("5http_sspi_make_credentials: CertOpenSystemStore failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
 //    fprintf(stderr, "5http_sspi_make_credentials: CertOpenSystemStore failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
@@ -1937,6 +1865,7 @@ http_sspi_make_credentials(
 
   if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
   {
+    http_sspi_set_error("CertStrToName");
     DEBUG_printf(("5http_sspi_make_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
 //    fprintf(stderr, "5http_sspi_make_credentials: CertStrToName failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
@@ -1947,6 +1876,7 @@ http_sspi_make_credentials(
 
   if (!p)
   {
+    _cupsSetHTTPError(HTTP_STATUS_ERROR);
     DEBUG_printf(("5http_sspi_make_credentials: malloc failed for %d bytes", dwSize));
 //    fprintf(stderr, "5http_sspi_make_credentials: malloc failed for %d bytes\n", dwSize);
     ok = FALSE;
@@ -1955,6 +1885,7 @@ http_sspi_make_credentials(
 
   if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
   {
+    http_sspi_set_error("CertStrToName");
     DEBUG_printf(("5http_sspi_make_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
 //    fprintf(stderr, "5http_sspi_make_credentials: CertStrToName failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
@@ -1970,6 +1901,7 @@ http_sspi_make_credentials(
 
   if (!CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE | RSA1024BIT_KEY, &hKey))
   {
+    http_sspi_set_error("CryptGenKey");
     DEBUG_printf(("5http_sspi_make_credentials: CryptGenKey failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
 //    fprintf(stderr, "5http_sspi_make_credentials: CryptGenKey failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
@@ -1994,6 +1926,7 @@ http_sspi_make_credentials(
 
   if (!createdContext)
   {
+    http_sspi_set_error("CertCreateSelfSignCertificate");
     DEBUG_printf(("5http_sspi_make_credentials: CertCreateSelfSignCertificate failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
 //    fprintf(stderr, "5http_sspi_make_credentials: CertCreateSelfSignCertificate failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
@@ -2007,8 +1940,8 @@ http_sspi_make_credentials(
 
   if (!CertAddCertificateContextToStore(store, createdContext, CERT_STORE_ADD_REPLACE_EXISTING, &storedContext))
   {
+    http_sspi_set_error("CertAddCertificateContextToStore");
     DEBUG_printf(("5http_sspi_make_credentials: CertAddCertificateContextToStore failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
-//    fprintf(stderr, "5http_sspi_make_credentials: CertAddCertificateContextToStore failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
     goto cleanup;
   }
@@ -2022,8 +1955,8 @@ http_sspi_make_credentials(
 
   if (!CertSetCertificateContextProperty(storedContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &ckp))
   {
+    http_sspi_set_error("CertSetCertificateContextProperty");
     DEBUG_printf(("5http_sspi_make_credentials: CertSetCertificateContextProperty failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
-//    fprintf(stderr, "5http_sspi_make_credentials: CertSetCertificateContextProperty failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError()));
     ok = FALSE;
     goto cleanup;
   }
@@ -2045,6 +1978,7 @@ http_sspi_make_credentials(
   Status = AcquireCredentialsHandle(NULL, UNISP_NAME, mode == _HTTP_MODE_SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &sspi->creds, &tsExpiry);
   if (Status != SEC_E_OK)
   {
+    http_sspi_set_error("AcquireCredentialsHandle");
     DEBUG_printf(("5http_sspi_make_credentials: AcquireCredentialsHandle failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), Status)));
 //    fprintf(stderr, "5http_sspi_make_credentials: AcquireCredentialsHandle failed: %s\n", http_sspi_strerror(sspi->error, sizeof(sspi->error), Status));
     ok = FALSE;
@@ -2122,9 +2056,6 @@ http_sspi_server(http_t     *http,        /* I - HTTP connection */
   if (!http_sspi_find_credentials(http, L"ServerContainer", common_name))
     if (!http_sspi_make_credentials(http->tls, L"ServerContainer", common_name, _HTTP_MODE_SERVER, 10))
     {
-//      char temp[8192];
-
-//      fprintf(stderr, "Unable to create credentials for '%s': %s\n", common_name, http_sspi_strerror(temp, sizeof(temp), GetLastError()));
       DEBUG_puts("5http_sspi_server: Unable to get server credentials.");
       return (-1);
     }
@@ -2158,6 +2089,7 @@ http_sspi_server(http_t     *http,        /* I - HTTP connection */
 
        if ((temp = realloc(sspi->decryptBuffer, sspi->decryptBufferLength + 4096)) == NULL)
        {
+         _cupsSetHTTPError(HTTP_STATUS_ERROR);
          DEBUG_printf(("5http_sspi_server: Unable to allocate %d byte buffer.", sspi->decryptBufferLength + 4096));
          WSASetLastError(E_OUTOFMEMORY);
          return (-1);
@@ -2266,6 +2198,7 @@ http_sspi_server(http_t     *http,        /* I - HTTP connection */
     }
     else if (FAILED(scRet) && scRet != SEC_E_INCOMPLETE_MESSAGE)
     {
+      http_sspi_set_error("AcceptSecurityContext");
       DEBUG_printf(("5http_sspi_server: AcceptSecurityContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
       ret = -1;
       break;
@@ -2298,6 +2231,7 @@ http_sspi_server(http_t     *http,        /* I - HTTP connection */
 
     if (scRet != SEC_E_OK)
     {
+      http_sspi_set_error("QueryContextAttributes");
       DEBUG_printf(("5http_sspi_server: QueryContextAttributes failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
       ret = -1;
     }
@@ -2307,6 +2241,24 @@ http_sspi_server(http_t     *http,       /* I - HTTP connection */
 }
 
 
+//
+// 'http_sspi_set_error()' - Copy the Windows error string to the CUPS error string.
+//
+
+static void
+http_sspi_set_error(const char *title) // I - Prefix/title for error
+{
+  char         temp[8192];             // Error string
+  size_t       templen;                // Length of prefix
+
+
+  snprintf(temp, sizeof(temp), "%s (%08x): ", title, GetLastError());
+  templen = strlen(templen);
+  http_sspi_strerror(temp + templen, sizeof(temp) - templen, GetLastError()));
+  _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, temp, 0);
+}
+
+
 /*
  * 'http_sspi_strerror()' - Return a string for the specified error code.
  */
@@ -2404,6 +2356,7 @@ http_sspi_verify(
   {
     status = GetLastError();
 
+    http_sspi_set_error("CertGetCertificateChain");
     DEBUG_printf(("5http_sspi_verify: CertGetCertificateChain returned: %s", http_sspi_strerror(error, sizeof(error), status)));
 
     LocalFree(commonNameUnicode);
@@ -2431,6 +2384,7 @@ http_sspi_verify(
   {
     status = GetLastError();
 
+    http_sspi_set_error("CertVerifyCertificateChainPolicy");
     DEBUG_printf(("5http_sspi_verify: CertVerifyCertificateChainPolicy returned %s", http_sspi_strerror(error, sizeof(error), status)));
   }
   else if (policyStatus.dwError)