func findGenericPasswordItem(attributes *GenericPasswordAttributes) (itemRef C.SecKeychainItemRef, err error) { if err = attributes.CheckValidity(); err != nil { return } serviceName := C.CString(attributes.ServiceName) defer C.free(unsafe.Pointer(serviceName)) accountName := C.CString(attributes.AccountName) defer C.free(unsafe.Pointer(accountName)) errCode := C.SecKeychainFindGenericPassword( nil, // default keychain C.UInt32(len(attributes.ServiceName)), serviceName, C.UInt32(len(attributes.AccountName)), accountName, nil, nil, &itemRef, ) err = newKeychainError(errCode) return }
// FindGenericPassword finds the first generic password item which matches the // attributes you provide. Most attributes are optional; you should pass only as // many as you need to narrow the search sufficiently for your application's // intended use. func FindGenericPassword(service, account string) (string, error) { if service == "" || account == "" { return "", errors.New("service and account are required") } cService := C.CString(service) defer C.free(unsafe.Pointer(cService)) cAccount := C.CString(account) defer C.free(unsafe.Pointer(cAccount)) cPasswordLen := C.UInt32(0) cPassword := unsafe.Pointer(nil) errCode := C.SecKeychainFindGenericPassword( nil, // default keychain C.UInt32(C.strlen(cService)), cService, C.UInt32(C.strlen(cAccount)), cAccount, &cPasswordLen, &cPassword, nil, ) if err := newKeychainError(errCode); err != nil { return "", err } defer C.SecKeychainItemFreeContent(nil, cPassword) return C.GoStringN((*C.char)(cPassword), C.int(cPasswordLen)), nil }
// FindGenericPassword finds a generic password with the given // attributes in the default keychain and returns the password field // if found. If not found, an error is returned. func FindGenericPassword(attributes *GenericPasswordAttributes) ([]byte, error) { if err := attributes.CheckValidity(); err != nil { return nil, err } serviceName := C.CString(attributes.ServiceName) defer C.free(unsafe.Pointer(serviceName)) accountName := C.CString(attributes.AccountName) defer C.free(unsafe.Pointer(accountName)) var passwordLength C.UInt32 var password unsafe.Pointer errCode := C.SecKeychainFindGenericPassword( nil, // default keychain C.UInt32(len(attributes.ServiceName)), serviceName, C.UInt32(len(attributes.AccountName)), accountName, &passwordLength, &password, nil, ) if err := newKeychainError(errCode); err != nil { return nil, err } defer C.SecKeychainItemFreeContent(nil, password) return C.GoBytes(password, C.int(passwordLength)), nil }
func (*keychainOSX) DeletePassword(service, account string) error { // Validate input serviceValid := isValidNonNullUTF8(service) accountValid := isValidNonNullUTF8(account) if !(serviceValid && accountValid) { return ErrInvalidValue } // Convert values to C strings serviceCStr := C.CString(service) defer C.free(unsafe.Pointer(serviceCStr)) accountCStr := C.CString(account) defer C.free(unsafe.Pointer(accountCStr)) // Grab the item var item C.SecKeychainItemRef status := C.SecKeychainFindGenericPassword( nil, C.UInt32(len(service)), serviceCStr, C.UInt32(len(account)), accountCStr, nil, nil, &item, ) // Check for errors if status != C.errSecSuccess { return ErrNotFound } // Delete the item status = C.SecKeychainItemDelete(item) // Free the item C.CFRelease(C.CFTypeRef(item)) // Check for errors if status != C.errSecSuccess { return ErrUnknown } // All done return nil }
func (*keychainOSX) GetPassword(service, account string) (string, error) { // Validate input serviceValid := isValidNonNullUTF8(service) accountValid := isValidNonNullUTF8(account) if !(serviceValid && accountValid) { return "", ErrInvalidValue } // Convert values to C strings serviceCStr := C.CString(service) defer C.free(unsafe.Pointer(serviceCStr)) accountCStr := C.CString(account) defer C.free(unsafe.Pointer(accountCStr)) // Look for a match var passwordData unsafe.Pointer var passwordDataLength C.UInt32 status := C.SecKeychainFindGenericPassword( nil, C.UInt32(len(service)), serviceCStr, C.UInt32(len(account)), accountCStr, &passwordDataLength, &passwordData, nil, ) // Check for errors if status != C.errSecSuccess { return "", ErrNotFound } // Create the result result := C.GoStringN((*C.char)(passwordData), C.int(passwordDataLength)) // Cleanup the temporary buffer C.SecKeychainItemFreeContent(nil, passwordData) // All done return result, nil }