podman

Форк
0
950 строк · 22.7 Кб
1
// Package gpgme provides a Go wrapper for the GPGME library
2
package gpgme
3

4
// #cgo pkg-config: gpgme
5
// #cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64
6
// #include <stdlib.h>
7
// #include <gpgme.h>
8
// #include "go_gpgme.h"
9
import "C"
10
import (
11
	"fmt"
12
	"io"
13
	"os"
14
	"runtime"
15
	"time"
16
	"unsafe"
17
)
18

19
var Version string
20

21
func init() {
22
	Version = C.GoString(C.gpgme_check_version(nil))
23
}
24

25
// Callback is the function that is called when a passphrase is required
26
type Callback func(uidHint string, prevWasBad bool, f *os.File) error
27

28
//export gogpgme_passfunc
29
func gogpgme_passfunc(hook unsafe.Pointer, uid_hint, passphrase_info *C.char, prev_was_bad, fd C.int) C.gpgme_error_t {
30
	c := callbackLookup(uintptr(hook)).(*Context)
31
	go_uid_hint := C.GoString(uid_hint)
32
	f := os.NewFile(uintptr(fd), go_uid_hint)
33
	defer f.Close()
34
	err := c.callback(go_uid_hint, prev_was_bad != 0, f)
35
	if err != nil {
36
		return C.GPG_ERR_CANCELED
37
	}
38
	return 0
39
}
40

41
type Protocol int
42

43
const (
44
	ProtocolOpenPGP  Protocol = C.GPGME_PROTOCOL_OpenPGP
45
	ProtocolCMS      Protocol = C.GPGME_PROTOCOL_CMS
46
	ProtocolGPGConf  Protocol = C.GPGME_PROTOCOL_GPGCONF
47
	ProtocolAssuan   Protocol = C.GPGME_PROTOCOL_ASSUAN
48
	ProtocolG13      Protocol = C.GPGME_PROTOCOL_G13
49
	ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
50
	ProtocolDefault  Protocol = C.GPGME_PROTOCOL_DEFAULT
51
	ProtocolUnknown  Protocol = C.GPGME_PROTOCOL_UNKNOWN
52
)
53

54
type PinEntryMode int
55

56
const (
57
	PinEntryDefault  PinEntryMode = C.GPGME_PINENTRY_MODE_DEFAULT
58
	PinEntryAsk      PinEntryMode = C.GPGME_PINENTRY_MODE_ASK
59
	PinEntryCancel   PinEntryMode = C.GPGME_PINENTRY_MODE_CANCEL
60
	PinEntryError    PinEntryMode = C.GPGME_PINENTRY_MODE_ERROR
61
	PinEntryLoopback PinEntryMode = C.GPGME_PINENTRY_MODE_LOOPBACK
62
)
63

64
type EncryptFlag uint
65

66
const (
67
	EncryptAlwaysTrust EncryptFlag = C.GPGME_ENCRYPT_ALWAYS_TRUST
68
	EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
69
	EncryptPrepare     EncryptFlag = C.GPGME_ENCRYPT_PREPARE
70
	EncryptExceptSign  EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
71
)
72

73
type HashAlgo int
74

75
// const values for HashAlgo values should be added when necessary.
76

77
type KeyListMode uint
78

79
const (
80
	KeyListModeLocal        KeyListMode = C.GPGME_KEYLIST_MODE_LOCAL
81
	KeyListModeExtern       KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
82
	KeyListModeSigs         KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
83
	KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
84
	KeyListModeEphemeral    KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
85
	KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
86
)
87

88
type PubkeyAlgo int
89

90
// const values for PubkeyAlgo values should be added when necessary.
91

92
type SigMode int
93

94
const (
95
	SigModeNormal SigMode = C.GPGME_SIG_MODE_NORMAL
96
	SigModeDetach SigMode = C.GPGME_SIG_MODE_DETACH
97
	SigModeClear  SigMode = C.GPGME_SIG_MODE_CLEAR
98
)
99

