Пример #1
0
static VALUE rb_default_keychain(VALUE self){
  SecKeychainRef keychain=NULL;
  OSStatus result =SecKeychainCopyDefault(&keychain);
  CheckOSStatusOrRaise(result);

  return KeychainFromSecKeychainRef(keychain);
}
Пример #2
0
static void
get_password_from_keychain(Pop3 pc, const char *username,
						   const char *servername,
						   /*@out@ */ char *password,
						   /*@out@ */
						   unsigned char *password_len)
{
	SecKeychainRef kc;
	OSStatus rc;
	char *secpwd;
	UInt32 pwdlen;
	rc = SecKeychainCopyDefault(&kc);
	if (rc != noErr) {
		DM(pc, DEBUG_ERROR, "passmgr: unable to open keychain, exiting\n");
		exit(EXIT_FAILURE);
	}
	rc = SecKeychainFindInternetPassword(kc, strlen(servername),
										 servername, 0, NULL,
										 strlen(username), username, 0,
										 NULL, 0, NULL,
										 kSecAuthenticationTypeDefault,
										 &pwdlen, (void **) &secpwd, NULL);
	if (rc != noErr) {
		DM(pc, DEBUG_ERROR,
		   "passmgr: keychain password grab for %s at %s failed, exiting\n", username, servername);
		DM(pc, DEBUG_ERROR, "passmgr: (perhaps you pressed 'deny')\n");
		/* this seems like the sanest thing to do, for now */
		exit(EXIT_FAILURE);
	}

	if (pwdlen < *password_len) {
		strncpy(password, secpwd, pwdlen);
		password[pwdlen] = '\0';
		*password_len = pwdlen;
	} else {
		DM(pc, DEBUG_ERROR,
		   "passmgr: warning: your password appears longer (%lu) than expected (%d)\n",
		   strlen(secpwd), *password_len - 1);
	}
	rc = SecKeychainItemFreeContent(NULL, secpwd);
	return;
}
Пример #3
0
void* CopyDefaultAndReleaseInSingleThread(void* arg)
{
    OSStatus result;

    double endTime = GetTimeOfDay() + kTestLength;
    do
    {
        SecKeychainRef kc;
        result  = SecKeychainCopyDefault(&kc);
        CFRelease(kc);

        if (result != noErr)
        {
            return NULL;
        }

    } while (GetTimeOfDay() < endTime);

    return NULL;
}
/*
 * 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
}
SecKeyRef
SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error)
{
	OSStatus result = paramErr; // default result for an early exit
	SecKeyRef key = NULL;
	SecKeychainRef keychain = NULL;
	SecAccessRef access;
	CFStringRef label;
	CFStringRef appLabel;
	CFStringRef appTag;
	CFStringRef dateLabel = NULL;
	
	CSSM_ALGORITHMS algorithm;
	uint32 keySizeInBits;
	CSSM_KEYUSE keyUsage;
	uint32 keyAttr = CSSM_KEYATTR_RETURN_DEFAULT;
	CSSM_KEYCLASS keyClass;
	CFTypeRef value;
	Boolean isPermanent;
	Boolean isExtractable;
	
	// verify keychain parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecUseKeychain, (const void **)&keychain))
		keychain = NULL;
	else if (SecKeychainGetTypeID() != CFGetTypeID(keychain)) {
		keychain = NULL;
		goto errorExit;
	}
	else
		CFRetain(keychain);

	// verify permanent parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsPermanent, (const void **)&value))
		isPermanent = false;
	else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value)))
		goto errorExit;
	else
		isPermanent = CFEqual(kCFBooleanTrue, value);
	if (isPermanent) {
		if (keychain == NULL) {
			// no keychain was specified, so use the default keychain
			result = SecKeychainCopyDefault(&keychain);
		}
		keyAttr |= CSSM_KEYATTR_PERMANENT;
	}

	// verify extractable parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsExtractable, (const void **)&value))
		isExtractable = true; // default to extractable if value not specified
	else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value)))
		goto errorExit;
	else
		isExtractable = CFEqual(kCFBooleanTrue, value);
	if (isExtractable)
		keyAttr |= CSSM_KEYATTR_EXTRACTABLE;

	// verify access parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrAccess, (const void **)&access))
		access = NULL;
	else if (SecAccessGetTypeID() != CFGetTypeID(access))
		goto errorExit;

	// verify label parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrLabel, (const void **)&label))
		label = (dateLabel = utilCopyDefaultKeyLabel()); // no label provided, so use default
	else if (CFStringGetTypeID() != CFGetTypeID(label))
		goto errorExit;

	// verify application label parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationLabel, (const void **)&appLabel))
		appLabel = (dateLabel) ? dateLabel : (dateLabel = utilCopyDefaultKeyLabel());
	else if (CFStringGetTypeID() != CFGetTypeID(appLabel))
		goto errorExit;

	// verify application tag parameter
	if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationTag, (const void **)&appTag))
		appTag = NULL;
	else if (CFStringGetTypeID() != CFGetTypeID(appTag))
		goto errorExit;

    utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass);

	if (!keychain) {
		// the generated key will not be stored in any keychain
		result = SecKeyGenerate(keychain, algorithm, keySizeInBits, 0, keyUsage, keyAttr, access, &key);
	}
	else {
		// we can set the label attributes on the generated key if it's a keychain item
		size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 0;
		char *labelBuf = (char *)malloc(labelBufLen);
		size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 0;
		char *appLabelBuf = (char *)malloc(appLabelBufLen);
		size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 0;
		char *appTagBuf = (char *)malloc(appTagBufLen);

		if (label && !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8))
			labelBuf[0]=0;
		if (appLabel && !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8))
			appLabelBuf[0]=0;
		if (appTag && !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8))
			appTagBuf[0]=0;
		
		SecKeychainAttribute attrs[] = {
			{ kSecKeyPrintName, strlen(labelBuf), (char *)labelBuf },
			{ kSecKeyLabel, strlen(appLabelBuf), (char *)appLabelBuf },
			{ kSecKeyApplicationTag, strlen(appTagBuf), (char *)appTagBuf }	};
		SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
		if (!appTag) --attributes.count;
	
		result = SecKeyGenerateWithAttributes(&attributes,
			keychain, algorithm, keySizeInBits, 0,
			keyUsage, keyAttr, access, &key);

		free(labelBuf);
		free(appLabelBuf);
		free(appTagBuf);
	}

errorExit:
	if (result && error) {
		*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, result, NULL);
	}
	if (dateLabel)
		CFRelease(dateLabel);
	if (keychain)
		CFRelease(keychain);

    return key;
}
OSStatus SecCertificateRequestGetResult(
        SecCertificateRequestRef certRequestRef,
        SecKeychainRef keychain,
        sint32 *estimatedTime,
        SecCertificateRef *certificateRef)
{
	BEGIN_SECAPI

	CssmData certData;
	*certificateRef = NULL;
	CertificateRequest::required(certRequestRef)->getResult(estimatedTime, certData);
	if(certData.data() != NULL) {
		/*
		 * Convert to SecCertifcateRef, optionally import. 
		 */
		CFDataRef cfCert = CFDataCreate(NULL, (UInt8 *)certData.data(), certData.Length);
		SecExternalItemType itemType = kSecItemTypeCertificate;
		CFArrayRef outItems = NULL;
		bool freeKcRef = false;
		OSStatus ortn;
		
		if(keychain == NULL) {
			/* 
			 * Unlike most Sec* calls, if the keychain argument to SecKeychainItemImport()
			 * is NULL, the item is not imported to the default keychain. At our
			 * interface, however, a NULL keychain means "import to the default
			 * keychain". 
			 */
			ortn = SecKeychainCopyDefault(&keychain);
			if(ortn) {
				certReqDbg("GetResult: SecKeychainCopyDefault failure");
				/* oh well, there's nothing we can do about this */
			}
			else {
				freeKcRef = true;
			}
		}
		ortn = SecKeychainItemImport(cfCert, NULL,
			NULL,			// format, don't care
			&itemType,
			0,				// flags
			NULL,			// keyParams
			keychain,		// optional, like ours
			&outItems);
		CFRelease(cfCert);
		if(freeKcRef) {
			CFRelease(keychain);
		}
		if(ortn) {
			certReqDbg("SecCertificateRequestGetResult: SecKeychainItemImport failure");
			MacOSError::throwMe(ortn);
		}
		CFIndex numItems = CFArrayGetCount(outItems);
		switch(numItems) {
			case 0:
				certReqDbg("SecCertificateRequestGetResult: import zero items");
				MacOSError::throwMe(errSecInternalComponent);
			default:
				certReqDbg("SecCertificateRequestGetResult: import %d items", 
					(int)numItems);
				/* but drop thru anyway, take the first one */
			case 1:
				SecCertificateRef certRef = 
					(SecCertificateRef)(CFArrayGetValueAtIndex(outItems, 0));
				if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
					certReqDbg("SecCertificateRequestGetResult: bad type");
				}
				else {
					CFRetain(certRef);
					*certificateRef = certRef;
				}
		}
		CFRelease(outItems);
	}	
	END_SECAPI
}
Пример #7
0
int main(int argc, char * const argv[]) {
  int verbose = 0;
  int dryRun = 0;
  int version = 0;
  char *toKeychainPath = NULL;

  struct option longopts[] = {
    { "dry-run",      no_argument,         &dryRun,     1   },
    { "to-keychain",  required_argument,   NULL,        'k' },
    { "verbose",      no_argument,         &verbose,    1   },
    { "version",      no_argument,         &version,       1   },
    { NULL,           0,                   NULL,        0   }
  };

  int ch;
  while ((ch = getopt_long(argc, argv, "dk:v", longopts, NULL)) != -1) {
    switch (ch) {
      case 'k':
        toKeychainPath = optarg;
        break;
      case 'd':
        dryRun = 1;
        break;
      case 'v':
        verbose = 1;
        break;
      case 0:
        // Handle long-only options
        break;
      default:
        SRPrintUsage();
        exit(EX_USAGE);
    }
  }
  argc -= optind;
  argv += optind;

  if (version) {
    fprintf(stderr, "splitring 1.1\nCopyright (C) 2013 Phil Calvin\n");
    exit(0);
  }

  if (!argc) {
    SRPrintUsage();
    exit(EX_USAGE);
  }

  CFMutableArrayRef keychains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

  // Iterate the passed keychain paths, opening each one
  for (int i = 0; i < argc; i++) {
    char* path = realpath(argv[i], NULL);
    if (path) {
      SecKeychainRef keychain = SROpenKeychain(path);
      CFArrayAppendValue(keychains, keychain);
      CFRelease(keychain);
      free(path);
    } else {
      fprintf(stderr, "Unable to find keychain: %s\n", argv[i]);
    }
  }

  // Unlock each of the keychains
  for (int i = 0; i < CFArrayGetCount(keychains); i++) {
    SecKeychainRef keychain = (SecKeychainRef)CFArrayGetValueAtIndex(keychains, i);
    // Unlock it; might not need to do this
    if (verbose) {
      UInt32 bufferSize = 4096;
      char keychainPath[bufferSize];
      SecKeychainGetPath(keychain, &bufferSize, keychainPath);
      fprintf(stderr, "Unlocking keychain at path: %s\n", keychainPath);
    }
    OSStatus status = SecKeychainUnlock(keychain, 0, NULL, FALSE);
    SRHandleError(status, true);
  }

  SecKeychainRef targetKeychain = NULL;
  if (toKeychainPath) {
    // Convert this to a canonical path
    char* canonicalPath = realpath(toKeychainPath, NULL);
    if (canonicalPath) {
      // Import to the specified keychain
      targetKeychain = SROpenKeychain(canonicalPath);
      free(canonicalPath);
    } else {
      fprintf(stderr, "Unable to find keychain: %s\n", toKeychainPath);
      exit(EX_IOERR);
    }
  } else {
    // Import to the default keychain if one wasn't specified
    OSStatus status = SecKeychainCopyDefault(&targetKeychain);
    SRHandleError(status, true);
    status = SecKeychainUnlock(targetKeychain, 0, NULL, FALSE);
    SRHandleError(status, true);
  }

  // Search for all items
  CFMutableArrayRef classes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
  CFArrayAppendValue(classes, kSecClassGenericPassword);
  CFArrayAppendValue(classes, kSecClassInternetPassword);
  //CFArrayAppendValue(classes, kSecClassCertificate);
  //CFArrayAppendValue(classes, kSecClassIdentity);
  //CFArrayAppendValue(classes, kSecClassKey);

  CFArrayRef items = SRCopyItems(keychains, classes);

  if (verbose) {
    UInt32 bufferSize = 4096;
    char defaultKeychainPath[bufferSize];
    SecKeychainGetPath(targetKeychain, &bufferSize, defaultKeychainPath);
    fprintf(stderr, "Importing %li items to keychain at path: %s\n",
            CFArrayGetCount(items),
            defaultKeychainPath);
  }

  SRCopyItemsToKeychain(items, targetKeychain, verbose, dryRun);

  CFRelease(items);
  CFRelease(targetKeychain);
  CFRelease(keychains);
  return 0;
}
Пример #8
0
/*
 * XXXX the following needs to be done in the S/MIME layer code
 * after signature of a signerinfo is verified
 */
