// 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
}
// FindInternetPassword function finds the first Internet 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. SecKeychainFindInternetPassword optionally
// returns a reference to the found item.
func FindInternetPassword(server, domain, account, path string, port uint16, protocol ProtocolType, authType AuthenticationType) (string, error) {
	if server == "" || account == "" {
		return "", errors.New("server and account are required")
	}

	cServer := C.CString(server)
	defer C.free(unsafe.Pointer(cServer))

	cDomain := C.CString(domain)
	defer C.free(unsafe.Pointer(cDomain))

	cAccount := C.CString(account)
	defer C.free(unsafe.Pointer(cAccount))

	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	cPasswordLen := C.UInt32(0)
	cPassword := unsafe.Pointer(nil)

	errCode := C.SecKeychainFindInternetPassword(
		nil, // default keychain,
		C.UInt32(C.strlen(cServer)),
		cServer,
		C.UInt32(C.strlen(cDomain)),
		cDomain,
		C.UInt32(C.strlen(cAccount)),
		cAccount,
		C.UInt32(C.strlen(cPath)),
		cPath,
		C.UInt16(port),
		C.SecProtocolType(protocol),
		C.SecAuthenticationType(authType),
		&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
}
Exemple #4
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
}