100
type SigSum int
101

102
const (
103
	SigSumValid      SigSum = C.GPGME_SIGSUM_VALID
104
	SigSumGreen      SigSum = C.GPGME_SIGSUM_GREEN
105
	SigSumRed        SigSum = C.GPGME_SIGSUM_RED
106
	SigSumKeyRevoked SigSum = C.GPGME_SIGSUM_KEY_REVOKED
107
	SigSumKeyExpired SigSum = C.GPGME_SIGSUM_KEY_EXPIRED
108
	SigSumSigExpired SigSum = C.GPGME_SIGSUM_SIG_EXPIRED
109
	SigSumKeyMissing SigSum = C.GPGME_SIGSUM_KEY_MISSING
110
	SigSumCRLMissing SigSum = C.GPGME_SIGSUM_CRL_MISSING
111
	SigSumCRLTooOld  SigSum = C.GPGME_SIGSUM_CRL_TOO_OLD
112
	SigSumBadPolicy  SigSum = C.GPGME_SIGSUM_BAD_POLICY
113
	SigSumSysError   SigSum = C.GPGME_SIGSUM_SYS_ERROR
114
)
115

116
type Validity int
117

118
const (
119
	ValidityUnknown   Validity = C.GPGME_VALIDITY_UNKNOWN
120
	ValidityUndefined Validity = C.GPGME_VALIDITY_UNDEFINED
121
	ValidityNever     Validity = C.GPGME_VALIDITY_NEVER
122
	ValidityMarginal  Validity = C.GPGME_VALIDITY_MARGINAL
123
	ValidityFull      Validity = C.GPGME_VALIDITY_FULL
124
	ValidityUltimate  Validity = C.GPGME_VALIDITY_ULTIMATE
125
)
126

127
type ErrorCode int
128

129
const (
130
	ErrorNoError ErrorCode = C.GPG_ERR_NO_ERROR
131
	ErrorEOF     ErrorCode = C.GPG_ERR_EOF
132
)
133

134
// Error is a wrapper for GPGME errors
135
type Error struct {
136
	err C.gpgme_error_t
137
}
138

139
func (e Error) Code() ErrorCode {
140
	return ErrorCode(C.gpgme_err_code(e.err))
141
}
142

143
func (e Error) Error() string {
144
	return C.GoString(C.gpgme_strerror(e.err))
145
}
146

147
func handleError(err C.gpgme_error_t) error {
148
	e := Error{err: err}
149
	if e.Code() == ErrorNoError {
150
		return nil
151
	}
152
	return e
153
}
154

155
func cbool(b bool) C.int {
156
	if b {
157
		return 1
158
	}
159
	return 0
160
}
161

162
func EngineCheckVersion(p Protocol) error {
163
	return handleError(C.gpgme_engine_check_version(C.gpgme_protocol_t(p)))
164
}
165

166
type EngineInfo struct {
167
	next            *EngineInfo
168
	protocol        Protocol
169
	fileName        string
170
	homeDir         string
171
	version         string
172
	requiredVersion string
173
}
174

175
func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
176
	res := &EngineInfo{
177
		next:            nil,
178
		protocol:        Protocol(info.protocol),
179
		fileName:        C.GoString(info.file_name),
180
		homeDir:         C.GoString(info.home_dir),
181
		version:         C.GoString(info.version),
182
		requiredVersion: C.GoString(info.req_version),
183
	}
184
	if info.next != nil {
185
		res.next = copyEngineInfo(info.next)
186
	}
187
	return res
188
}
189

190
func (e *EngineInfo) Next() *EngineInfo {
191
	return e.next
192
}
193

194
func (e *EngineInfo) Protocol() Protocol {
195
	return e.protocol
196
}
197

198
func (e *EngineInfo) FileName() string {
199
	return e.fileName
200
}
201

