summaryrefslogtreecommitdiff
path: root/cups/tls-sspi.c
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2014-07-17 21:21:21 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2014-07-17 21:21:21 +0000
commit17eecbf1d82fc87361012c11a5d288763707aaf9 (patch)
treedd74d4cf781d181756d899bed869ca1787b365e7 /cups/tls-sspi.c
parente32497ad0cbacd5abf9458556b6f2b73959c1e66 (diff)
downloadcups-17eecbf1d82fc87361012c11a5d288763707aaf9.tar.gz
Save work on SSPI certificate functions for validation and info.
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@12044 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'cups/tls-sspi.c')
-rw-r--r--cups/tls-sspi.c241
1 files changed, 121 insertions, 120 deletions
diff --git a/cups/tls-sspi.c b/cups/tls-sspi.c
index 26823d9a7..fcebb7ee4 100644
--- a/cups/tls-sspi.c
+++ b/cups/tls-sspi.c
@@ -48,6 +48,7 @@
static _http_sspi_t *http_sspi_alloc(void);
static int http_sspi_client(http_t *http, const char *hostname);
+static PCCERT_CONTEXT http_sspi_create_credential(http_credential_t *cred);
static BOOL http_sspi_find_credentials(http_t *http, const LPWSTR containerName, const char *common_name);
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);
@@ -147,9 +148,7 @@ http_tls_credentials_t /* O - Internal credentials */
_httpCreateCredentials(
cups_array_t *credentials) /* I - Array of credentials */
{
- (void)credentials;
-
- return (NULL);
+ return (http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials)));
}
@@ -164,10 +163,47 @@ httpCredentialsAreValidForName(
cups_array_t *credentials, /* I - Credentials */
const char *common_name) /* I - Name to check */
{
- (void)credentials;
- (void)common_name;
+ int valid = 1; /* Valid name? */
+ PCCERT_CONTEXT cert = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
+ /* Certificate */
+ char cert_name[1024]; /* Name from certificate */
+
+
+ if (cert)
+ {
+ if (!CertNameToStr(X509_ASN_ENCODING, cert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, cert_name, sizeof(cert_name)))
+ strlcpy(cert_name, "unknown", sizeof(cert_name));
+
+ CertFreeCertificateContext(cert);
+ }
+ else
+ strlcpy(cert_name, "unknown", sizeof(cert_name));
+
+ /*
+ * Compare the common names...
+ */
+
+ if (_cups_strcasecmp(common_name, cert_name))
+ {
+ /*
+ * Not an exact match for the common name, check for wildcard certs...
+ */
+
+ const char *domain = strchr(common_name, '.');
+ /* Domain in common name */
+
+ if (strncmp(cert_name, "*.", 2) || !domain || _cups_strcasecmp(domain, cert_name + 1))
+ {
+ /*
+ * Not a wildcard match.
+ */
+
+ /* TODO: Check subject alternate names */
+ valid = 0;
+ }
+ }
- return (1);
+ return (valid);
}
@@ -182,68 +218,32 @@ httpCredentialsGetTrust(
cups_array_t *credentials, /* I - Credentials */
const char *common_name) /* I - Common name for trust lookup */
{
- http_trust_t trust = HTTP_TRUST_OK;
- /* Trusted? */
- cups_array_t *tcreds = NULL; /* Trusted credentials */
- _cups_globals_t *cg = _cupsGlobals();
- /* Per-thread globals */
+ http_trust_t trust = HTTP_TRUST_OK; /* Level of trust */
+ PCCERT_CONTEXT cert = NULL; /* Certificate to validate */
+ DWORD certFlags = 0; /* Cert verification flags */
+ _cups_globals_t *cg = _cupsGlobals(); /* Per-thread global data */
if (!common_name)
return (HTTP_TRUST_UNKNOWN);
- /*
- * Look this common name up in the default keychains...
- */
-
- httpLoadCredentials(NULL, &tcreds, common_name);
-
- if (tcreds)
- {
- char credentials_str[1024], /* String for incoming credentials */
- tcreds_str[1024]; /* String for saved credentials */
-
- httpCredentialsString(credentials, credentials_str, sizeof(credentials_str));
- httpCredentialsString(tcreds, tcreds_str, sizeof(tcreds_str));
-
- if (strcmp(credentials_str, tcreds_str))
- {
- /*
- * Credentials don't match, let's look at the expiration date of the new
- * credentials and allow if the new ones have a later expiration...
- */
-
- if (httpCredentialsGetExpiration(credentials) <= httpCredentialsGetExpiration(tcreds) ||
- !httpCredentialsAreValidForName(credentials, common_name))
- {
- /*
- * Either the new credentials are not newly issued, or the common name
- * does not match the issued certificate...
- */
+ cert = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
+ if (!cert)
+ return (HTTP_TRUST_UNKNOWN);
- trust = HTTP_TRUST_INVALID;
- }
- else if (httpCredentialsGetExpiration(tcreds) < time(NULL))
- {
- /*
- * Save the renewed credentials...
- */
+ if (cg->any_root)
+ certFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
- trust = HTTP_TRUST_RENEWED;
+ if (cg->expired_certs)
+ certFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
- httpSaveCredentials(NULL, credentials, common_name);
- }
- }
+ if (!cg->validate_certs)
+ certFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
- httpFreeCredentials(tcreds);
- }
- else if (cg->validate_certs && !httpCredentialsAreValidForName(credentials, common_name))
+ if (http_sspi_verify(cert, common_name, certFlags) != SEC_E_OK)
trust = HTTP_TRUST_INVALID;
- if (!cg->expired_certs && time(NULL) > httpCredentialsGetExpiration(credentials))
- trust = HTTP_TRUST_EXPIRED;
- else if (!cg->any_root && cupsArrayCount(credentials) == 1)
- trust = HTTP_TRUST_INVALID;
+ CertFreeCertificateContext(cert);
return (trust);
}
@@ -259,9 +259,30 @@ time_t /* O - Expiration date of credentials */
httpCredentialsGetExpiration(
cups_array_t *credentials) /* I - Credentials */
{
- (void)credentials;
+ time_t expiration_date = 0; /* Expiration data of credentials */
+ PCCERT_CONTEXT cert = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
+ /* Certificate */
- return (INT_MAX);
+ if (cert)
+ {
+ SYSTEMTIME systime; /* System time */
+ struct tm tm; /* UNIX date/time */
+
+ FileTimeToSystemTime(cert->pCertInfo->NotAfter, &systime);
+
+ tm.tm_year = systime.wYear - 1900;
+ tm.tm_mon = systime.wMonth - 1;
+ tm.tm_mday = systime.wDay;
+ tm.tm_hour = systime.wHour;
+ tm.tm_min = systime.wMinute;
+ tm.tm_sec = systime.wSecond;
+
+ expiration_date = mktime(&tm);
+
+ CertFreeCertificateContext(cert);
+ }
+
+ return (expiration_date);
}
@@ -277,6 +298,11 @@ httpCredentialsString(
char *buffer, /* I - Buffer or @code NULL@ */
size_t bufsize) /* I - Size of buffer */
{
+ http_credential_t *first = (http_credential_t *)cupsArrayFirst(credentials);
+ /* First certificate */
+ PCCERT_CONTEXT cert; /* Certificate */
+
+
DEBUG_printf(("httpCredentialsString(credentials=%p, buffer=%p, bufsize=" CUPS_LLFMT ")", credentials, buffer, CUPS_LLCAST bufsize));
if (!buffer)
@@ -285,39 +311,39 @@ httpCredentialsString(
if (buffer && bufsize > 0)
*buffer = '\0';
-#if 0
- http_credential_t *first; /* First certificate */
- SecCertificateRef secCert; /* Certificate reference */
-
+ cert = http_sspi_create_credential(first);
- if ((first = (http_credential_t *)cupsArrayFirst(credentials)) != NULL &&
- (secCert = http_cdsa_create_credential(first)) != NULL)
+ if (cert)
{
- CFStringRef cf_name; /* CF common name string */
- char name[256]; /* Common name associated with cert */
+ char cert_name[256]; /* Common name */
+ SYSTEMTIME systime; /* System time */
+ struct tm tm; /* UNIX date/time */
time_t expiration; /* Expiration date of cert */
_cups_md5_state_t md5_state; /* MD5 state */
unsigned char md5_digest[16]; /* MD5 result */
- if ((cf_name = SecCertificateCopySubjectSummary(secCert)) != NULL)
- {
- CFStringGetCString(cf_name, name, (CFIndex)sizeof(name), kCFStringEncodingUTF8);
- CFRelease(cf_name);
- }
- else
- strlcpy(name, "unknown", sizeof(name));
+ FileTimeToSystemTime(cert->pCertInfo->NotAfter, &systime);
+
+ tm.tm_year = systime.wYear - 1900;
+ tm.tm_mon = systime.wMonth - 1;
+ tm.tm_mday = systime.wDay;
+ tm.tm_hour = systime.wHour;
+ tm.tm_min = systime.wMinute;
+ tm.tm_sec = systime.wSecond;
+
+ expiration = mktime(&tm);
- expiration = (time_t)(SecCertificateNotValidAfter(secCert) + kCFAbsoluteTimeIntervalSince1970);
+ if (!CertNameToStr(X509_ASN_ENCODING, cert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, cert_name, sizeof(cert_name)))
+ strlcpy(cert_name, "unknown", sizeof(cert_name));
_cupsMD5Init(&md5_state);
_cupsMD5Append(&md5_state, first->data, (int)first->datalen);
_cupsMD5Finish(&md5_state, md5_digest);
- snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]);
+ snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", cert_name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]);
- CFRelease(secCert);
+ CertFreeCertificateContext(cert);
}
-#endif /* 0 */
DEBUG_printf(("1httpCredentialsString: Returning \"%s\".", buffer));
@@ -335,6 +361,8 @@ _httpFreeCredentials(
{
if (!credentials)
return;
+
+ CertFreeCertificateContext(credentials);
}
@@ -1333,18 +1361,6 @@ http_sspi_client(http_t *http, /* I - Client connection */
return (-1);
}
-#if 0
- /* TODO: Move this out for opt-in server cert validation, like other platforms. */
- scRet = http_sspi_verify(sspi->remoteCert, hostname, sspi->certFlags);
-
- if (scRet != SEC_E_OK)
- {
- DEBUG_printf(("http_sspi_client: sspi_verify_certificate failed: %s", http_sspi_strerror(sspi, scRet)));
- ret = -1;
- goto cleanup;
- }
-#endif // 0
-
/*
* Find out how big the header/trailer will be:
*/
@@ -1363,6 +1379,21 @@ http_sspi_client(http_t *http, /* I - Client connection */
/*
+ * 'http_sspi_create_credential()' - Create an SSPI certificate context.
+ */
+
+static PCCERT_CONTEXT /* O - Certificate context */
+http_sspi_create_credential(
+ http_credential_t *cred) /* I - Credential */
+{
+ if (cred)
+ return (CertCreateCertificateContext(X509_ASN_ENCODING, cred->data, cred->datalen));
+ else
+ return (NULL);
+}
+
+
+/*
* 'http_sspi_find_credentials()' - Retrieve a TLS certificate from the system store.
*/
@@ -2071,36 +2102,6 @@ http_sspi_verify(
}
-#if 0
-/*
- * '_sspiSetAllowsAnyRoot()' - Set the client cert policy for untrusted root certs
- */
-void
-_sspiSetAllowsAnyRoot(_http_sspi_t *sspi,
- /* I - SSPI data */
- BOOL allow)
- /* I - Allow any root */
-{
- sspi->certFlags = (allow) ? sspi->certFlags | SECURITY_FLAG_IGNORE_UNKNOWN_CA :
- sspi->certFlags & ~SECURITY_FLAG_IGNORE_UNKNOWN_CA;
-}
-
-
-/*
- * '_sspiSetAllowsExpiredCerts()' - Set the client cert policy for expired root certs
- */
-void
-_sspiSetAllowsExpiredCerts(_http_sspi_t *sspi,
- /* I - SSPI data */
- BOOL allow)
- /* I - Allow expired certs */
-{
- sspi->certFlags = (allow) ? sspi->certFlags | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID :
- sspi->certFlags & ~SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
-}
-#endif // 0
-
-
/*
* End of "$Id$".
*/