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
}
Exemple #4
0
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
}
Exemple #5
0
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
}