Example #1
0
func loadSystemRoots() (*CertPool, error) {
	roots := NewCertPool()

	var data C.CFDataRef = nil
	var untrustedData C.CFDataRef = nil
	err := C.FetchPEMRoots(&data, &untrustedData)
	if err == -1 {
		// TODO: better error message
		return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo")
	}

	defer C.CFRelease(C.CFTypeRef(data))
	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
	roots.AppendCertsFromPEM(buf)
	if untrustedData == nil {
		return roots, nil
	}
	defer C.CFRelease(C.CFTypeRef(untrustedData))
	buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData)))
	untrustedRoots := NewCertPool()
	untrustedRoots.AppendCertsFromPEM(buf)

	trustedRoots := NewCertPool()
	for _, c := range roots.certs {
		if !untrustedRoots.contains(c) {
			trustedRoots.AddCert(c)
		}
	}
	return trustedRoots, nil
}
Example #2
0
// Given a PostScript font name the function will attempt to load a matching
// font and return a font object back to the caller.
//
// If no font with the given name is found a font that most closely resembles
// what was requested will be returned instead based on the platform's fallback
// mechanism.
// More details on the mechanism can be found at:
// https://developer.apple.com/library/mac/documentation/Carbon/Reference/CTFontRef/#//apple_ref/c/func/CTFontCreateWithName
//
// The function returns an error if loading the font failed for any reason.
func NewFontWithName(fontName string) (font *Font, err error) {
	cfname := GoStringToCFString(fontName)
	defer C.CFRelease(C.CFTypeRef(cfname))

	font = &Font{
		ref: C.CTFontCreateWithName(cfname, 0.0, nil),
	}

	if font.ref == nil {
		err = fmt.Errorf("CoreText failed to craete a CTFontRef object with name '%s'", fontName)
		return
	}

	runtime.SetFinalizer(font, (*Font).release)

	name := C.CTFontCopyPostScriptName(font.ref)
	defer C.CFRelease(C.CFTypeRef(name))

	family := C.CTFontCopyFamilyName(font.ref)
	defer C.CFRelease(C.CFTypeRef(family))

	display := C.CTFontCopyDisplayName(font.ref)
	defer C.CFRelease(C.CFTypeRef(display))

	font.name = CFStringToGoString(name)
	font.family = CFStringToGoString(family)
	font.display = CFStringToGoString(display)
	return
}
Example #3
0
func CGImageCreateWithImageNoCopy(img image.Image) (cgimg C.CGImageRef, err error) {
	var data imageData

	if data, err = extractImageData(img); err != nil {
		return
	}

	provider := C.CGDataProviderCreateWithData(
		nil,
		unsafe.Pointer(&data.pixels[0]),
		C.size_t(len(data.pixels)),
		nil,
	)

	cgimg = C.CGImageCreate(
		C.size_t(data.width),
		C.size_t(data.height),
		C.size_t(data.bpc),
		C.size_t(data.bpp),
		C.size_t(data.stride),
		data.colors,
		data.info,
		provider,
		nil,
		false,
		C.kCGRenderingIntentDefault,
	)

	C.CFRelease(provider)
	C.CFRelease(data.colors)
	return
}
Example #4
0
// GetAllAccountNames returns a list of all account names for the
// given service name in the default keychain.
func GetAllAccountNames(serviceName string) (accountNames []string, err error) {
	var serviceNameString C.CFStringRef
	if serviceNameString, err = _UTF8StringToCFString(serviceName); err != nil {
		return
	}
	defer C.CFRelease(C.CFTypeRef(serviceNameString))

	query := map[C.CFTypeRef]C.CFTypeRef{
		secClass:            secClassGenericPassword,
		secAttrService:      C.CFTypeRef(serviceNameString),
		secMatchLimit:       secMatchLimitAll,
		secReturnAttributes: C.CFTypeRef(C.kCFBooleanTrue),
	}
	queryDict := mapToCFDictionary(query)
	defer C.CFRelease(C.CFTypeRef(queryDict))

	var resultsRef C.CFTypeRef
	errCode := C.SecItemCopyMatching(queryDict, &resultsRef)
	err = newKeychainError(errCode)
	if err == ErrItemNotFound {
		return []string{}, nil
	} else if err != nil {
		return nil, err
	}

	defer C.CFRelease(resultsRef)

	// The resultsRef should always be an array (because kSecReturnAttributes is true)
	// but it's a good sanity check and useful if want to support kSecReturnRef in the future.
	typeID := C.CFGetTypeID(resultsRef)
	if typeID != C.CFArrayGetTypeID() {
		typeDesc := C.CFCopyTypeIDDescription(typeID)
		defer C.CFRelease(C.CFTypeRef(typeDesc))
		err = fmt.Errorf("Invalid result type: %s", _CFStringToUTF8String(typeDesc))
		return
	}

	results := _CFArrayToArray(C.CFArrayRef(resultsRef))
	for _, result := range results {
		m := _CFDictionaryToMap(C.CFDictionaryRef(result))
		resultServiceName := _CFStringToUTF8String(C.CFStringRef(m[secAttrService]))
		if resultServiceName != serviceName {
			err = fmt.Errorf("Expected service name %s, got %s", serviceName, resultServiceName)
			return
		}
		accountName := _CFStringToUTF8String(C.CFStringRef(m[secAttrAccount]))
		accountNames = append(accountNames, accountName)
	}
	return
}
Example #5
0
// Covert attributes to CFDictionaryRef. You need to release the result.
func convertAttr(attr map[string]interface{}) (C.CFDictionaryRef, error) {
	m := make(map[C.CFTypeRef]C.CFTypeRef)
	for key, i := range attr {
		var valueRef C.CFTypeRef
		switch i.(type) {
		default:
			return nil, fmt.Errorf("Unsupported value type for keychain item: %v", reflect.TypeOf(i))
		case C.CFTypeRef:
			valueRef = i.(C.CFTypeRef)
		case bool:
			if i == true {
				valueRef = C.CFTypeRef(C.kCFBooleanTrue)
			} else {
				valueRef = C.CFTypeRef(C.kCFBooleanFalse)
			}
		case []byte:
			bytesRef, err := bytesToCFData(i.([]byte))
			if err != nil {
				return nil, err
			}
			valueRef = C.CFTypeRef(bytesRef)
			defer C.CFRelease(valueRef)
		case string:
			stringRef, err := stringToCFString(i.(string))
			if err != nil {
				return nil, err
			}
			valueRef = C.CFTypeRef(stringRef)
			defer C.CFRelease(valueRef)
		case Convertable:
			convertedRef, err := (i.(Convertable)).Convert()
			if err != nil {
				return nil, err
			}
			valueRef = C.CFTypeRef(convertedRef)
			defer C.CFRelease(valueRef)
		}
		keyRef, err := stringToCFString(key)
		if err != nil {
			return nil, err
		}
		m[C.CFTypeRef(keyRef)] = valueRef
	}

	cfDict, err := mapToCFDictionary(m)
	if err != nil {
		return nil, err
	}
	return cfDict, nil
}
Example #6
0
// QueryItem returns a list of query results.
func QueryItem(item Item) ([]QueryResult, error) {
	cfDict, err := convertAttr(item.attr)
	if err != nil {
		return nil, err
	}
	defer C.CFRelease(C.CFTypeRef(cfDict))

	var resultsRef C.CFTypeRef
	errCode := C.SecItemCopyMatching(cfDict, &resultsRef)
	if Error(errCode) == ErrorItemNotFound {
		return nil, nil
	}
	err = checkError(errCode)
	if err != nil {
		return nil, err
	}
	defer C.CFRelease(resultsRef)

	results := make([]QueryResult, 0, 1)

	typeID := C.CFGetTypeID(resultsRef)
	if typeID == C.CFArrayGetTypeID() {
		arr := cfArrayToArray(C.CFArrayRef(resultsRef))
		for _, dictRef := range arr {
			item, err := convertResult(C.CFDictionaryRef(dictRef))
			if err != nil {
				return nil, err
			}
			results = append(results, *item)
		}
	} else if typeID == C.CFDictionaryGetTypeID() {
		item, err := convertResult(C.CFDictionaryRef(resultsRef))
		if err != nil {
			return nil, err
		}
		results = append(results, *item)
	} else if typeID == C.CFDataGetTypeID() {
		b, err := cfDataToBytes(C.CFDataRef(resultsRef))
		if err != nil {
			return nil, err
		}
		item := QueryResult{Data: b}
		results = append(results, item)
	} else {
		return nil, fmt.Errorf("Invalid result type: %s", cfTypeDescription(resultsRef))
	}

	return results, nil
}
Example #7
0
func (w *Watcher) watchPath(path string, options *Options) error {
	path, _ = filepath.Abs(path)

	w.wmut.Lock()
	_, found := w.watches[path]
	w.wmut.Unlock()

	if !found {
		cPaths := C.ArrayCreateMutable(C.int(1))
		defer C.CFRelease(C.CFTypeRef(cPaths))

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

		str := C.CFStringCreateWithCString(nil, cpath, C.kCFStringEncodingUTF8)
		C.CFArrayAppendValue(cPaths, unsafe.Pointer(str))

		context := C.FSEventStreamContext{info: unsafe.Pointer(&w.internalEvent)}
		latency := C.CFTimeInterval(0)
		if options != nil && options.Throttle {
			latency = C.CFTimeInterval(options.ThrottleDuration / time.Second)
		}
		stream := C.EventStreamCreate(&context, cPaths, C.kFSEventStreamEventIdSinceNow+(1<<64), latency)
		w.wmut.Lock()
		w.watches[path] = stream
		w.wmut.Unlock()
		C.FSEventStreamScheduleWithRunLoop(stream, w.rlref, C.kCFRunLoopDefaultMode)
		C.FSEventStreamStart(stream)
	}

	return nil
}
Example #8
0
func CaptureRect(rect image.Rectangle) (*image.RGBA, error) {
	displayID := C.CGMainDisplayID()
	width := int(C.CGDisplayPixelsWide(displayID))
	rawData := C.CGDataProviderCopyData(C.CGImageGetDataProvider(C.CGDisplayCreateImage(displayID)))

	length := int(C.CFDataGetLength(rawData))
	ptr := unsafe.Pointer(C.CFDataGetBytePtr(rawData))

	var slice []byte
	hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
	hdrp.Data = uintptr(ptr)
	hdrp.Len = length
	hdrp.Cap = length

	imageBytes := make([]byte, length)

	for i := 0; i < length; i += 4 {
		imageBytes[i], imageBytes[i+2], imageBytes[i+1], imageBytes[i+3] = slice[i+2], slice[i], slice[i+1], slice[i+3]
	}

	C.CFRelease(rawData)

	img := &image.RGBA{Pix: imageBytes, Stride: 4 * width, Rect: rect}
	return img, nil
}
Example #9
0
func NewCFError(c C.CFErrorRef) *CFError {
	e := &CFError{
		Domain: convertCFStringToString(C.CFErrorGetDomain(c)),
		Code:   int(C.CFErrorGetCode(c)),
	}
	cfDict := C.CFErrorCopyUserInfo(c)
	defer C.CFRelease(C.CFTypeRef(cfDict))
	if userInfo, err := convertCFDictionaryToMap(cfDict); err == nil {
		// on error, skip user info
		e.UserInfo = userInfo
	}
	cfStr := C.CFErrorCopyDescription(c)
	defer C.CFRelease(C.CFTypeRef(cfStr))
	e.Description = convertCFStringToString(cfStr)
	return e
}
Example #10
0
// ExportFromKeychain ...
func ExportFromKeychain(itemRefsToExport []C.CFTypeRef, outputFilePath string, isAskForPassword bool) error {
	passphraseCString := C.CString("")
	defer C.free(unsafe.Pointer(passphraseCString))

	var exportedData C.CFDataRef
	var exportParams C.SecItemImportExportKeyParameters
	exportParams.keyUsage = nil
	exportParams.keyAttributes = nil
	exportParams.version = C.SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION
	if isAskForPassword {
		exportParams.flags = C.kSecKeySecurePassphrase
		exportParams.passphrase = nil
		exportParams.alertTitle = nil

		promptText := C.CString("Enter a password which will be used to protect the exported items")
		defer C.free(unsafe.Pointer(promptText))
		exportParams.alertPrompt = convertCStringToCFString(promptText)
	} else {
		exportParams.flags = 0
		exportParams.passphrase = (C.CFTypeRef)(convertCStringToCFString(passphraseCString))
		exportParams.alertTitle = nil
		exportParams.alertPrompt = nil
	}

	// create a C array from the input
	ptr := (*unsafe.Pointer)(&itemRefsToExport[0])
	cfArrayForExport := C.CFArrayCreate(
		C.kCFAllocatorDefault,
		ptr,
		C.CFIndex(len(itemRefsToExport)),
		&C.kCFTypeArrayCallBacks)

	// do the export!
	status := C.SecItemExport(C.CFTypeRef(cfArrayForExport),
		C.kSecFormatPKCS12,
		0, //C.kSecItemPemArmour, // Use kSecItemPemArmour to add PEM armour - the .p12 generated by Keychain Access.app does NOT have PEM armour
		&exportParams,
		&exportedData)

	if status != C.errSecSuccess {
		return fmt.Errorf("SecItemExport: error (OSStatus): %d", status)
	}
	// exportedData now contains your PKCS12 data
	//  make sure it'll be released properly!
	defer C.CFRelease(C.CFTypeRef(exportedData))

	dataBytes := convertCFDataRefToGoBytes(exportedData)
	if dataBytes == nil || len(dataBytes) < 1 {
		return errors.New("ExportFromKeychain: failed to convert export data - nil or empty")
	}

	if err := fileutil.WriteBytesToFile(outputFilePath, dataBytes); err != nil {
		return fmt.Errorf("ExportFromKeychain: failed to write into file: %s", err)
	}

	log.Debug("Export - success")

	return nil
}
Example #11
0
// AddGenericPassword adds a generic password with the given
// attributes to the default keychain.
func AddGenericPassword(attributes *GenericPasswordAttributes) (err error) {
	if err = attributes.CheckValidity(); err != nil {
		return
	}

	var serviceNameString C.CFStringRef
	if serviceNameString, err = _UTF8StringToCFString(attributes.ServiceName); err != nil {
		return
	}
	defer C.CFRelease(C.CFTypeRef(serviceNameString))

	var accountNameString C.CFStringRef
	if accountNameString, err = _UTF8StringToCFString(attributes.AccountName); err != nil {
		return
	}
	defer C.CFRelease(C.CFTypeRef(accountNameString))

	dataBytes := bytesToCFData(attributes.Password)
	defer C.CFRelease(C.CFTypeRef(dataBytes))

	query := map[C.CFTypeRef]C.CFTypeRef{
		secClass:       secClassGenericPassword,
		secAttrService: C.CFTypeRef(serviceNameString),
		secAttrAccount: C.CFTypeRef(accountNameString),
		secValueData:   C.CFTypeRef(dataBytes),
	}

	access, err := createAccess(attributes.ServiceName, attributes.TrustedApplications)
	if err != nil {
		return
	}

	if access != nil {
		defer C.CFRelease(C.CFTypeRef(access))
		query[secAttrAccess] = C.CFTypeRef(access)
	}

	queryDict := mapToCFDictionary(query)
	defer C.CFRelease(C.CFTypeRef(queryDict))

	errCode := C.SecItemAdd(queryDict, nil)

	err = newKeychainError(errCode)
	return
}
Example #12
0
// The returned SecAccessRef, if non-nil, must be released via CFRelease.
func createEmptyAccess(label string) (C.SecAccessRef, error) {
	var err error
	var labelRef C.CFStringRef
	if labelRef, err = _UTF8StringToCFString(label); err != nil {
		return nil, err
	}
	defer C.CFRelease(C.CFTypeRef(labelRef))

	var access C.SecAccessRef
	trustedApplicationsArray := arrayToCFArray([]C.CFTypeRef{})
	defer C.CFRelease(C.CFTypeRef(trustedApplicationsArray))

	if err = newKeychainError(C.SecAccessCreate(labelRef, trustedApplicationsArray, &access)); err != nil {
		return nil, err
	}

	return access, nil
}
Example #13
0
func stringToCFString(str string, callback func(cfStr C.CFStringRef)) {
	cStr := C.CString(str)
	cfStr := C.CFStringCreateWithCString(nil, cStr, C.kCFStringEncodingMacRoman)

	defer C.free(unsafe.Pointer(cStr))
	defer C.CFRelease((C.CFTypeRef)(cfStr))

	callback(cfStr)
}
Example #14
0
func (k *keychain) Keys() ([]string, error) {
	serviceRef, err := _UTF8StringToCFString(k.Service)
	if err != nil {
		return nil, err
	}
	defer C.CFRelease(C.CFTypeRef(serviceRef))

	query := map[C.CFTypeRef]C.CFTypeRef{
		C.CFTypeRef(C.kSecClass):            C.CFTypeRef(C.kSecClassGenericPassword),
		C.CFTypeRef(C.kSecAttrService):      C.CFTypeRef(serviceRef),
		C.CFTypeRef(C.kSecMatchLimit):       C.CFTypeRef(C.kSecMatchLimitAll),
		C.CFTypeRef(C.kSecReturnAttributes): C.CFTypeRef(C.kCFBooleanTrue),
	}

	kref, err := openKeychain(k.Path)
	if err != nil {
		return nil, err
	}

	searchArray := arrayToCFArray([]C.CFTypeRef{C.CFTypeRef(kref)})
	defer C.CFRelease(C.CFTypeRef(searchArray))
	query[C.CFTypeRef(C.kSecMatchSearchList)] = C.CFTypeRef(searchArray)

	queryDict := mapToCFDictionary(query)
	defer C.CFRelease(C.CFTypeRef(queryDict))

	var resultsRef C.CFTypeRef
	if err = newKeychainError(C.SecItemCopyMatching(queryDict, &resultsRef)); err == errItemNotFound {
		return nil, nil
	} else if err != nil {
		return nil, err
	}

	defer C.CFRelease(resultsRef)
	var accountNames = []string{}

	for _, result := range _CFArrayToArray(C.CFArrayRef(resultsRef)) {
		m := _CFDictionaryToMap(C.CFDictionaryRef(result))
		accountName := _CFStringToUTF8String(C.CFStringRef(m[C.CFTypeRef(C.kSecAttrAccount)]))
		accountNames = append(accountNames, accountName)
	}

	return accountNames, nil
}
func CFNetServiceSetTXTData(cns *CFNetService, data []byte) bool {
	p := unsafe.Pointer(nil)
	if data != nil && len(data) > 0 {
		p = unsafe.Pointer(&data[0])
	}
	data_ := C.CFDataCreate(nil, (*C.UInt8)(p), C.CFIndex(len(data)))
	retval := C.CFNetServiceSetTXTData(cns.ref, data_)
	C.CFRelease((C.CFTypeRef)(data_))
	return retval != 0
}
Example #16
0
// DeleteItem removes a Item
func DeleteItem(item Item) error {
	cfDict, err := convertAttr(item.attr)
	if err != nil {
		return err
	}
	defer C.CFRelease(C.CFTypeRef(cfDict))

	errCode := C.SecItemDelete(cfDict)
	return checkError(errCode)
}
Example #17
0
func (self *Clipboard) addImage(img image.Image) (err error) {
	var i C.CGImageRef

	if i, err = CGImageCreateWithImage(img); err == nil {
		C.Clipboard_AddImage(self.ref, i)
		C.CFRelease(C.CFTypeRef(i))
	}

	return
}
Example #18
0
// Attributes provides metadata about the voice.
// The attributes for a voice are described in the documentation for [NSSpeechSynthesizer attributesForVoice].
// This functionality is undocumented in the Carbon Speech Synthesis Manager.
func (vs VoiceSpec) Attributes() (VoiceAttributes, error) {
	var va VoiceAttributes
	oserr := C.GetVoiceInfo((*C.VoiceSpec)(&vs), C.soVoiceAttributes, unsafe.Pointer(&va.cfd))
	if oserr != 0 {
		return va, osError(oserr)
	}
	runtime.SetFinalizer(&va, func(va *VoiceAttributes) {
		C.CFRelease(C.CFTypeRef(va.cfd))
	})
	return va, nil
}
Example #19
0
// AddItem adds a Item
func AddItem(item Item) error {
	cfDict, err := convertAttr(item.attr)
	if err != nil {
		return err
	}
	defer C.CFRelease(C.CFTypeRef(cfDict))

	errCode := C.SecItemAdd(cfDict, nil)
	err = checkError(errCode)
	return err
}
Example #20
0
// FindAndRemoveGenericPassword finds a generic password with the
// given attributes in the default keychain and removes it if
// found. If not found, an error is returned.
func FindAndRemoveGenericPassword(attributes *GenericPasswordAttributes) error {
	itemRef, err := findGenericPasswordItem(attributes)
	if err != nil {
		return err
	}

	defer C.CFRelease(C.CFTypeRef(itemRef))

	errCode := C.SecKeychainItemDelete(itemRef)
	return newKeychainError(errCode)
}
Example #21
0
func iterateDevices(action func(device C.IOHIDDeviceRef) bool) cleanupDeviceManagerFn {
	mgr := C.IOHIDManagerCreate(C.kCFAllocatorDefault, C.kIOHIDOptionsTypeNone)
	C.IOHIDManagerSetDeviceMatching(mgr, nil)
	C.IOHIDManagerOpen(mgr, C.kIOHIDOptionsTypeNone)

	allDevicesSet := C.IOHIDManagerCopyDevices(mgr)
	defer C.CFRelease(C.CFTypeRef(allDevicesSet))
	devCnt := C.CFSetGetCount(allDevicesSet)
	allDevices := make([]unsafe.Pointer, uint64(devCnt))
	C.CFSetGetValues(allDevicesSet, &allDevices[0])

	for _, pDev := range allDevices {
		if !action(C.IOHIDDeviceRef(pDev)) {
			break
		}
	}
	return func() {
		C.IOHIDManagerClose(mgr, C.kIOHIDOptionsTypeNone)
		C.CFRelease(C.CFTypeRef(mgr))
	}
}
Example #22
0
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/Reference/reference.html#jumpTo_8
func (s Stream) Paths() []string {
	cpaths := C.FSEventStreamCopyPathsBeingWatched(s.cstream)
	defer C.CFRelease(C.CFTypeRef(cpaths))
	count := C.CFArrayGetCount(cpaths)
	paths := make([]string, count)
	var i C.CFIndex
	for ; i < count; i++ {
		cpath := C.CFStringRef(C.CFArrayGetValueAtIndex(cpaths, i))
		paths[i] = fromCFString(cpath)
	}
	return paths
}
Example #23
0
func (ke keychainError) Error() string {
	errorMessageCFString := C.SecCopyErrorMessageString(C.OSStatus(ke), nil)
	defer C.CFRelease(C.CFTypeRef(errorMessageCFString))

	errorMessageCString := C.CFStringGetCStringPtr(errorMessageCFString, C.kCFStringEncodingASCII)

	if errorMessageCString != nil {
		return C.GoString(errorMessageCString)
	}

	return fmt.Sprintf("keychainError with unknown error code %d", C.OSStatus(ke))
}
Example #24
0
func buildFont(f C.CTFontRef) []byte {
	ctags := C.CTFontCopyAvailableTables(f, C.kCTFontTableOptionExcludeSynthetic)
	tagsCount := C.CFArrayGetCount(ctags)

	var tags []uint32
	var dataRefs []C.CFDataRef
	var dataLens []uint32

	for i := C.CFIndex(0); i < tagsCount; i++ {
		tag := (C.CTFontTableTag)((uintptr)(C.CFArrayGetValueAtIndex(ctags, i)))
		dataRef := C.CTFontCopyTable(f, tag, 0) // retained
		tags = append(tags, uint32(tag))
		dataRefs = append(dataRefs, dataRef)
		dataLens = append(dataLens, uint32(C.CFDataGetLength(dataRef)))
	}

	totalLen := 0
	for _, l := range dataLens {
		totalLen += int(l)
	}

	// Big-endian output.
	buf := make([]byte, 0, 12+16*len(tags)+totalLen)
	write16 := func(x uint16) { buf = append(buf, byte(x>>8), byte(x)) }
	write32 := func(x uint32) { buf = append(buf, byte(x>>24), byte(x>>16), byte(x>>8), byte(x)) }

	// File format description: http://www.microsoft.com/typography/otspec/otff.htm
	write32(0x00010000)        // version 1.0
	write16(uint16(len(tags))) // numTables
	write16(0)                 // searchRange
	write16(0)                 // entrySelector
	write16(0)                 // rangeShift

	// Table tags, includes offsets into following data segments.
	offset := uint32(12 + 16*len(tags)) // offset starts after table tags
	for i, tag := range tags {
		write32(tag)
		write32(0)
		write32(offset)
		write32(dataLens[i])
		offset += dataLens[i]
	}

	// Data segments.
	for i, dataRef := range dataRefs {
		data := (*[1<<31 - 2]byte)((unsafe.Pointer)(C.CFDataGetBytePtr(dataRef)))[:dataLens[i]]
		buf = append(buf, data...)
		C.CFRelease(C.CFTypeRef(dataRef))
	}

	return buf
}
Example #25
0
func (k *keychain) Remove(key string) error {
	if _, err := os.Stat(k.Path); os.IsNotExist(err) {
		return ErrKeyNotFound
	}

	serviceRef, err := _UTF8StringToCFString(k.Service)
	if err != nil {
		return err
	}
	defer C.CFRelease(C.CFTypeRef(serviceRef))

	accountRef, err := _UTF8StringToCFString(key)
	if err != nil {
		return err
	}
	defer C.CFRelease(C.CFTypeRef(serviceRef))

	query := map[C.CFTypeRef]C.CFTypeRef{
		C.CFTypeRef(C.kSecClass):       C.CFTypeRef(C.kSecClassGenericPassword),
		C.CFTypeRef(C.kSecAttrService): C.CFTypeRef(serviceRef),
		C.CFTypeRef(C.kSecAttrAccount): C.CFTypeRef(accountRef),
		C.CFTypeRef(C.kSecMatchLimit):  C.CFTypeRef(C.kSecMatchLimitOne),
	}

	kref, err := openKeychain(k.Path)
	if err != nil {
		return err
	}

	searchArray := arrayToCFArray([]C.CFTypeRef{C.CFTypeRef(kref)})
	defer C.CFRelease(C.CFTypeRef(searchArray))
	query[C.CFTypeRef(C.kSecMatchSearchList)] = C.CFTypeRef(searchArray)

	queryDict := mapToCFDictionary(query)
	defer C.CFRelease(C.CFTypeRef(queryDict))

	log.Printf("Removing keychain item service=%q, account=%q from osx keychain %q", k.Service, key, k.Path)
	return newKeychainError(C.SecItemDelete(queryDict))
}
Example #26
0
func initDefaultRoots() {
	roots := x509.NewCertPool()

	var data C.CFDataRef = nil
	err := C.FetchPEMRoots(&data)
	if err != -1 {
		defer C.CFRelease(C.CFTypeRef(data))
		buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
		roots.AppendCertsFromPEM(buf)
	}

	varDefaultRoots = roots
}
Example #27
0
// Start listening to an event stream.
func (es *EventStream) Start() {
	cPaths := C.ArrayCreateMutable(C.int(len(es.Paths)))
	defer C.CFRelease(C.CFTypeRef(cPaths))

	for _, p := range es.Paths {
		p, _ = filepath.Abs(p)
		cpath := C.CString(p)
		defer C.free(unsafe.Pointer(cpath))

		str := C.CFStringCreateWithCString(nil, cpath, C.kCFStringEncodingUTF8)
		C.CFArrayAppendValue(cPaths, unsafe.Pointer(str))
	}

	since := C.FSEventStreamEventId(EventIDSinceNow)
	if es.Resume {
		since = C.FSEventStreamEventId(es.EventID)
	}

	if es.Events == nil {
		es.Events = make(chan []Event)
	}

	es.registryID = registry.Add(es)
	context := C.FSEventStreamContext{}
	info := C.uintptr_t(es.registryID)
	latency := C.CFTimeInterval(float64(es.Latency) / float64(time.Second))
	if es.Device != 0 {
		es.stream = C.EventStreamCreateRelativeToDevice(&context, info, C.dev_t(es.Device), cPaths, since, latency, C.FSEventStreamCreateFlags(es.Flags))
	} else {
		es.stream = C.EventStreamCreate(&context, info, cPaths, since, latency, C.FSEventStreamCreateFlags(es.Flags))
	}

	started := make(chan struct{})

	go func() {
		runtime.LockOSThread()
		es.rlref = C.CFRunLoopGetCurrent()
		C.FSEventStreamScheduleWithRunLoop(es.stream, es.rlref, C.kCFRunLoopDefaultMode)
		C.FSEventStreamStart(es.stream)
		close(started)
		C.CFRunLoopRun()
	}()

	if !es.hasFinalizer {
		runtime.SetFinalizer(es, finalizer)
		es.hasFinalizer = true
	}

	<-started
}
Example #28
0
func (dev *osxDevice) Close() {
	if !dev.disconnected {
		C.IOHIDDeviceClose(dev.osDevice, C.kIOHIDOptionsTypeSeizeDevice)
		dev.disconnected = true
	}
	if dev.osDevice != nil {
		C.CFRelease(C.CFTypeRef(dev.osDevice))
		dev.osDevice = nil
	}
	if dev.closeDM != nil {
		dev.closeDM()
		dev.closeDM = nil
	}
}
Example #29
0
func initSystemRoots() {
	roots := NewCertPool()

	var data C.CFDataRef = nil
	err := C.ZToolsFetchPEMRoots(&data)
	if err == -1 {
		return
	}

	defer C.CFRelease(C.CFTypeRef(data))
	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
	roots.AppendCertsFromPEM(buf)
	systemRoots = roots
}
Example #30
0
// The returned SecAccessRef, if non-nil, must be released via CFRelease.
func createAccess(label string, trustedApplications []string) (C.CFTypeRef, error) {
	if len(trustedApplications) == 0 {
		return nil, nil
	}

	// Always prepend with empty string which signifies that we
	// include a NULL application, which means ourselves.
	trustedApplications = append([]string{""}, trustedApplications...)

	var err error
	var labelRef C.CFStringRef
	if labelRef, err = StringToCFString(label); err != nil {
		return nil, err
	}
	defer C.CFRelease(C.CFTypeRef(labelRef))

	var trustedApplicationsRefs []C.CFTypeRef
	for _, trustedApplication := range trustedApplications {
		trustedApplicationRef, err := createTrustedApplication(trustedApplication)
		if err != nil {
			return nil, err
		}
		defer C.CFRelease(C.CFTypeRef(trustedApplicationRef))
		trustedApplicationsRefs = append(trustedApplicationsRefs, trustedApplicationRef)
	}

	var access C.SecAccessRef
	trustedApplicationsArray := ArrayToCFArray(trustedApplicationsRefs)
	defer C.CFRelease(C.CFTypeRef(trustedApplicationsArray))
	errCode := C.SecAccessCreate(labelRef, trustedApplicationsArray, &access)
	err = checkError(errCode)
	if err != nil {
		return nil, err
	}

	return C.CFTypeRef(access), nil
}