202
func (e *EngineInfo) Version() string {
203
	return e.version
204
}
205

206
func (e *EngineInfo) RequiredVersion() string {
207
	return e.requiredVersion
208
}
209

210
func (e *EngineInfo) HomeDir() string {
211
	return e.homeDir
212
}
213

214
func GetEngineInfo() (*EngineInfo, error) {
215
	var cInfo C.gpgme_engine_info_t
216
	err := handleError(C.gpgme_get_engine_info(&cInfo))
217
	if err != nil {
218
		return nil, err
219
	}
220
	return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
221
}
222

223
func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
224
	var cfn, chome *C.char
225
	if fileName != "" {
226
		cfn = C.CString(fileName)
227
		defer C.free(unsafe.Pointer(cfn))
228
	}
229
	if homeDir != "" {
230
		chome = C.CString(homeDir)
231
		defer C.free(unsafe.Pointer(chome))
232
	}
233
	return handleError(C.gpgme_set_engine_info(C.gpgme_protocol_t(proto), cfn, chome))
234
}
235

236
func FindKeys(pattern string, secretOnly bool) ([]*Key, error) {
237
	var keys []*Key
238
	ctx, err := New()
239
	if err != nil {
240
		return keys, err
241
	}
242
	defer ctx.Release()
243
	if err := ctx.KeyListStart(pattern, secretOnly); err != nil {
244
		return keys, err
245
	}
246
	defer ctx.KeyListEnd()
247
	for ctx.KeyListNext() {
248
		keys = append(keys, ctx.Key)
249
	}
250
	if ctx.KeyError != nil {
251
		return keys, ctx.KeyError
252
	}
253
	return keys, nil
254
}
255

256
func Decrypt(r io.Reader) (*Data, error) {
257
	ctx, err := New()
258
	if err != nil {
259
		return nil, err
260
	}
261
	defer ctx.Release()
262
	cipher, err := NewDataReader(r)
263
	if err != nil {
264
		return nil, err
265
	}
266
	defer cipher.Close()
267
	plain, err := NewData()
268
	if err != nil {
269
		return nil, err
270
	}
271
	err = ctx.Decrypt(cipher, plain)
272
	plain.Seek(0, SeekSet)
273
	return plain, err
274
}
275

276
type Context struct {
277
	Key      *Key
278
	KeyError error
279

280
	callback Callback
281
	cbc      uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
282

283
	ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
284
}
285

286
func New() (*Context, error) {
287
	c := &Context{}
288
	err := C.gpgme_new(&c.ctx)
289
	runtime.SetFinalizer(c, (*Context).Release)
290
	return c, handleError(err)
291
}
292

293
func (c *Context) Release() {
294
	if c.ctx == nil {
295
		return
296
	}
297
	if c.cbc > 0 {
298
		callbackDelete(c.cbc)
299
	}
300
	C.gpgme_release(c.ctx)
301
	runtime.KeepAlive(c)
302
	c.ctx = nil
303
}
304

305
func (c *Context) SetArmor(yes bool) {
306
	C.gpgme_set_armor(c.ctx, cbool(yes))
307
	runtime.KeepAlive(c)
308
}
309

310
func (c *Context) Armor() bool {
311
	res := C.gpgme_get_armor(c.ctx) != 0
312
	runtime.KeepAlive(c)
313
	return res
314
}
315

316
func (c *Context) SetTextMode(yes bool) {
317
	C.gpgme_set_textmode(c.ctx, cbool(yes))
318
	runtime.KeepAlive(c)
319
}
320

321
func (c *Context) TextMode() bool {
322
	res := C.gpgme_get_textmode(c.ctx) != 0
323
	runtime.KeepAlive(c)
324
	return res
325
}
326

327
func (c *Context) SetProtocol(p Protocol) error {
328
	err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
329
	runtime.KeepAlive(c)
330
	return err
331
}
332

