Certificate_Store_MacOS_Impl() : m_policy(SecPolicyCreateBasicX509()), m_system_roots(nullptr), m_system_chain(nullptr), m_keychains(nullptr) { check_success(SecKeychainOpen(system_roots, &m_system_roots.get()), "open system root certificates"); check_success(SecKeychainOpen(system_keychain, &m_system_chain.get()), "open system keychain"); check_notnull(m_system_roots, "open system root certificate chain"); check_notnull(m_system_chain, "open system certificate chain"); // m_keychains is merely a convenience list view into all open keychain // objects. This list is required in prepareQuery(). std::array<const void*, 2> keychains{{ m_system_roots.get(), m_system_chain.get() }}; m_keychains.assign( CFArrayCreate(kCFAllocatorDefault, keychains.data(), keychains.size(), &kCFTypeArrayCallBacks)); check_notnull(m_keychains, "initialize keychain array"); }
static VALUE rb_open_keychain(VALUE self, VALUE path){ SecKeychainRef keychain=NULL; OSStatus result =SecKeychainOpen(StringValueCStr(path), &keychain); CheckOSStatusOrRaise(result); return KeychainFromSecKeychainRef(keychain); }
void makeEncryptKey(CFStringRef pass) { UInt32 passLen; unsigned char *passData; SecKeychainItemRef itemRef=NULL; SecKeychainRef sysChain; OSStatus secRes; BF_KEY temp_key; unsigned char encrypt_key[8]; if ((secRes = SecKeychainOpen(SYSTEM_KEYCHAIN, &sysChain)) != 0) { syslog(LOG_ERR,"Couldn't get system keychain: %d\n",secRes); exit(-1); } if ((secRes = SecKeychainFindGenericPassword(sysChain, strlen(SECRET_SERVICENAME), SECRET_SERVICENAME, 0, NULL, &passLen, (void**)&passData, &itemRef))!=0) { syslog(LOG_ERR,"Error finding secret in keychain (%d). Failing",secRes); exit(-1); } BF_set_key(&temp_key,passLen,passData); BF_ecb_encrypt((const unsigned char*)CFStringGetCStringPtr(pass,CFStringGetFastestEncoding(pass)),encrypt_key,&temp_key,BF_ENCRYPT); BF_set_key(&encrypt_bf_key,8,encrypt_key); return; }
static int keychain_init(hx509_context context, hx509_certs certs, void **data, int flags, const char *residue, hx509_lock lock) { struct ks_keychain *ctx; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { hx509_clear_error_string(context); return ENOMEM; } if (residue) { if (strcasecmp(residue, "system-anchors") == 0) { ctx->anchors = 1; } else if (strncasecmp(residue, "FILE:", 5) == 0) { OSStatus ret; ret = SecKeychainOpen(residue + 5, &ctx->keychain); if (ret != noErr) { hx509_set_error_string(context, 0, ENOENT, "Failed to open %s", residue); return ENOENT; } } else { hx509_set_error_string(context, 0, ENOENT, "Unknown subtype %s", residue); return ENOENT; } } *data = ctx; return 0; }
SecKeychainRef SROpenKeychain(char* path) { SecKeychainRef keychain = NULL; OSStatus status = SecKeychainOpen(path, &keychain); SecKeychainStatus keychainStatus = 0; status = SecKeychainGetStatus(keychain, &keychainStatus); if (status == 0) { } else { fprintf(stderr, "Unable to open keychain at path %s: ", path); SRHandleError(status, false); exit(EX_IOERR); } return keychain; }
void genKeychains(const std::string& path, CFMutableArrayRef& keychains) { std::vector<std::string> paths; // Support both a directory and explicit path search. if (isDirectory(path).ok()) { // Try to list every file in the given keychain search path. if (!listFilesInDirectory(path, paths).ok()) { return; } } else { // The explicit path search comes from a query predicate. paths.push_back(path); } for (const auto& keychain_path : paths) { SecKeychainRef keychain = nullptr; auto status = SecKeychainOpen(keychain_path.c_str(), &keychain); if (status == 0 && keychain != nullptr) { CFArrayAppendValue(keychains, keychain); } } }
static CFArrayRef /* O - Array of certificates */ copy_cdsa_certificate( cupsd_client_t *con) /* I - Client connection */ { OSStatus err; /* Error info */ SecKeychainRef keychain = NULL;/* Keychain reference */ SecIdentitySearchRef search = NULL; /* Search reference */ SecIdentityRef identity = NULL;/* Identity */ CFArrayRef certificates = NULL; /* Certificate array */ SecPolicyRef policy = NULL; /* Policy ref */ CFStringRef servername = NULL; /* Server name */ CFMutableDictionaryRef query = NULL; /* Query qualifiers */ CFArrayRef list = NULL; /* Keychain list */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) char localname[1024];/* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ cupsdLogMessage(CUPSD_LOG_DEBUG, "copy_cdsa_certificate: Looking for certs for \"%s\".", con->servername); if ((err = SecKeychainOpen(ServerCertificate, &keychain))) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)", ServerCertificate, cssmErrorString(err), (int)err); goto cleanup; } servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername, kCFStringEncodingUTF8); policy = SecPolicyCreateSSL(1, servername); if (servername) CFRelease(servername); if (!policy) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); goto cleanup; } if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks))) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary"); goto cleanup; } list = CFArrayCreate(kCFAllocatorDefault, (const void **)&keychain, 1, &kCFTypeArrayCallBacks); CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); CFDictionaryAddValue(query, kSecMatchPolicy, policy); CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne); CFDictionaryAddValue(query, kSecMatchSearchList, list); CFRelease(list); err = SecItemCopyMatching(query, (CFTypeRef *)&identity); # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (err && DNSSDHostName) { /* * Search for the connection server name failed; try the DNS-SD .local * hostname instead... */ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); cupsdLogMessage(CUPSD_LOG_DEBUG, "copy_cdsa_certificate: Looking for certs for \"%s\".", localname); servername = CFStringCreateWithCString(kCFAllocatorDefault, localname, kCFStringEncodingUTF8); CFRelease(policy); policy = SecPolicyCreateSSL(1, servername); if (servername) CFRelease(servername); if (!policy) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); goto cleanup; } CFDictionarySetValue(query, kSecMatchPolicy, policy); err = SecItemCopyMatching(query, (CFTypeRef *)&identity); } # endif /* HAVE_DNSSD || HAVE_AVAHI */ if (err) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Cannot find signing key in keychain \"%s\": %s (%d)", ServerCertificate, cssmErrorString(err), (int)err); goto cleanup; } if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure."); goto cleanup; } if ((certificates = CFArrayCreate(NULL, (const void **)&identity, 1, &kCFTypeArrayCallBacks)) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); goto cleanup; } cleanup : if (keychain) CFRelease(keychain); if (search) CFRelease(search); if (identity) CFRelease(identity); if (policy) CFRelease(policy); if (query) CFRelease(query); return (certificates); }
static value cert_load_defaults(){ #if defined(NEKO_WINDOWS) value v; HCERTSTORE store; PCCERT_CONTEXT cert; mbedtls_x509_crt *chain = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( chain ); if( store = CertOpenSystemStore(0, (LPCSTR)"Root") ){ cert = NULL; while( cert = CertEnumCertificatesInStore(store, cert) ) mbedtls_x509_crt_parse_der( chain, (unsigned char *)cert->pbCertEncoded, cert->cbCertEncoded ); CertCloseStore(store, 0); } v = alloc_abstract(k_cert, chain); val_gc(v,free_cert); return v; #elif defined(NEKO_MAC) CFMutableDictionaryRef search; CFArrayRef result; SecKeychainRef keychain; SecCertificateRef item; CFDataRef dat; value v; mbedtls_x509_crt *chain = NULL; // Load keychain if( SecKeychainOpen("/System/Library/Keychains/SystemRootCertificates.keychain",&keychain) != errSecSuccess ) return val_null; // Search for certificates search = CFDictionaryCreateMutable( NULL, 0, NULL, NULL ); CFDictionarySetValue( search, kSecClass, kSecClassCertificate ); CFDictionarySetValue( search, kSecMatchLimit, kSecMatchLimitAll ); CFDictionarySetValue( search, kSecReturnRef, kCFBooleanTrue ); CFDictionarySetValue( search, kSecMatchSearchList, CFArrayCreate(NULL, (const void **)&keychain, 1, NULL) ); if( SecItemCopyMatching( search, (CFTypeRef *)&result ) == errSecSuccess ){ CFIndex n = CFArrayGetCount( result ); for( CFIndex i = 0; i < n; i++ ){ item = (SecCertificateRef)CFArrayGetValueAtIndex( result, i ); // Get certificate in DER format dat = SecCertificateCopyData( item ); if( dat ){ if( chain == NULL ){ chain = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( chain ); } mbedtls_x509_crt_parse_der( chain, (unsigned char *)CFDataGetBytePtr(dat), CFDataGetLength(dat) ); CFRelease( dat ); } } } CFRelease(keychain); if( chain != NULL ){ v = alloc_abstract(k_cert, chain); val_gc(v,free_cert); return v; }else{ return val_null; } #else return val_null; #endif }
/* * Returns true if we are to allow/trust the specified * cert as a PKINIT-only anchor. */ static bool tpCheckPkinitServerCert( TPCertGroup &certGroup) { /* * Basic requirement: exactly one cert, self-signed. * The numCerts == 1 requirement might change... */ unsigned numCerts = certGroup.numCerts(); if(numCerts != 1) { tpDebug("tpCheckPkinitServerCert: too many certs"); return false; } /* end of chain... */ TPCertInfo *theCert = certGroup.certAtIndex(numCerts - 1); if(!theCert->isSelfSigned()) { tpDebug("tpCheckPkinitServerCert: 1 cert, not self-signed"); return false; } const CSSM_DATA *subjectName = theCert->subjectName(); /* * Open the magic keychain. * We're going up and over the Sec layer here, not generally * kosher, but this is a temp hack. */ OSStatus ortn; SecKeychainRef kcRef = NULL; string fullPathName; const char *homeDir = getenv("HOME"); if (homeDir == NULL) { // If $HOME is unset get the current user's home directory // from the passwd file. uid_t uid = geteuid(); if (!uid) uid = getuid(); struct passwd *pw = getpwuid(uid); if (!pw) { return false; } homeDir = pw->pw_dir; } fullPathName = homeDir; fullPathName += "/Library/Application Support/PKINIT/TrustedServers.keychain"; ortn = SecKeychainOpen(fullPathName.c_str(), &kcRef); if(ortn) { tpDebug("tpCheckPkinitServerCert: keychain not found (1)"); return false; } /* subsequent errors to errOut: */ bool ourRtn = false; SecKeychainStatus kcStatus; CSSM_DATA_PTR subjSerial = NULL; CSSM_RETURN crtn; SecKeychainSearchRef srchRef = NULL; SecKeychainAttributeList attrList; SecKeychainAttribute attrs[2]; SecKeychainItemRef foundItem = NULL; ortn = SecKeychainGetStatus(kcRef, &kcStatus); if(ortn) { tpDebug("tpCheckPkinitServerCert: keychain not found (2)"); goto errOut; } /* * We already have this cert's normalized name; get its * serial number. */ crtn = theCert->fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial); if(crtn) { /* should never happen */ tpDebug("tpCheckPkinitServerCert: error fetching serial number"); goto errOut; } attrs[0].tag = kSecSubjectItemAttr; attrs[0].length = subjectName->Length; attrs[0].data = subjectName->Data; attrs[1].tag = kSecSerialNumberItemAttr; attrs[1].length = subjSerial->Length; attrs[1].data = subjSerial->Data; attrList.count = 2; attrList.attr = attrs; ortn = SecKeychainSearchCreateFromAttributes(kcRef, kSecCertificateItemClass, &attrList, &srchRef); if(ortn) { tpDebug("tpCheckPkinitServerCert: search failure"); goto errOut; } for(;;) { ortn = SecKeychainSearchCopyNext(srchRef, &foundItem); if(ortn) { tpDebug("tpCheckPkinitServerCert: end search"); break; } /* found a matching cert; do byte-for-byte compare */ CSSM_DATA certData; ortn = SecCertificateGetData((SecCertificateRef)foundItem, &certData); if(ortn) { tpDebug("tpCheckPkinitServerCert: SecCertificateGetData failure"); continue; } if(tpCompareCssmData(&certData, theCert->itemData())){ tpDebug("tpCheckPkinitServerCert: FOUND CERT"); ourRtn = true; break; } tpDebug("tpCheckPkinitServerCert: skipping matching cert"); CFRelease(foundItem); foundItem = NULL; } errOut: CFRELEASE(kcRef); CFRELEASE(srchRef); CFRELEASE(foundItem); if(subjSerial != NULL) { theCert->freeField(&CSSMOID_X509V1SerialNumber, subjSerial); } return ourRtn; }
static void tls_get_cert_from_keychain( char *host ) { /* Cert info is kept in the global options. */ struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); if ( !lo ) return; /* If the server identity option is set, don't need to do anything * as the certificate will get set in the SSL context during context * initialization. */ if (lo->ldo_tls_server_ident_ref_name) { return; } /* If the cert is set in the options, don't override it. */ if ( lo->ldo_tls_cacertfile || lo->ldo_tls_certfile ) { Debug( LDAP_DEBUG_ANY, "TLS: not reading certificate from keychain, option %s is set\n", lo->ldo_tls_cacertfile ? "cacertfile" : "certfile", 0, 0 ); return; } SecKeychainRef keychainRef = NULL; OSStatus status = SecKeychainOpen( SYSTEM_KEYCHAIN_PATH, &keychainRef ); if ( status != errSecSuccess ) { Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainOpen failed for keychain %s: %d", SYSTEM_KEYCHAIN_PATH, (int)status, 0 ); syslog( LOG_ERR, "TLS: SecKeychainOpen failed for keychain %s: %d", SYSTEM_KEYCHAIN_PATH, (int)status, 0 ); cssmPerror( "SecKeychainOpen", status ); return; } SecKeychainSearchRef searchRef = NULL; status = SecKeychainSearchCreateFromAttributes( keychainRef, kSecCertificateItemClass, NULL, &searchRef ); if ( status != errSecSuccess ) { Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainSearchCreateFromAttributes failed: %d", (int)status, 0, 0 ); syslog( LOG_ERR, "TLS: SecKeychainSearchCreateFromAttributes failed: %d", (int)status ); cssmPerror( "SecKeychainSearchCreateFromAttributes", status ); } while ( status == errSecSuccess ) { SecCertificateRef certificateRef = NULL; status = SecKeychainSearchCopyNext( searchRef, (SecKeychainItemRef*)&certificateRef ); /* Bail on any error. */ if ( status != errSecSuccess ) { /* Only complain if the error is something other than * the normal search end. */ if ( status != errSecItemNotFound ) { Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainSearchCopyNext failed: %d", (int)status, 0, 0 ); syslog( LOG_ERR, "SecKeychainSearchCopyNext failed: %d", (int)status ); cssmPerror( "SecKeychainSearchCopyNext", status ); } break; } /* Extract the name from the certificate. Will check against the host * name passed in. */ CFStringRef commonName = NULL; status = SecCertificateCopyCommonName( certificateRef, &commonName ); if ( status != errSecSuccess || !commonName ) { Debug( LDAP_DEBUG_ANY, "TLS: SecCertificateCopyCommonName failed: %d", (int)status, 0, 0 ); cssmPerror( "SecCertificateCopyCommonName", status ); /* Reset 'status' to allow the loop to continue. No need to * stop just because we can't get the name from one of the * certs. */ status = errSecSuccess; } else { /* If the common name in the certificate matches the host name, save * the certificate reference in the options data for later use. */ char commonNameCStr[PATH_MAX]; if ( !CFStringGetCString( commonName, commonNameCStr, sizeof(commonNameCStr), kCFStringEncodingUTF8 ) ) { Debug( LDAP_DEBUG_ANY, "TLS: Unable to convert certificate common name CFString into C String", 0, 0, 0); } CFRelease( commonName ); if ( commonNameCStr && strcmp( commonNameCStr, host ) == 0 ) { if ( lo->ldo_tls_cert_ref ) { CFRelease( lo->ldo_tls_cert_ref ); } lo->ldo_tls_cert_ref = certificateRef; status = !errSecSuccess; /* cert found - terminate the loop */ } } /* Only release the ref if we don't care about it. Refs we care * about get released later (when the connection is closed). */ if ( lo->ldo_tls_cert_ref != certificateRef ) { CFRelease( certificateRef ); } } if ( searchRef ) { CFRelease( searchRef ); } CFRelease( keychainRef ); Debug( LDAP_DEBUG_ANY, "TLS: %s certificate in keychain for host \"%s\"\n", lo->ldo_tls_cert_ref ? "found" : "did not find", host, 0 ); }
/* * Convert a keychain name (which may be NULL) into the CFArrayRef required * by SSLSetCertificate. This is a bare-bones example of this operation, * since it requires and assumes that there is exactly one SecIdentity * in the keychain - i.e., there is exactly one matching cert/private key * pair. A real world server would probably search a keychain for a SecIdentity * matching some specific criteria. */ CFArrayRef getSslCerts( const char *kcName, // may be NULL, i.e., use default bool encryptOnly, bool completeCertChain, const char *anchorFile, // optional trusted anchor SecKeychainRef *pKcRef) // RETURNED { #if 0 SecKeychainRef kcRef = nil; OSStatus ortn; *pKcRef = nil; /* pick a keychain */ if(kcName) { ortn = SecKeychainOpen(kcName, &kcRef); if(ortn) { printf("SecKeychainOpen returned %d.\n", (int)ortn); printf("Cannot open keychain at %s. Aborting.\n", kcName); return NULL; } } else { /* use default keychain */ ortn = SecKeychainCopyDefault(&kcRef); if(ortn) { printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); return nil; } } *pKcRef = kcRef; return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); #else SecCertificateRef cert = NULL; SecIdentityRef identity = NULL; CFMutableArrayRef certificates = NULL, result = NULL; CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; SecTrustRef trust = NULL; SecKeyRef key = NULL; CFTypeRef pkdigest = NULL; // Find the first private key in the keychain and return both it's // attributes and a ref to it. require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), errOut); require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), errOut); require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), errOut); // Find the first certificate that has the same public key hash as the // returned private key and return it as a ref. require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); // Create an identity from the key and certificate. require(identity = SecIdentityCreate(NULL, cert, key), errOut); // Build a (partial) certificate chain from cert require(certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), errOut); CFArrayAppendValue(certificates, cert); require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), errOut); SecTrustResultType tresult; require_noerr(SecTrustEvaluate(trust, &tresult), errOut); CFIndex certCount, ix; // We need at least 1 certificate require(certCount = SecTrustGetCertificateCount(trust), errOut); // Build a result where element 0 is the identity and the other elements // are the certs in the chain starting at the first intermediate up to the // anchor, if we found one, or as far as we were able to build the chain // if not. require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), errOut); // We are commited to returning a result now, so do not use require below // this line without setting result to NULL again. CFArrayAppendValue(result, identity); for (ix = 1; ix < certCount; ++ix) { CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); } errOut: CFReleaseSafe(trust); CFReleaseSafe(certificates); CFReleaseSafe(identity); CFReleaseSafe(cert); CFReleaseSafe(certQuery); CFReleaseSafe(keyResult); CFReleaseSafe(keyQuery); return result; #endif }
int main(int argc, char **argv) { if(argc < 2) { usage(argv); } ocspOp op; switch(argv[1][0]) { case 'g': op = op_genReq; break; case 'G': op = op_parseReq; break; case 'r': op = op_genReply; break; case 'R': op = op_parseResp; break; case 'p': op = op_post; break; default: usage(argv); } /* user defined vars */ char *inFile = NULL; char *outFile = NULL; char *inCertName = NULL; char *issuerCertName = NULL; SecAsn1OCSPCertStatusTag certStatus = CS_Good; CE_CrlReason crlReason = CE_CR_Unspecified; char *kcName = NULL; bool verbose = false; bool doParse = false; const char *responderURI = NULL; extern int optind; optind = 2; extern char *optarg; int arg; while ((arg = getopt(argc, argv, "c:C:i:o:s:r:k:phvu:")) != -1) { switch (arg) { case 'c': inCertName = optarg; break; case 'C': issuerCertName = optarg; break; case 'i': inFile = optarg; break; case 'o': outFile = optarg; break; case 's': switch(optarg[0]) { case 'g': certStatus = CS_Good; break; case 'r': certStatus = CS_Revoked; break; case 'u': certStatus = CS_Unknown; break; default: printf("***Unrecognized certStatus***\n"); usage(argv); } break; case 'r': crlReason = atoi(optarg); break; case 'k': kcName = optarg; break; case 'v': verbose = 1; break; case 'p': doParse = true; break; case 'u': responderURI = optarg; break; default: case '?': usage(argv); } } if(optind != argc) { /* this happens if you give getopt() an arg which doesn't start with '-' */ usage(argv); } unsigned char *certData = NULL; unsigned certDataLen = 0; unsigned char *issuerCertData = NULL; unsigned issuerCertDataLen = 0; unsigned char *inData = NULL; unsigned inDataLen = 0; unsigned char *outData = NULL; unsigned outDataLen = 0; SecKeychainRef kcRef = NULL; OSStatus ortn; if(inCertName) { if(readFile(inCertName, &certData, &certDataLen)) { printf("***Error reading cert file %s. Aborting.\n", inCertName); exit(1); } } if(issuerCertName) { if(readFile(issuerCertName, &issuerCertData, &issuerCertDataLen)) { printf("***Error reading cert file %s. Aborting.\n", issuerCertName); exit(1); } } if(inFile) { if(readFile(inFile, &inData, &inDataLen)) { printf("***Error reading input file %s. Aborting.\n", inFile); exit(1); } } if(kcName) { ortn = SecKeychainOpen(kcName, &kcRef); if(ortn) { cssmPerror("SecKeychainOpen", ortn); return ortn; } } CSSM_CL_HANDLE clHand = cuClStartup(); switch(op) { case op_genReq: ortn = genOcspReq(clHand, certData, certDataLen, issuerCertData, issuerCertDataLen, &outData, &outDataLen); break; case op_parseReq: ortn = parseOcspReq(clHand, inData, inDataLen, verbose); break; case op_genReply: { SecIdentityRef idRef = NULL; ortn = sslSimpleIdentPicker(kcRef, &idRef); if(ortn) { printf("***Error choosing identity. Aborting.\n"); exit(1); } ortn = genOcspResp(clHand, certStatus, crlReason, certData, certDataLen, issuerCertData, issuerCertDataLen, idRef, &outData, &outDataLen); CFRelease(idRef); break; } case op_parseResp: ortn = parseOcspResp(clHand, inData, inDataLen, verbose); break; case op_post: ortn = postOcspReq(clHand, certData, certDataLen, issuerCertData, issuerCertDataLen, responderURI, doParse, verbose, &outData, &outDataLen); break; default: printf("Op %s is not yet implemented.\n", argv[1]); exit(1); } if(ortn == 0) { if(outData != NULL) { if(outFile== NULL) { printf("...generated %u bytes but no place to write it.\n", outDataLen); } else { ortn = writeFile(outFile, outData, outDataLen); if(ortn) { printf("***Error writing output to %s.\n", outFile); } else { printf("...wrote %u bytes to %s\n", outDataLen, outFile); } } } } return ortn; }
int main(int argc, char **argv) { char *kcName = NULL; SecKeychainRef kcRef = NULL; char *prefName = NULL; bool doSet = false; if((argc < 2) || (argv[1][0] == 'h')) { usage(argv); } if(!strcmp(argv[1], "get")) { doSet = false; } else if(!strcmp(argv[1], "set")) { doSet = true; } else { printf("Bad op argument\n"); usage(argv); } extern int optind; optind = 2; extern char *optarg; int arg; while ((arg = getopt(argc, argv, "p:k:h")) != -1) { switch (arg) { case 'p': prefName = optarg; break; case 'k': kcName = optarg; break; case 'h': usage(argv); } } if(optind != argc) { usage(argv); } if(prefName == NULL) { printf("***You must specify a preference name via -p.\n"); usage(argv); } CFStringRef prefStr = CFStringCreateWithCString(NULL, prefName, kCFStringEncodingASCII); if(prefStr == NULL) { printf("***Error converting pref name '%s' to CFString.\n", prefName); exit(1); } OSStatus ortn; if(kcName) { ortn = SecKeychainOpen(kcName, &kcRef); if(ortn) { cssmPerror("SecKeychainOpen", ortn); exit(1); } } SecIdentityRef idRef = NULL; if(doSet) { ortn = sslSimpleIdentPicker(kcRef, &idRef); if(ortn) { printf("Error picking identity; aborting.\n"); exit(1); } ortn = SecIdentitySetPreference(idRef, prefStr, 0); if(ortn) { cssmPerror("SecIdentitySetPreference", ortn); exit(1); } printf("...Identity preference set for name '%s'.\n", prefName); } else { ortn = SecIdentityCopyPreference(prefStr, 0, NULL, &idRef); if(ortn) { cssmPerror("SecIdentityCopyPreference", ortn); } else { SecCertificateRef certRef = NULL; ortn = SecIdentityCopyCertificate(idRef, &certRef); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); exit(1); } char *idName = kcItemPrintableName((SecKeychainItemRef)certRef); printf("Identity for prefName '%s' found : '%s'\n", prefName, idName); free(idName); CFRelease(certRef); } } CFRelease(idRef); return 0; }
int main(int argc, char **argv) { /* user-spec'd variables */ const char *kcName = DEFAULT_KC; unsigned xferSize = XFERSIZE_DEF; int port = PORT_DEF; const char *hostName = HOST_DEF; SSLCipherSuite cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; SSLProtocol prot = kTLSProtocol1Only; char password[200]; bool clientAuthEnable = false; bool isServer = false; unsigned bufSize = BUFSIZE; bool diffieHellman = false; int nonBlocking = 0; if(argc < 2) { usage(argv); } password[0] = 0; switch(argv[1][0]) { case 's': isServer = true; break; case 'c': isServer = false; break; default: usage(argv); } extern int optind; extern char *optarg; int arg; optind = 2; while ((arg = getopt(argc, argv, "h:p:k:x:c:v:w:b:aB")) != -1) { switch (arg) { case 'h': hostName = optarg; break; case 'p': port = atoi(optarg); break; case 'k': kcName = optarg; break; case 'x': xferSize = atoi(optarg); break; case 'c': if(!isServer) { printf("***Specify cipherSuite on server side.\n"); exit(1); } switch(optarg[0]) { case 'r': cipherSuite = SSL_RSA_WITH_RC4_128_SHA; break; case 'd': cipherSuite = SSL_RSA_WITH_DES_CBC_SHA; break; case 'D': cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA; break; case 'h': cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5; diffieHellman = true; break; case 'H': cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA; diffieHellman = true; break; case 'A': cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA; break; default: usage(argv); } break; case 'v': if(!isServer) { printf("***Specify protocol on server side.\n"); exit(1); } switch(optarg[0]) { case 't': prot = kTLSProtocol1Only; break; case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3Only; break; default: usage(argv); } break; case 'w': strcpy(password, optarg); break; case 'b': bufSize = atoi(optarg); break; case 'a': clientAuthEnable = true; break; case 'B': nonBlocking = 1; break; default: usage(argv); } } /* per-transfer buffer - make it random for server */ char *buf = (char *)malloc(bufSize); if(isServer) { Security::DevRandomGenerator rng; rng.random(buf, bufSize); } /* gather Diffie-Hellman params from cwd */ unsigned char *dhParams = NULL; unsigned dhParamsLen = 0; if(diffieHellman && isServer) { if(readFile(DH_PARAM_FILE, &dhParams, &dhParamsLen)) { printf("***Error reading Diffie-Hellman Params. Prepare to " "wait for a minute during SSL handshake.\n"); } } /* * Open keychain; both sides use the same one. */ OSStatus ortn; SecKeychainRef certKc = NULL; CFAbsoluteTime kcOpenStart = CFAbsoluteTimeGetCurrent(); ortn = SecKeychainOpen(kcName, &certKc); if(ortn) { printf("Error opening keychain %s (%d); aborting.\n", kcName, (int)ortn); exit(1); } if(password[0]) { ortn = SecKeychainUnlock(certKc, strlen(password), password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } CFAbsoluteTime kcOpenEnd = CFAbsoluteTimeGetCurrent(); otSocket peerSock = 0; otSocket listenSock = 0; // for server only PeerSpec peerId; if(isServer) { printf("...listening for client connection on port %d\n", port); ortn = ListenForClients(port, nonBlocking, &listenSock); if(ortn) { printf("...error establishing a listen socket. Aborting.\n"); exit(1); } ortn = AcceptClientConnection(listenSock, &peerSock, &peerId); if(ortn) { printf("...error listening for connection. Aborting.\n"); exit(1); } } else { printf("...connecting to host %s at port %d\n", hostName, port); ortn = MakeServerConnection(hostName, port, nonBlocking, &peerSock, &peerId); if(ortn) { printf("...error connecting to server %s. Aborting.\n", hostName); exit(1); } } /* start timing SSL setup */ CFAbsoluteTime setupStart = CFAbsoluteTimeGetCurrent(); SSLContextRef ctx; ortn = SSLNewContext(isServer, &ctx); if(ortn) { printSslErrStr("SSLNewContext", ortn); exit(1); } ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); if(ortn) { printSslErrStr("SSLSetIOFuncs", ortn); exit(1); } ortn = SSLSetConnection(ctx, (SSLConnectionRef)peerSock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); exit(1); } ortn = SSLSetPeerDomainName(ctx, hostName, strlen(hostName) + 1); if(ortn) { printSslErrStr("SSLSetPeerDomainName", ortn); exit(1); } /* * Server/client specific setup. * * Client uses the same keychain as server, but it uses it for * sslAddTrustedRoots() instead of getSslCerts() and * SSLSetCertificate(). */ CFArrayRef myCerts = NULL; if(clientAuthEnable || isServer) { myCerts = sslKcRefToCertArray(certKc, CSSM_FALSE, CSSM_FALSE, NULL, NULL); if(myCerts == NULL) { exit(1); } ortn = addIdentityAsTrustedRoot(ctx, myCerts); if(ortn) { exit(1); } ortn = SSLSetCertificate(ctx, myCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); exit(1); } } if(isServer) { SSLAuthenticate auth; if(clientAuthEnable) { auth = kAlwaysAuthenticate; } else { auth = kNeverAuthenticate; } ortn = SSLSetClientSideAuthenticate(ctx, auth); if(ortn) { printSslErrStr("SSLSetClientSideAuthenticate", ortn); exit(1); } ortn = SSLSetEnabledCiphers(ctx, &cipherSuite, 1); if(ortn) { printSslErrStr("SSLSetEnabledCiphers", ortn); exit(1); } ortn = SSLSetProtocolVersion(ctx, prot); if(ortn) { printSslErrStr("SSLSetProtocolVersion", ortn); exit(1); } if(dhParams != NULL) { ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); if(ortn) { printSslErrStr("SSLSetDiffieHellmanParams", ortn); exit(1); } } } else { /* client setup */ if(!clientAuthEnable) { /* We're not presenting a cert; trust the server certs */ bool foundOne; ortn = sslAddTrustedRoots(ctx, certKc, &foundOne); if(ortn) { printSslErrStr("sslAddTrustedRoots", ortn); exit(1); } } } /* * Context setup complete. Start timing handshake. */ CFAbsoluteTime hshakeStart = CFAbsoluteTimeGetCurrent(); do { ortn = SSLHandshake(ctx); } while (ortn == errSSLWouldBlock); if(ortn) { printSslErrStr("SSLHandshake", ortn); exit(1); } CFAbsoluteTime hshakeEnd = CFAbsoluteTimeGetCurrent(); /* snag these before data xfer possibly shuts down connection */ SSLProtocol negVersion; SSLCipherSuite negCipher; SSLClientCertificateState certState; // RETURNED SSLGetNegotiatedCipher(ctx, &negCipher); SSLGetNegotiatedProtocolVersion(ctx, &negVersion); SSLGetClientCertificateState(ctx, &certState); /* server sends xferSize bytes to client and shuts down */ size_t bytesMoved; CFAbsoluteTime dataStart = CFAbsoluteTimeGetCurrent(); size_t totalMoved = 0; if(isServer) { size_t bytesToGo = xferSize; bool done = false; do { size_t thisMove = bufSize; if(thisMove > bytesToGo) { thisMove = bytesToGo; } ortn = SSLWrite(ctx, buf, thisMove, &bytesMoved); switch(ortn) { case noErr: case errSSLWouldBlock: break; default: done = true; break; } bytesToGo -= bytesMoved; totalMoved += bytesMoved; if(bytesToGo == 0) { done = true; } } while(!done); if(ortn != noErr) { printSslErrStr("SSLWrite", ortn); exit(1); } } else { /* client reads until error or errSSLClosedGraceful */ bool done = false; do { ortn = SSLRead(ctx, buf, bufSize, &bytesMoved); switch(ortn) { case errSSLClosedGraceful: done = true; break; case noErr: case errSSLWouldBlock: break; default: done = true; break; } totalMoved += bytesMoved; } while(!done); if(ortn != errSSLClosedGraceful) { printSslErrStr("SSLRead", ortn); exit(1); } } /* shut down channel */ ortn = SSLClose(ctx); if(ortn) { printSslErrStr("SSLCLose", ortn); exit(1); } CFAbsoluteTime dataEnd = CFAbsoluteTimeGetCurrent(); /* how'd we do? */ printf("SSL version : %s\n", sslGetProtocolVersionString(negVersion)); printf("CipherSuite : %s\n", sslGetCipherSuiteString(negCipher)); printf("Client Cert State : %s\n", sslGetClientCertStateString(certState)); if(password[0]) { printf("keychain open/unlock : "); } else { printf("keychain open : "); } printf("%f s\n", kcOpenEnd - kcOpenStart); printf("SSLContext setup : %f s\n", hshakeStart - setupStart); printf("SSL Handshake : %f s\n", hshakeEnd - hshakeStart); printf("Data Transfer : %u bytes in %f s\n", (unsigned)totalMoved, dataEnd - dataStart); printf(" : %.1f Kbytes/s\n", totalMoved / (dataEnd - dataStart) / 1024.0); return 0; }
static void tests(void) { char *home = getenv("HOME"); char kcname1[256], kcname2[256]; SecKeychainStatus status1, status2; if (!home || strlen(home) > 200) plan_skip_all("home too big"); sprintf(kcname1, "%s/kctests/kc1/kc1", home); SecKeychainRef kc1 = NULL, kc2 = NULL; kc1 = createNewKeychainAt(kcname1, "test"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); ok_status(SecKeychainLock(kc1), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecReadPermStatus|kSecWritePermStatus, "status (locked) readable writable"); } /* Make keychain non writable. */ char kcdir1[256]; sprintf(kcdir1, "%s/kctests/kc1", home); ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecReadPermStatus, "status (locked) readable"); ok_status(SecKeychainUnlock(kc1, 4, "test", TRUE), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } /* Reopen the keychain. */ CFRelease(kc1); ok_status(SecKeychainOpen(kcname1, &kc1), "SecKeychainOpen kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } sprintf(kcname2, "%s/kctests/kc2/kc2", home); kc2 = createNewKeychainAt(kcname2, "test"); ok_unix(chmod(kcname2, 0444), "chmod kc2 0444"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Reopen the keychain. */ CFRelease(kc2); ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Restore dir to writable so cleanup code will work ok. */ ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755"); ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName); CFRelease(kc1); ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName); CFRelease(kc2); bool testWithFreshlyCreatedKeychain = true; SecKeychainRef keychain = createNewKeychain("test", "test"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); do { SecKeychainStatus keychainStatus = 0; is_status(SecKeychainUnlock(keychain, 0, NULL, true), -25293, "SecKeychainUnlock with NULL password (incorrect)"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), 0, "Check it's not unlocked"); keychainStatus = 0; ok_status(SecKeychainUnlock(keychain, strlen("test"), "test", true), "SecKeychainUnlock with correct password"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); if (testWithFreshlyCreatedKeychain) { CFRelease(keychain); testWithFreshlyCreatedKeychain = false; ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); } else { testWithFreshlyCreatedKeychain = true; ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); CFReleaseNull(keychain); } } while(!testWithFreshlyCreatedKeychain); }