// 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 }
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 }