333
func (c *Context) Protocol() Protocol {
334
	res := Protocol(C.gpgme_get_protocol(c.ctx))
335
	runtime.KeepAlive(c)
336
	return res
337
}
338

339
func (c *Context) SetKeyListMode(m KeyListMode) error {
340
	err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
341
	runtime.KeepAlive(c)
342
	return err
343
}
344

345
func (c *Context) KeyListMode() KeyListMode {
346
	res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
347
	runtime.KeepAlive(c)
348
	return res
349
}
350

351
func (c *Context) SetPinEntryMode(m PinEntryMode) error {
352
	err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
353
	runtime.KeepAlive(c)
354
	return err
355
}
356

357
func (c *Context) PinEntryMode() PinEntryMode {
358
	res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
359
	runtime.KeepAlive(c)
360
	return res
361
}
362

363
func (c *Context) SetCallback(callback Callback) error {
364
	var err error
365
	c.callback = callback
366
	if c.cbc > 0 {
367
		callbackDelete(c.cbc)
368
	}
369
	if callback != nil {
370
		cbc := callbackAdd(c)
371
		c.cbc = cbc
372
		_, err = C.gogpgme_set_passphrase_cb(c.ctx, C.gpgme_passphrase_cb_t(C.gogpgme_passfunc), C.uintptr_t(cbc))
373
	} else {
374
		c.cbc = 0
375
		_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
376
	}
377
	runtime.KeepAlive(c)
378
	return err
379
}
380

381
func (c *Context) EngineInfo() *EngineInfo {
382
	cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
383
	runtime.KeepAlive(c)
384
	// NOTE: c must be live as long as we are accessing cInfo.
385
	res := copyEngineInfo(cInfo)
386
	runtime.KeepAlive(c) // for accesses to cInfo
387
	return res
388
}
389

390
func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
391
	var cfn, chome *C.char
392
	if fileName != "" {
393
		cfn = C.CString(fileName)
394
		defer C.free(unsafe.Pointer(cfn))
395
	}
396
	if homeDir != "" {
397
		chome = C.CString(homeDir)
398
		defer C.free(unsafe.Pointer(chome))
399
	}
400
	err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
401
	runtime.KeepAlive(c)
402
	return err
403
}
404

405
func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
406
	cpattern := C.CString(pattern)
407
	defer C.free(unsafe.Pointer(cpattern))
408
	err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
409
	runtime.KeepAlive(c)
410
	return err
411
}
412

413
func (c *Context) KeyListNext() bool {
414
	c.Key = newKey()
415
	err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
416
	runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
417
	if err != nil {
418
		if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
419
			c.KeyError = nil
420
		} else {
421
			c.KeyError = err
422
		}
423
		return false
424
	}
425
	c.KeyError = nil
426
	return true
427
}
428

429
func (c *Context) KeyListEnd() error {
430
	err := handleError(C.gpgme_op_keylist_end(c.ctx))
431
	runtime.KeepAlive(c)
432
	return err
433
}
434

435
func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
436
	key := newKey()
437
	cfpr := C.CString(fingerprint)
438
	defer C.free(unsafe.Pointer(cfpr))
439
	err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
440
	runtime.KeepAlive(c)
441
	runtime.KeepAlive(key)
442
	keyKIsNil := key.k == nil
443
	runtime.KeepAlive(key)
444
	if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
445
		return nil, fmt.Errorf("key %q not found", fingerprint)
446
	}
447
	if err != nil {
448
		return nil, err
449
	}
450
	return key, nil
451
}
452

453
func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
454
	err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
455
	runtime.KeepAlive(c)
456
	runtime.KeepAlive(ciphertext)
457
	runtime.KeepAlive(plaintext)
458
	return err
459
}
460

461
func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
462
	err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
463
	runtime.KeepAlive(c)
464
	runtime.KeepAlive(ciphertext)
465
	runtime.KeepAlive(plaintext)