OSStatus
SecCmsSignerInfoSaveSMIMEProfile(SecCmsSignerInfoRef signerinfo)
{
    SecCertificateRef cert = NULL;
    CSSM_DATA_PTR profile = NULL;
    SecCmsAttribute *attr;
    CSSM_DATA_PTR utc_stime = NULL;
    CSSM_DATA_PTR ekp;
    int save_error;
    OSStatus rv;
    Boolean must_free_cert = PR_FALSE;
    OSStatus status;
    SecKeychainRef keychainOrArray;
    
    status = SecKeychainCopyDefault(&keychainOrArray);

    /* sanity check - see if verification status is ok (unverified does not count...) */
    if (signerinfo->verificationStatus != SecCmsVSGoodSignature)
        return SECFailure;

    /* find preferred encryption cert */
    if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr) &&
	(attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr,
			       SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, PR_TRUE)) != NULL)
    { /* we have a SMIME_ENCRYPTION_KEY_PREFERENCE attribute! */
	ekp = SecCmsAttributeGetValue(attr);
	if (ekp == NULL)
	    return SECFailure;

	/* we assume that all certs coming with the message have been imported to the */
	/* temporary database */
	cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, ekp);
	if (cert == NULL)
	    return SECFailure;
	must_free_cert = PR_TRUE;
    }

    if (cert == NULL) {
	/* no preferred cert found?
	 * find the cert the signerinfo is signed with instead */
	CFStringRef emailAddress=NULL;

	cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, keychainOrArray);
	if (cert == NULL)
	    return SECFailure;
	if (SecCertificateGetEmailAddress(cert,&emailAddress))
	    return SECFailure;
    }

    /* verify this cert for encryption (has been verified for signing so far) */    /* don't verify this cert for encryption. It may just be a signing cert.
     * that's OK, we can still save the S/MIME profile. The encryption cert
     * should have already been saved */
#ifdef notdef
    if (CERT_VerifyCert(keychainOrArray, cert, certUsageEmailRecipient, CFAbsoluteTimeGetCurrent(), NULL) != SECSuccess) {
	if (must_free_cert)
	    CERT_DestroyCertificate(cert);
	return SECFailure;
    }
#endif

    /* XXX store encryption cert permanently? */

    /*
     * Remember the current error set because we do not care about
     * anything set by the functions we are about to call.
     */
    save_error = PORT_GetError();

    if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) {
	attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr,
				       SEC_OID_PKCS9_SMIME_CAPABILITIES,
				       PR_TRUE);
	profile = SecCmsAttributeGetValue(attr);
	attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr,
				       SEC_OID_PKCS9_SIGNING_TIME,
				       PR_TRUE);
	utc_stime = SecCmsAttributeGetValue(attr);
    }

    rv = CERT_SaveSMimeProfile (cert, profile, utc_stime);
    if (must_free_cert)
	CERT_DestroyCertificate(cert);

    /*
     * Restore the saved error in case the calls above set a new
     * one that we do not actually care about.
     */
    PORT_SetError (save_error);

    return rv;
}