*
* TLS support code for the CUPS scheduler on OS X.
*
- * Copyright 2007-2012 by Apple Inc.
+ * Copyright 2007-2013 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
if (!SSLCopyPeerTrust(con->http.tls, &peerTrust) && peerTrust)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates!",
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates.",
(int)SecTrustGetCertificateCount(peerTrust));
CFRelease(peerTrust);
}
else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates!");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates.");
return (1);
}
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "copy_cdsa_certificate: Looking for certs for \"%s\"...",
+ "copy_cdsa_certificate: Looking for certs for \"%s\".",
con->servername);
if ((err = SecKeychainOpen(ServerCertificate, &keychain)))
snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "copy_cdsa_certificate: Looking for certs for \"%s\"...",
+ "copy_cdsa_certificate: Looking for certs for \"%s\".",
localname);
servername = CFStringCreateWithCString(kCFAllocatorDefault, localname,
if (CFGetTypeID(identity) != SecIdentityGetTypeID())
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!");
+ cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure.");
goto cleanup;
}
static int /* O - 1 on success, 0 on failure */
make_certificate(cupsd_client_t *con) /* I - Client connection */
{
-#if 1
+# ifdef HAVE_SECGENERATESELFSIGNEDCERTIFICATE
+ int status = 0; /* Return status */
+ OSStatus err; /* Error code (if any) */
+# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ char localname[1024];/* Local hostname */
+# endif /* HAVE_DNSSD || HAVE_AVAHI */
+ const char *servername; /* Name of server in cert */
+ CFStringRef cfservername = NULL;
+ /* CF string for server name */
+ SecIdentityRef ident = NULL; /* Identity */
+ SecKeyRef publicKey = NULL,
+ /* Public key */
+ privateKey = NULL;
+ /* Private key */
+ CFMutableDictionaryRef keyParams = NULL;
+ /* Key generation parameters */
+
+
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Generating SSL server key and certificate.");
+
+# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
+ {
+ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+ servername = localname;
+ }
+ else
+# endif /* HAVE_DNSSD || HAVE_AVAHI */
+ servername = con->servername;
+
+ cfservername = CFStringCreateWithCString(kCFAllocatorDefault, servername,
+ kCFStringEncodingUTF8);
+ if (!cfservername)
+ goto cleanup;
+
+ /*
+ * Create a public/private key pair...
+ */
+
+ keyParams = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (!keyParams)
+ goto cleanup;
+
+ CFDictionaryAddValue(keyParams, kSecAttrKeyType, kSecAttrKeyTypeRSA);
+ CFDictionaryAddValue(keyParams, kSecAttrKeySizeInBits, CFSTR("2048"));
+ CFDictionaryAddValue(keyParams, kSecAttrLabel,
+ CFSTR("CUPS Self-Signed Certificate"));
+
+ err = SecKeyGeneratePair(keyParams, &publicKey, &privateKey);
+ if (err != noErr)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "SecKeyGeneratePair returned %ld.",
+ (long)err);
+ goto cleanup;
+ }
+
+ /*
+ * Create a self-signed certificate using the public/private key pair...
+ */
+
+ CFIndex usageInt = kSecKeyUsageAll;
+ CFNumberRef usage = CFNumberCreate(alloc, kCFNumberCFIndexType, &usageInt);
+ CFDictionaryRef certParams = CFDictionaryCreateMutable(kCFAllocatorDefault,
+ kSecCSRBasicContraintsPathLen, CFINT(0),
+ kSecSubjectAltName, cfservername,
+ kSecCertificateKeyUsage, usage,
+ NULL, NULL);
+ CFRelease(usage);
+
+ const void *ca_o[] = { kSecOidOrganization, CFSTR("") };
+ const void *ca_cn[] = { kSecOidCommonName, cfservername };
+ CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL);
+ CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL);
+ const void *ca_dn_array[2];
+
+ ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn,
+ 1, NULL);
+ ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn,
+ 1, NULL);
+
+ CFArrayRef subject = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2,
+ NULL);
+ SecCertificateRef cert = SecGenerateSelfSignedCertificate(subject, certParams,
+ publicKey,
+ privateKey);
+ CFRelease(subject);
+ CFRelease(certParams);
+
+ if (!cert)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "SecGenerateSelfSignedCertificate failed.");
+ goto cleanup;
+ }
+
+ ident = SecIdentityCreate(kCFAllocatorDefault, cert, privateKey);
+
+ if (ident)
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Created SSL server certificate file \"%s\".",
+ ServerCertificate);
+
+ /*
+ * Cleanup and return...
+ */
+
+cleanup:
+
+ if (cfservername)
+ CFRelease(cfservername);
+
+ if (keyParams)
+ CFRelease(keyParams);
+
+ if (ident)
+ CFRelease(ident);
+
+ if (cert)
+ CFRelease(cert);
+
+ if (publicKey)
+ CFRelease(publicKey);
+
+ if (privateKey)
+ CFRelease(publicKey);
+
+ if (!status)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to create SSL server key and certificate.");
+
+ return (status);
+
+# else /* !HAVE_SECGENERATESELFSIGNEDCERTIFICATE */
int pid, /* Process ID of command */
status; /* Status of command */
char command[1024], /* Command */
*envp[MAX_ENV + 1], /* Environment variables */
keychain[1024], /* Keychain argument */
infofile[1024], /* Type-in information for cert */
-# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
localname[1024], /* Local hostname */
-# endif /* HAVE_DNSSD || HAVE_AVAHI */
+# endif /* HAVE_DNSSD || HAVE_AVAHI */
*servername; /* Name of server in cert */
cups_file_t *fp; /* Seed/info file */
int infofd; /* Info file descriptor */
-# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
{
snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
servername = localname;
}
else
-# endif /* HAVE_DNSSD || HAVE_AVAHI */
+# endif /* HAVE_DNSSD || HAVE_AVAHI */
servername = con->servername;
/*
if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command)))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "No SSL certificate and certtool command not found!");
+ "No SSL certificate and certtool command not found.");
return (0);
}
cupsFileClose(fp);
cupsdLogMessage(CUPSD_LOG_INFO,
- "Generating SSL server key and certificate...");
+ "Generating SSL server key and certificate.");
snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate);
if (WIFEXITED(status))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to create SSL server key and certificate - "
- "the certtool command stopped with status %d!",
+ "the certtool command stopped with status %d.",
WEXITSTATUS(status));
else
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to create SSL server key and certificate - "
- "the certtool command crashed on signal %d!",
+ "the certtool command crashed on signal %d.",
WTERMSIG(status));
}
else
{
cupsdLogMessage(CUPSD_LOG_INFO,
- "Created SSL server certificate file \"%s\"...",
+ "Created SSL server certificate file \"%s\".",
ServerCertificate);
}
return (!status);
-#else
- int status = 0; /* Return status */
- OSStatus err; /* Error code (if any) */
-# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
- char localname[1024];/* Local hostname */
-# endif /* HAVE_DNSSD || HAVE_AVAHI */
- const char *servername; /* Name of server in cert */
- CFStringRef cfservername = NULL;
- /* CF string for server name */
- SecIdentityRef ident = NULL; /* Identity */
- SecKeyRef publicKey = NULL,
- /* Public key */
- privateKey = NULL;
- /* Private key */
- CFDictionaryRef keyParams = NULL;
- /* Key generation parameters */
-
-
-# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
- if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
- {
- snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
- servername = localname;
- }
- else
-# endif /* HAVE_DNSSD || HAVE_AVAHI */
- servername = con->servername;
-
- cfservername = CFStringCreateFromCString(kCFAllocatorDefault, servername,
- kCFStringEncodingUTF8);
- if (!cfservername)
- goto cleanup;
-
- /*
- * Create a public/private key pair...
- */
-
- keyParams = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)))
- if (!keyParams)
- goto cleanup;
-
- CFDictionaryAddValue(keyParams, kSecAttrKeyType, kSecAttrKeyTypeRSA);
- CFDictionaryAddValue(keyParams, kSecAttrKeySizeInBits, CFSTR("2048"));
- CFDictionaryAddValue(keyParams, kSecAttrLabel,
- CFSTR("CUPS Self-Signed Certificate"));
-
- err = SecKeyGeneratePair(keyParams, &publicKey, &privateKey);
- if (err != noErr)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "SecKeyGeneratePair returned %ld.",
- (long)err);
- goto cleanup;
- }
-
- /*
- * Create a self-signed certificate...
- */
-
- CE_DataAndType exts[2],
- *extp = exts;
- unsigned numExts = 0;
- CSSM_DATA refId; // mallocd by CSSM_TP_SubmitCredRequest
- CSSM_APPLE_TP_CERT_REQUEST certReq;
- CSSM_TP_REQUEST_SET reqSet;
- sint32 estTime;
- CSSM_BOOL confirmRequired;
- CSSM_TP_RESULT_SET_PTR resultSet;
- CSSM_ENCODED_CERT *encCert;
- CSSM_APPLE_TP_NAME_OID subjectNames[MAX_NAMES];
- uint32 numNames = 0;
- CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext;
- CSSM_FIELD policyId;
-
- certReq.challengeString = NULL;
-
- extp->type = DT_KeyUsage;
- extp->critical = CSSM_FALSE;
- extp->extension.keyUsage = CE_KU_DigitalSignature | CE_KU_KeyCertSign |
- CE_KU_KeyEncipherment | CE_KU_DataEncipherment;
- extp ++;
- numExts ++;
-
- extp->type = DT_BasicConstraints;
- extp->critical = CSSM_TRUE;
- extp->extension.basicConstraints.cA = CSSM_FALSE;
- extp->extension.basicConstraints.pathLenConstraintPresent = CSSM_FALSE;
- extp ++;
- numExts ++;
-
- subjectNames[0].string = servername;
- subjectNames[0].oid = &CSSMOID_CommonName;
- subjectNames[1].string = "";
- subjectNames[1].oid = &CSSMOID_OrganizationName;
- subjectNames[2].string = "";
- subjectNames[2].oid = &CSSMOID_CountryName;
- subjectNames[3].string = "";
- subjectNames[3].oid = &CSSMOID_StateProvinceName;
- numNames = 4;
-
- /* certReq */
- certReq.cspHand = cspHand;
- certReq.clHand = clHand;
- certReq.serialNumber = 0x12345678; // TBD - random? From user?
- certReq.numSubjectNames = numNames;
- certReq.subjectNames = subjectNames;
- certReq.numIssuerNames = 0;
- certReq.issuerNames = NULL;
- certReq.issuerNameX509 = NULL;
- certReq.certPublicKey = subjPubKey;
- certReq.issuerPrivateKey = signerPrivKey;
- certReq.signatureAlg = sigAlg;
- certReq.signatureOid = *sigOid;
- certReq.notBefore = 0; // TBD - from user
- certReq.notAfter = 10 * 365 * 86400;
- certReq.numExtensions = numExts;
- certReq.extensions = exts;
- reqSet.NumberOfRequests = 1;
- reqSet.Requests = &certReq;
-
- memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
-
- memset(&policyId, 0, sizeof(CSSM_FIELD));
- policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
-
- CallerAuthContext.Policy.NumberOfPolicyIds = 1;
- CallerAuthContext.Policy.PolicyIds = &policyId;
-
- CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tpHand,
- NULL, // PreferredAuthority
- CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
- &reqSet,
- &CallerAuthContext,
- &estTime,
- &refId);
- /* before proceeding, free resources allocated thus far */
-#if CERT_TOOL
- if (!useAllDefaults) {
- freeNameOids(subjectNames, numNames);
- }
-#endif
-
- if (crtn) {
- cuPrintError("CSSM_TP_SubmitCredRequest", crtn);
- return crtn;
- }
- crtn = CSSM_TP_RetrieveCredResult(tpHand,
- &refId,
- NULL, // CallerAuthCredentials
- &estTime,
- &confirmRequired,
- &resultSet);
- if (crtn) {
- cuPrintError("CSSM_TP_RetrieveCredResult", crtn);
- return crtn;
- }
- if (resultSet == NULL) {
- coreLog("httpserver", "***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
- return ioErr;
- }
- encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
- *certData = encCert->CertBlob;
- /* free resources allocated by TP */
- APP_FREE(refId.Data);
- APP_FREE(encCert);
- APP_FREE(resultSet);
- return noErr;
-
- /*
- * Cleanup and return...
- */
-
-cleanup:
-
- if (cfservername)
- CFRelease(cfservername);
-
- if (keyParams)
- CFRelease(keyParams);
-
- if (ident)
- CFRelease(ident);
-
- if (publicKey)
- CFRelease(publicKey);
-
- if (privateKey)
- CFRelease(publicKey);
-
- if (!status)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create SSL server key and certificate.");
-
- return (status);
-#endif // 0
+# endif /* HAVE_SECGENERATESELFSIGNEDCERTIFICATE */
}