466
	return err
467
}
468

469
type Signature struct {
470
	Summary        SigSum
471
	Fingerprint    string
472
	Status         error
473
	Timestamp      time.Time
474
	ExpTimestamp   time.Time
475
	WrongKeyUsage  bool
476
	PKATrust       uint
477
	ChainModel     bool
478
	Validity       Validity
479
	ValidityReason error
480
	PubkeyAlgo     PubkeyAlgo
481
	HashAlgo       HashAlgo
482
}
483

484
func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, error) {
485
	var signedTextPtr, plainPtr C.gpgme_data_t = nil, nil
486
	if signedText != nil {
487
		signedTextPtr = signedText.dh
488
	}
489
	if plain != nil {
490
		plainPtr = plain.dh
491
	}
492
	err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
493
	runtime.KeepAlive(c)
494
	runtime.KeepAlive(sig)
495
	if signedText != nil {
496
		runtime.KeepAlive(signedText)
497
	}
498
	if plain != nil {
499
		runtime.KeepAlive(plain)
500
	}
501
	if err != nil {
502
		return "", nil, err
503
	}
504
	res := C.gpgme_op_verify_result(c.ctx)
505
	runtime.KeepAlive(c)
506
	// NOTE: c must be live as long as we are accessing res.
507
	sigs := []Signature{}
508
	for s := res.signatures; s != nil; s = s.next {
509
		sig := Signature{
510
			Summary:     SigSum(s.summary),
511
			Fingerprint: C.GoString(s.fpr),
512
			Status:      handleError(s.status),
513
			// s.notations not implemented
514
			Timestamp:      time.Unix(int64(s.timestamp), 0),
515
			ExpTimestamp:   time.Unix(int64(s.exp_timestamp), 0),
516
			WrongKeyUsage:  C.signature_wrong_key_usage(s) != 0,
517
			PKATrust:       uint(C.signature_pka_trust(s)),
518
			ChainModel:     C.signature_chain_model(s) != 0,
519
			Validity:       Validity(s.validity),
520
			ValidityReason: handleError(s.validity_reason),
521
			PubkeyAlgo:     PubkeyAlgo(s.pubkey_algo),
522
			HashAlgo:       HashAlgo(s.hash_algo),
523
		}
524
		sigs = append(sigs, sig)
525
	}
526
	fileName := C.GoString(res.file_name)
527
	runtime.KeepAlive(c) // for all accesses to res above
528
	return fileName, sigs, nil
529
}
530

531
func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
532
	size := unsafe.Sizeof(new(C.gpgme_key_t))
533
	recp := C.calloc(C.size_t(len(recipients)+1), C.size_t(size))
534
	defer C.free(recp)
535
	for i := range recipients {
536
		ptr := (*C.gpgme_key_t)(unsafe.Pointer(uintptr(recp) + size*uintptr(i)))
537
		*ptr = recipients[i].k
538
	}
539
	err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
540
	runtime.KeepAlive(c)
541
	runtime.KeepAlive(recipients)
542
	runtime.KeepAlive(plaintext)
543
	runtime.KeepAlive(ciphertext)
544
	return handleError(err)
545
}
546

547
func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
548
	C.gpgme_signers_clear(c.ctx)
549
	runtime.KeepAlive(c)
550
	for _, k := range signers {
551
		err := handleError(C.gpgme_signers_add(c.ctx, k.k))
552
		runtime.KeepAlive(c)
553
		runtime.KeepAlive(k)
554
		if err != nil {
555
			C.gpgme_signers_clear(c.ctx)
556
			runtime.KeepAlive(c)
557
			return err
558
		}
559
	}
560
	err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
561
	runtime.KeepAlive(c)
562
	runtime.KeepAlive(plain)
563
	runtime.KeepAlive(sig)
564
	return err
565
}
566

