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 */
*
* 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 */
/*
* '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) */
/*
* '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 */
/*
* 'httpCredentialsGetTrust()' - Return the trust of credentials.
- *
- * @since CUPS 2.0/OS 10.10@
*/
http_trust_t /* O - Level of trust */
/*
* 'httpCredentialsGetExpiration()' - Return the expiration date of the credentials.
- *
- * @since CUPS 2.0/OS 10.10@
*/
time_t /* O - Expiration date of credentials */
/*
* 'httpCredentialsString()' - Return a string representing the credentials.
- *
- * @since CUPS 2.0/OS 10.10@
*/
size_t /* O - Total size of credentials string */
/*
* 'httpLoadCredentials()' - Load X.509 credentials from a keychain file.
- *
- * @since CUPS 2.0/OS 10.10@
*/
int /* O - 0 on success, -1 on error */
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;
}
}
if (!store)
{
DEBUG_printf(("1httpLoadCredentials: CertOpenSystemStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+ http_sspi_set_error("CertOpenSystemStore");
goto cleanup;
}
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;
}
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;
}
/*
* 'httpSaveCredentials()' - Save X.509 credentials to a keychain file.
- *
- * @since CUPS 2.0/OS 10.10@
*/
int /* O - -1 on error, 0 on success */
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;
}
}
if (!store)
{
DEBUG_printf(("1httpSaveCredentials: CertOpenSystemStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
+ http_sspi_set_error("CertOpenSystemStore");
goto cleanup;
}
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;
}
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;
}
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;
}
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;
}
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);
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);
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);
}
}
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)));
}
}
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);
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);
}
-#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.
*/
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);
}
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);
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;
* Unimplemented
*/
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, "Need client credentials.", 0);
DEBUG_printf(("5http_sspi_client: server requested client credentials."));
ret = -1;
break;
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);
}
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;
}
{
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;
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;
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;
if (!p)
{
+ _cupsSetHTTPError(HTTP_STATUS_ERROR);
DEBUG_printf(("5http_sspi_find_credentials: malloc failed for %d bytes.", dwSize));
ok = FALSE;
goto cleanup;
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;
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;
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;
{
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;
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;
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;
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;
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;
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;
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;
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;
}
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;
}
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;
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);
}
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);
}
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;
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;
}
}
+//
+// '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.
*/
{
status = GetLastError();
+ http_sspi_set_error("CertGetCertificateChain");
DEBUG_printf(("5http_sspi_verify: CertGetCertificateChain returned: %s", http_sspi_strerror(error, sizeof(error), status)));
LocalFree(commonNameUnicode);
{
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)