+
+
+/*
+ * 'http_cdsa_open_keychain()' - Open (or create) a keychain.
+ */
+
+static SecKeychainRef /* O - Keychain or NULL */
+http_cdsa_open_keychain(
+ const char *path, /* I - Path to keychain */
+ char *filename, /* I - Keychain filename */
+ size_t filesize) /* I - Size of filename buffer */
+{
+ SecKeychainRef keychain = NULL;/* Temporary keychain */
+ OSStatus err; /* Error code */
+ Boolean interaction; /* Interaction allowed? */
+ SecKeychainStatus status = 0; /* Keychain status */
+
+
+ /*
+ * Get the keychain filename...
+ */
+
+ if (!path)
+ {
+ path = http_cdsa_default_path(filename, filesize);
+ tls_cups_keychain = 1;
+ }
+ else
+ {
+ strlcpy(filename, path, filesize);
+ tls_cups_keychain = 0;
+ }
+
+ /*
+ * Save the interaction setting and disable while we open the keychain...
+ */
+
+ SecKeychainGetUserInteractionAllowed(&interaction);
+ SecKeychainSetUserInteractionAllowed(FALSE);
+
+ if (access(path, R_OK) && tls_cups_keychain)
+ {
+ /*
+ * Create a new keychain at the given path...
+ */
+
+ err = SecKeychainCreate(path, _CUPS_CDSA_PASSLEN, _CUPS_CDSA_PASSWORD, FALSE, NULL, &keychain);
+ }
+ else
+ {
+ /*
+ * Open the existing keychain and unlock as needed...
+ */
+
+ err = SecKeychainOpen(path, &keychain);
+
+ if (err == noErr)
+ err = SecKeychainGetStatus(keychain, &status);
+
+ if (err == noErr && !(status & kSecUnlockStateStatus) && tls_cups_keychain)
+ err = SecKeychainUnlock(keychain, _CUPS_CDSA_PASSLEN, _CUPS_CDSA_PASSWORD, TRUE);
+ }
+
+ /*
+ * Restore interaction setting...
+ */
+
+ SecKeychainSetUserInteractionAllowed(interaction);
+
+ /*
+ * Release the keychain if we had any errors...
+ */
+
+ if (err != noErr)
+ {
+ /* TODO: Set cups last error string */
+ DEBUG_printf(("4http_cdsa_open_keychain: Unable to open keychain (%d), returning NULL.", (int)err));
+
+ if (keychain)
+ {
+ CFRelease(keychain);
+ keychain = NULL;
+ }
+ }
+
+ /*
+ * Return the keychain or NULL...
+ */
+
+ return (keychain);
+}
+
+
+/*
+ * 'http_cdsa_open_system_keychain()' - Open the System keychain.
+ */
+
+static SecKeychainRef
+http_cdsa_open_system_keychain(void)
+{
+ SecKeychainRef keychain = NULL;/* Temporary keychain */
+ OSStatus err; /* Error code */
+ Boolean interaction; /* Interaction allowed? */
+ SecKeychainStatus status = 0; /* Keychain status */
+
+
+ /*
+ * Save the interaction setting and disable while we open the keychain...
+ */
+
+ SecKeychainGetUserInteractionAllowed(&interaction);
+ SecKeychainSetUserInteractionAllowed(TRUE);
+
+ err = SecKeychainOpen("/Library/Keychains/System.keychain", &keychain);
+
+ if (err == noErr)
+ err = SecKeychainGetStatus(keychain, &status);
+
+ if (err == noErr && !(status & kSecUnlockStateStatus))
+ err = errSecInteractionNotAllowed;
+
+ /*
+ * Restore interaction setting...
+ */
+
+ SecKeychainSetUserInteractionAllowed(interaction);
+
+ /*
+ * Release the keychain if we had any errors...
+ */
+
+ if (err != noErr)
+ {
+ /* TODO: Set cups last error string */
+ DEBUG_printf(("4http_cdsa_open_system_keychain: Unable to open keychain (%d), returning NULL.", (int)err));
+
+ if (keychain)
+ {
+ CFRelease(keychain);
+ keychain = NULL;
+ }
+ }
+
+ /*
+ * Return the keychain or NULL...
+ */
+
+ return (keychain);
+}