567
type AssuanDataCallback func(data []byte) error
568
type AssuanInquireCallback func(name, args string) error
569
type AssuanStatusCallback func(status, args string) error
570

571
// AssuanSend sends a raw Assuan command to gpg-agent
572
func (c *Context) AssuanSend(
573
	cmd string,
574
	data AssuanDataCallback,
575
	inquiry AssuanInquireCallback,
576
	status AssuanStatusCallback,
577
) error {
578
	var operr C.gpgme_error_t
579

580
	dataPtr := callbackAdd(&data)
581
	inquiryPtr := callbackAdd(&inquiry)
582
	statusPtr := callbackAdd(&status)
583
	cmdCStr := C.CString(cmd)
584
	defer C.free(unsafe.Pointer(cmdCStr))
585
	err := C.gogpgme_op_assuan_transact_ext(
586
		c.ctx,
587
		cmdCStr,
588
		C.uintptr_t(dataPtr),
589
		C.uintptr_t(inquiryPtr),
590
		C.uintptr_t(statusPtr),
591
		&operr,
592
	)
593
	runtime.KeepAlive(c)
594

595
	if handleError(operr) != nil {
596
		return handleError(operr)
597
	}
598
	return handleError(err)
599
}
600

601
//export gogpgme_assuan_data_callback
602
func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
603
	c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
604
	if *c == nil {
605
		return 0
606
	}
607
	(*c)(C.GoBytes(data, C.int(datalen)))
608
	return 0
609
}
610

611
//export gogpgme_assuan_inquiry_callback
612
func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
613
	name := C.GoString(cName)
614
	args := C.GoString(cArgs)
615
	c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
616
	if *c == nil {
617
		return 0
618
	}
619
	(*c)(name, args)
620
	return 0
621
}
622

623
//export gogpgme_assuan_status_callback
624
func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
625
	status := C.GoString(cStatus)
626
	args := C.GoString(cArgs)
627
	c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
628
	if *c == nil {
629
		return 0
630
	}
631
	(*c)(status, args)
632
	return 0
633
}
634

635
// ExportModeFlags defines how keys are exported from Export
636
type ExportModeFlags uint
637

638
const (
639
	ExportModeExtern  ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
640
	ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
641
)
642

643
func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
644
	pat := C.CString(pattern)
645
	defer C.free(unsafe.Pointer(pat))
646
	err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
647
	runtime.KeepAlive(c)
648
	runtime.KeepAlive(data)
649
	return err
650
}
651

652
// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
653
type ImportStatusFlags uint
654

655
const (
656
	ImportNew    ImportStatusFlags = C.GPGME_IMPORT_NEW
657
	ImportUID    ImportStatusFlags = C.GPGME_IMPORT_UID
658
	ImportSIG    ImportStatusFlags = C.GPGME_IMPORT_SIG
659
	ImportSubKey ImportStatusFlags = C.GPGME_IMPORT_SUBKEY
660
	ImportSecret ImportStatusFlags = C.GPGME_IMPORT_SECRET
661
)
662

663
type ImportStatus struct {
664
	Fingerprint string
665
	Result      error
666
	Status      ImportStatusFlags
667
}
668

669
type ImportResult struct {
670
	Considered      int
671
	NoUserID        int
672
	Imported        int
673
	ImportedRSA     int
674
	Unchanged       int
675
	NewUserIDs      int
676
	NewSubKeys      int
677
	NewSignatures   int
678
	NewRevocations  int
679
	SecretRead      int
680
	SecretImported  int
681
	SecretUnchanged int
682
	NotImported     int
683
	Imports         []ImportStatus
684
}
685

