func splitServer(serverURL string) (*C.struct_Server, error) { u, err := url.Parse(serverURL) if err != nil { return nil, err } hostAndPort := strings.Split(u.Host, ":") host := hostAndPort[0] var port int if len(hostAndPort) == 2 { p, err := strconv.Atoi(hostAndPort[1]) if err != nil { return nil, err } port = p } proto := C.kSecProtocolTypeHTTPS if u.Scheme != "https" { proto = C.kSecProtocolTypeHTTP } return &C.struct_Server{ proto: C.SecProtocolType(proto), host: C.CString(host), port: C.uint(port), path: C.CString(u.Path), }, 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 }