686
func (c *Context) Import(keyData *Data) (*ImportResult, error) {
687
	err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
688
	runtime.KeepAlive(c)
689
	runtime.KeepAlive(keyData)
690
	if err != nil {
691
		return nil, err
692
	}
693
	res := C.gpgme_op_import_result(c.ctx)
694
	runtime.KeepAlive(c)
695
	// NOTE: c must be live as long as we are accessing res.
696
	imports := []ImportStatus{}
697
	for s := res.imports; s != nil; s = s.next {
698
		imports = append(imports, ImportStatus{
699
			Fingerprint: C.GoString(s.fpr),
700
			Result:      handleError(s.result),
701
			Status:      ImportStatusFlags(s.status),
702
		})
703
	}
704
	importResult := &ImportResult{
705
		Considered:      int(res.considered),
706
		NoUserID:        int(res.no_user_id),
707
		Imported:        int(res.imported),
708
		ImportedRSA:     int(res.imported_rsa),
709
		Unchanged:       int(res.unchanged),
710
		NewUserIDs:      int(res.new_user_ids),
711
		NewSubKeys:      int(res.new_sub_keys),
712
		NewSignatures:   int(res.new_signatures),
713
		NewRevocations:  int(res.new_revocations),
714
		SecretRead:      int(res.secret_read),
715
		SecretImported:  int(res.secret_imported),
716
		SecretUnchanged: int(res.secret_unchanged),
717
		NotImported:     int(res.not_imported),
718
		Imports:         imports,
719
	}
720
	runtime.KeepAlive(c) // for all accesses to res above
721
	return importResult, nil
722
}
723

724
type Key struct {
725
	k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
726
}
727

728
func newKey() *Key {
729
	k := &Key{}
730
	runtime.SetFinalizer(k, (*Key).Release)
731
	return k
732
}
733

734
func (k *Key) Release() {
735
	C.gpgme_key_release(k.k)
736
	runtime.KeepAlive(k)
737
	k.k = nil
738
}
739

740
func (k *Key) Revoked() bool {
741
	res := C.key_revoked(k.k) != 0
742
	runtime.KeepAlive(k)
743
	return res
744
}
745

746
func (k *Key) Expired() bool {
747
	res := C.key_expired(k.k) != 0
748
	runtime.KeepAlive(k)
749
	return res
750
}
751

752
func (k *Key) Disabled() bool {
753
	res := C.key_disabled(k.k) != 0
754
	runtime.KeepAlive(k)
755
	return res
756
}
757

758
func (k *Key) Invalid() bool {
759
	res := C.key_invalid(k.k) != 0
760
	runtime.KeepAlive(k)
761
	return res
762
}
763

764
func (k *Key) CanEncrypt() bool {
765
	res := C.key_can_encrypt(k.k) != 0
766
	runtime.KeepAlive(k)
767
	return res
768
}
769

770
func (k *Key) CanSign() bool {
771
	res := C.key_can_sign(k.k) != 0
772
	runtime.KeepAlive(k)
773
	return res
774
}
775

776
func (k *Key) CanCertify() bool {
777
	res := C.key_can_certify(k.k) != 0
778
	runtime.KeepAlive(k)
779
	return res
780
}
781

782
func (k *Key) Secret() bool {
783
	res := C.key_secret(k.k) != 0
784
	runtime.KeepAlive(k)
785
	return res
786
}
787

788
func (k *Key) CanAuthenticate() bool {
789
	res := C.key_can_authenticate(k.k) != 0
790
	runtime.KeepAlive(k)
791
	return res
792
}
793

794
func (k *Key) IsQualified() bool {
795
	res := C.key_is_qualified(k.k) != 0
796
	runtime.KeepAlive(k)
797
	return res
798
}
799

800
func (k *Key) Protocol() Protocol {
801
	res := Protocol(k.k.protocol)
802
	runtime.KeepAlive(k)
803
	return res
804
}
805

806
func (k *Key) IssuerSerial() string {
807
	res := C.GoString(k.k.issuer_serial)
808
	runtime.KeepAlive(k)
809
	return res
810
}
811

812
func (k *Key) IssuerName() string {
813
	res := C.GoString(k.k.issuer_name)
814
	runtime.KeepAlive(k)
815
	return res
816
}
817

818
func (k *Key) ChainID() string {
819
	res := C.GoString(k.k.chain_id)
820
	runtime.KeepAlive(k)
821
	return res
822
}
823

824
func (k *Key) OwnerTrust() Validity {
825
	res := Validity(k.k.owner_trust)
826
	runtime.KeepAlive(k)
827
	return res
828
}
829

830
func (k *Key) SubKeys() *SubKey {
831
	subKeys := k.k.subkeys
832
	runtime.KeepAlive(k)
833
	if subKeys == nil {
834
		return nil
835
	}
836
	return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
837
}
838

839
func (k *Key) UserIDs() *UserID {
840
	uids := k.k.uids
841
	runtime.KeepAlive(k)
842
	if uids == nil {
843
		return nil
844
	}
845
	return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
846
}
847

848
func (k *Key) KeyListMode() KeyListMode {
849
	res := KeyListMode(k.k.keylist_mode)
850
	runtime.KeepAlive(k)
851
	return res
852
}
853

854
type SubKey struct {
855
	k      C.gpgme_subkey_t
856
	parent *Key // make sure the key is not released when we have a reference to a subkey
857
}
858

859
func (k *SubKey) Next() *SubKey {
860
	if k.k.next == nil {
861
		return nil
862
	}
863
	return &SubKey{k: k.k.next, parent: k.parent}
864
}
865

866
func (k *SubKey) Revoked() bool {
867
	return C.subkey_revoked(k.k) != 0
868
}
869

870
func (k *SubKey) Expired() bool {
871
	return C.subkey_expired(k.k) != 0
872
}
873

874
func (k *SubKey) Disabled() bool {
875
	return C.subkey_disabled(k.k) != 0
876
}
877

878
func (k *SubKey) Invalid() bool {
879
	return C.subkey_invalid(k.k) != 0
880
}
881

882
func (k *SubKey) Secret() bool {
883
	return C.subkey_secret(k.k) != 0
884
}
885

886
func (k *SubKey) KeyID() string {
887
	return C.GoString(k.k.keyid)
888
}
889

890
func (k *SubKey) Fingerprint() string {
891
	return C.GoString(k.k.fpr)
892
}
893

894
func (k *SubKey) Created() time.Time {
895
	if k.k.timestamp <= 0 {
896
		return time.Time{}
897
	}
898
	return time.Unix(int64(k.k.timestamp), 0)
899
}
900

901
func (k *SubKey) Expires() time.Time {
902
	if k.k.expires <= 0 {
903
		return time.Time{}
904
	}
905
	return time.Unix(int64(k.k.expires), 0)
906
}
907

908
func (k *SubKey) CardNumber() string {
909
	return C.GoString(k.k.card_number)
910
}
911

912
type UserID struct {
913
	u      C.gpgme_user_id_t
914
	parent *Key // make sure the key is not released when we have a reference to a user ID
915
}
916

917
func (u *UserID) Next() *UserID {
918
	if u.u.next == nil {
919
		return nil
920
	}
921
	return &UserID{u: u.u.next, parent: u.parent}
922
}
923

924
func (u *UserID) Revoked() bool {
925
	return C.uid_revoked(u.u) != 0
926
}
927

928
func (u *UserID) Invalid() bool {
929
	return C.uid_invalid(u.u) != 0
930
}
931

932
func (u *UserID) Validity() Validity {
933
	return Validity(u.u.validity)
934
}
935

936
func (u *UserID) UID() string {
937
	return C.GoString(u.u.uid)
938
}
939

940
func (u *UserID) Name() string {
941
	return C.GoString(u.u.name)
942
}
943

944
func (u *UserID) Comment() string {
945
	return C.GoString(u.u.comment)
946
}
947

948
func (u *UserID) Email() string {
949
	return C.GoString(u.u.email)
950
}
951

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.