mirror of
https://github.com/containers/skopeo.git
synced 2026-01-30 13:58:48 +00:00
Compare commits
7 Commits
v1.3.1
...
release-0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c79a5b404b | ||
|
|
f992ab28e7 | ||
|
|
14f5abb6a6 | ||
|
|
0484557df8 | ||
|
|
c16c7e37f2 | ||
|
|
7902be2dc4 | ||
|
|
5c3a5ddf2d |
@@ -1,6 +1,6 @@
|
||||
FROM fedora
|
||||
|
||||
RUN dnf -y update && dnf install -y make git golang golang-github-cpuguy83-go-md2man \
|
||||
RUN dnf -y update && dnf install -y make git golang golang-github-cpuguy83-md2man \
|
||||
# storage deps
|
||||
btrfs-progs-devel \
|
||||
device-mapper-devel \
|
||||
|
||||
@@ -106,6 +106,23 @@ function run_skopeo() {
|
||||
fi
|
||||
}
|
||||
|
||||
#################
|
||||
# log_and_run # log a command for later debugging, then run it
|
||||
#################
|
||||
#
|
||||
# When diagnosing a test failure, it can be really nice to see the
|
||||
# more important commands that have been run in test setup: openssl,
|
||||
# podman registry, other complex commands that can give one a boost
|
||||
# when trying to reproduce problems. This simple wrapper takes a
|
||||
# command as its arg, echoes it to stdout (with a '$' prefix),
|
||||
# then runs the command. BATS does not show stdout unless there's
|
||||
# an error. Use this judiciously.
|
||||
#
|
||||
function log_and_run() {
|
||||
echo "\$ $*"
|
||||
"$@"
|
||||
}
|
||||
|
||||
#########
|
||||
# die # Abort with helpful message
|
||||
#########
|
||||
@@ -276,7 +293,7 @@ start_registry() {
|
||||
fi
|
||||
|
||||
if ! egrep -q "^$testuser:" $AUTHDIR/htpasswd; then
|
||||
$PODMAN run --rm --entrypoint htpasswd registry:2 \
|
||||
log_and_run $PODMAN run --rm --entrypoint htpasswd registry:2 \
|
||||
-Bbn $testuser $testpassword >> $AUTHDIR/htpasswd
|
||||
fi
|
||||
|
||||
@@ -291,7 +308,7 @@ start_registry() {
|
||||
if [[ -n $create_cert ]]; then
|
||||
CERT=$AUTHDIR/domain.crt
|
||||
if [ ! -e $CERT ]; then
|
||||
openssl req -newkey rsa:4096 -nodes -sha256 \
|
||||
log_and_run openssl req -newkey rsa:4096 -nodes -sha256 \
|
||||
-keyout $AUTHDIR/domain.key -x509 -days 2 \
|
||||
-out $CERT \
|
||||
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
|
||||
@@ -306,15 +323,15 @@ start_registry() {
|
||||
# test the client. (If client sees a matching .key file, it fails)
|
||||
# Thanks to Miloslav Trmac for this hint.
|
||||
mkdir -p $TESTDIR/client-auth
|
||||
cp $CERT $TESTDIR/client-auth/
|
||||
log_and_run cp $CERT $TESTDIR/client-auth/
|
||||
fi
|
||||
|
||||
$PODMAN run -d --name $name "${reg_args[@]}" registry:2
|
||||
log_and_run $PODMAN run -d --name $name "${reg_args[@]}" registry:2
|
||||
|
||||
# Wait for registry to actually come up
|
||||
timeout=10
|
||||
while [[ $timeout -ge 1 ]]; do
|
||||
if curl localhost:$port/; then
|
||||
if echo -n >/dev/tcp/127.0.0.1/$port; then
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
github.com/urfave/cli v1.20.0
|
||||
github.com/kr/pretty v0.1.0
|
||||
github.com/kr/text v0.1.0
|
||||
github.com/containers/image v2.0.0
|
||||
github.com/containers/image podman-1.4.2
|
||||
github.com/containers/buildah v1.8.4
|
||||
github.com/vbauerster/mpb v3.3.4
|
||||
github.com/mattn/go-isatty v0.0.4
|
||||
@@ -11,7 +11,7 @@ golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||
github.com/containers/storage v1.12.10
|
||||
github.com/sirupsen/logrus v1.0.0
|
||||
github.com/go-check/check v1
|
||||
github.com/go-check/check 788fd78401277ebd861206a03c884797c6ec5541
|
||||
github.com/stretchr/testify v1.1.3
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/pmezard/go-difflib 5d4384ee4fb2527b0a1256a821ebfc92f91efefc
|
||||
@@ -47,7 +47,7 @@ github.com/xeipuuv/gojsonschema v1.1.0
|
||||
go4.org ce4c26f7be8eb27dc77f996b08d286dd80bc4a01 https://github.com/camlistore/go4
|
||||
github.com/ostreedev/ostree-go 56f3a639dbc0f2f5051c6d52dade28a882ba78ce
|
||||
# -- end OCI image validation requirements
|
||||
github.com/mtrmac/gpgme b2432428689ca58c2b8e8dea9449d3295cf96fc9
|
||||
github.com/mtrmac/gpgme v0.1.2
|
||||
# openshift/origin' k8s dependencies as of OpenShift v1.1.5
|
||||
k8s.io/client-go kubernetes-1.10.13-beta.0
|
||||
github.com/ghodss/yaml 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
||||
|
||||
7
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
7
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -17,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/pkg/docker/config"
|
||||
"github.com/containers/image/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/pkg/tlsclientconfig"
|
||||
@@ -540,7 +540,7 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected http code: %d (%s), URL: %s", res.StatusCode, http.StatusText(res.StatusCode), authReq.URL)
|
||||
}
|
||||
tokenBlob, err := ioutil.ReadAll(res.Body)
|
||||
tokenBlob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -631,7 +631,8 @@ func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerRe
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, errors.Wrapf(client.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name())
|
||||
}
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
|
||||
body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureListBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
3
vendor/github.com/containers/image/docker/docker_image_dest.go
generated
vendored
3
vendor/github.com/containers/image/docker/docker_image_dest.go
generated
vendored
@@ -15,6 +15,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/types"
|
||||
@@ -590,7 +591,7 @@ sigExists:
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxErrorBodySize)
|
||||
if err == nil {
|
||||
logrus.Debugf("Error body %s", string(body))
|
||||
}
|
||||
|
||||
10
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
10
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/types"
|
||||
@@ -148,7 +149,8 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.ref.ref.Name())
|
||||
}
|
||||
manblob, err := ioutil.ReadAll(res.Body)
|
||||
|
||||
manblob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxManifestBodySize)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -335,7 +337,7 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) (
|
||||
} else if res.StatusCode != http.StatusOK {
|
||||
return nil, false, errors.Errorf("Error reading signature from %s: status %d (%s)", url.String(), res.StatusCode, http.StatusText(res.StatusCode))
|
||||
}
|
||||
sig, err := ioutil.ReadAll(res.Body)
|
||||
sig, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureBodySize)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@@ -396,7 +398,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
|
||||
return err
|
||||
}
|
||||
defer get.Body.Close()
|
||||
manifestBody, err := ioutil.ReadAll(get.Body)
|
||||
manifestBody, err := iolimits.ReadAtMost(get.Body, iolimits.MaxManifestBodySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -419,7 +421,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
|
||||
}
|
||||
defer delete.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(delete.Body)
|
||||
body, err := iolimits.ReadAtMost(delete.Body, iolimits.MaxErrorBodySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
3
vendor/github.com/containers/image/docker/tarfile/dest.go
generated
vendored
3
vendor/github.com/containers/image/docker/tarfile/dest.go
generated
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/internal/tmpdir"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/types"
|
||||
@@ -135,7 +136,7 @@ func (d *Destination) PutBlob(ctx context.Context, stream io.Reader, inputInfo t
|
||||
}
|
||||
|
||||
if isConfig {
|
||||
buf, err := ioutil.ReadAll(stream)
|
||||
buf, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, errors.Wrap(err, "Error reading Config file stream")
|
||||
}
|
||||
|
||||
9
vendor/github.com/containers/image/docker/tarfile/src.go
generated
vendored
9
vendor/github.com/containers/image/docker/tarfile/src.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/containers/image/internal/tmpdir"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/pkg/compression"
|
||||
"github.com/containers/image/types"
|
||||
@@ -187,13 +188,13 @@ func findTarComponent(inputFile io.Reader, path string) (*tar.Reader, *tar.Heade
|
||||
}
|
||||
|
||||
// readTarComponent returns full contents of componentPath.
|
||||
func (s *Source) readTarComponent(path string) ([]byte, error) {
|
||||
func (s *Source) readTarComponent(path string, limit int) ([]byte, error) {
|
||||
file, err := s.openTarComponent(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error loading tar component %s", path)
|
||||
}
|
||||
defer file.Close()
|
||||
bytes, err := ioutil.ReadAll(file)
|
||||
bytes, err := iolimits.ReadAtMost(file, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -217,7 +218,7 @@ func (s *Source) ensureCachedDataIsPresent() error {
|
||||
}
|
||||
|
||||
// Read and parse config.
|
||||
configBytes, err := s.readTarComponent(tarManifest[0].Config)
|
||||
configBytes, err := s.readTarComponent(tarManifest[0].Config, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
s.cacheDataResult = err
|
||||
return
|
||||
@@ -247,7 +248,7 @@ func (s *Source) ensureCachedDataIsPresent() error {
|
||||
// loadTarManifest loads and decodes the manifest.json.
|
||||
func (s *Source) loadTarManifest() ([]ManifestItem, error) {
|
||||
// FIXME? Do we need to deal with the legacy format?
|
||||
bytes, err := s.readTarComponent(manifestFileName)
|
||||
bytes, err := s.readTarComponent(manifestFileName, iolimits.MaxTarFileManifestSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/containers/image/image/docker_schema2.go
generated
vendored
4
vendor/github.com/containers/image/image/docker_schema2.go
generated
vendored
@@ -6,10 +6,10 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/types"
|
||||
@@ -101,7 +101,7 @@ func (m *manifestSchema2) ConfigBlob(ctx context.Context) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer stream.Close()
|
||||
blob, err := ioutil.ReadAll(stream)
|
||||
blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/containers/image/image/oci.go
generated
vendored
4
vendor/github.com/containers/image/image/oci.go
generated
vendored
@@ -3,9 +3,9 @@ package image
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/types"
|
||||
@@ -66,7 +66,7 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer stream.Close()
|
||||
blob, err := ioutil.ReadAll(stream)
|
||||
blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
60
vendor/github.com/containers/image/internal/iolimits/iolimits.go
generated
vendored
Normal file
60
vendor/github.com/containers/image/internal/iolimits/iolimits.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package iolimits
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// All constants below are intended to be used as limits for `ReadAtMost`. The
|
||||
// immediate use-case for limiting the size of in-memory copied data is to
|
||||
// protect against OOM DOS attacks as described inCVE-2020-1702. Instead of
|
||||
// copying data until running out of memory, we error out after hitting the
|
||||
// specified limit.
|
||||
const (
|
||||
// megaByte denotes one megabyte and is intended to be used as a limit in
|
||||
// `ReadAtMost`.
|
||||
megaByte = 1 << 20
|
||||
// MaxManifestBodySize is the maximum allowed size of a manifest. The limit
|
||||
// of 4 MB aligns with the one of a Docker registry:
|
||||
// https://github.com/docker/distribution/blob/a8371794149d1d95f1e846744b05c87f2f825e5a/registry/handlers/manifests.go#L30
|
||||
MaxManifestBodySize = 4 * megaByte
|
||||
// MaxAuthTokenBodySize is the maximum allowed size of an auth token.
|
||||
// The limit of 1 MB is considered to be greatly sufficient.
|
||||
MaxAuthTokenBodySize = megaByte
|
||||
// MaxSignatureListBodySize is the maximum allowed size of a signature list.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxSignatureListBodySize = 4 * megaByte
|
||||
// MaxSignatureBodySize is the maximum allowed size of a signature.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxSignatureBodySize = 4 * megaByte
|
||||
// MaxErrorBodySize is the maximum allowed size of an error-response body.
|
||||
// The limit of 1 MB is considered to be greatly sufficient.
|
||||
MaxErrorBodySize = megaByte
|
||||
// MaxConfigBodySize is the maximum allowed size of a config blob.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxConfigBodySize = 4 * megaByte
|
||||
// MaxOpenShiftStatusBody is the maximum allowed size of an OpenShift status body.
|
||||
// The limit of 4 MB is considered to be greatly sufficient.
|
||||
MaxOpenShiftStatusBody = 4 * megaByte
|
||||
// MaxTarFileManifestSize is the maximum allowed size of a (docker save)-like manifest (which may contain multiple images)
|
||||
// The limit of 1 MB is considered to be greatly sufficient.
|
||||
MaxTarFileManifestSize = megaByte
|
||||
)
|
||||
|
||||
// ReadAtMost reads from reader and errors out if the specified limit (in bytes) is exceeded.
|
||||
func ReadAtMost(reader io.Reader, limit int) ([]byte, error) {
|
||||
limitedReader := io.LimitReader(reader, int64(limit+1))
|
||||
|
||||
res, err := ioutil.ReadAll(limitedReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(res) > limit {
|
||||
return nil, errors.Errorf("exceeded maximum allowed size of %d bytes", limit)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
4
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
4
vendor/github.com/containers/image/openshift/openshift.go
generated
vendored
@@ -7,13 +7,13 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/docker"
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/internal/iolimits"
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/image/version"
|
||||
@@ -102,7 +102,7 @@ func (c *openshiftClient) doRequest(ctx context.Context, method, path string, re
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxOpenShiftStatusBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
18
vendor/github.com/mtrmac/gpgme/data.go
generated
vendored
18
vendor/github.com/mtrmac/gpgme/data.go
generated
vendored
@@ -50,25 +50,25 @@ func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
|
||||
}
|
||||
|
||||
//export gogpgme_seekfunc
|
||||
func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t {
|
||||
func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {
|
||||
d := callbackLookup(uintptr(handle)).(*Data)
|
||||
n, err := d.s.Seek(int64(offset), int(whence))
|
||||
if err != nil {
|
||||
C.gpgme_err_set_errno(C.EIO)
|
||||
return -1
|
||||
}
|
||||
return C.off_t(n)
|
||||
return C.gpgme_off_t(n)
|
||||
}
|
||||
|
||||
// The Data buffer used to communicate with GPGME
|
||||
type Data struct {
|
||||
dh C.gpgme_data_t
|
||||
dh C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C
|
||||
buf []byte
|
||||
cbs C.struct_gpgme_data_cbs
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
s io.Seeker
|
||||
cbc uintptr
|
||||
cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)
|
||||
}
|
||||
|
||||
func newData() *Data {
|
||||
@@ -154,12 +154,14 @@ func (d *Data) Close() error {
|
||||
callbackDelete(d.cbc)
|
||||
}
|
||||
_, err := C.gpgme_data_release(d.dh)
|
||||
runtime.KeepAlive(d)
|
||||
d.dh = nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Data) Write(p []byte) (int, error) {
|
||||
n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
|
||||
runtime.KeepAlive(d)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -171,6 +173,7 @@ func (d *Data) Write(p []byte) (int, error) {
|
||||
|
||||
func (d *Data) Read(p []byte) (int, error) {
|
||||
n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
|
||||
runtime.KeepAlive(d)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -181,11 +184,14 @@ func (d *Data) Read(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (d *Data) Seek(offset int64, whence int) (int64, error) {
|
||||
n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence))
|
||||
n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))
|
||||
runtime.KeepAlive(d)
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// Name returns the associated filename if any
|
||||
func (d *Data) Name() string {
|
||||
return C.GoString(C.gpgme_data_get_file_name(d.dh))
|
||||
res := C.GoString(C.gpgme_data_get_file_name(d.dh))
|
||||
runtime.KeepAlive(d)
|
||||
return res
|
||||
}
|
||||
|
||||
3
vendor/github.com/mtrmac/gpgme/go.mod
generated
vendored
Normal file
3
vendor/github.com/mtrmac/gpgme/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module github.com/mtrmac/gpgme
|
||||
|
||||
go 1.11
|
||||
22
vendor/github.com/mtrmac/gpgme/go_gpgme.c
generated
vendored
22
vendor/github.com/mtrmac/gpgme/go_gpgme.c
generated
vendored
@@ -8,6 +8,28 @@ void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintpt
|
||||
gpgme_set_passphrase_cb(ctx, cb, (void *)handle);
|
||||
}
|
||||
|
||||
gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence) {
|
||||
return gpgme_data_seek(dh, offset, whence);
|
||||
}
|
||||
|
||||
gpgme_error_t gogpgme_op_assuan_transact_ext(
|
||||
gpgme_ctx_t ctx,
|
||||
char* cmd,
|
||||
uintptr_t data_h,
|
||||
uintptr_t inquiry_h,
|
||||
uintptr_t status_h,
|
||||
gpgme_error_t *operr
|
||||
){
|
||||
return gpgme_op_assuan_transact_ext(
|
||||
ctx,
|
||||
cmd,
|
||||
(gpgme_assuan_data_cb_t) gogpgme_assuan_data_callback, (void *)data_h,
|
||||
(gpgme_assuan_inquire_cb_t) gogpgme_assuan_inquiry_callback, (void *)inquiry_h,
|
||||
(gpgme_assuan_status_cb_t) gogpgme_assuan_status_callback, (void *)status_h,
|
||||
operr
|
||||
);
|
||||
}
|
||||
|
||||
unsigned int key_revoked(gpgme_key_t k) {
|
||||
return k->revoked;
|
||||
}
|
||||
|
||||
12
vendor/github.com/mtrmac/gpgme/go_gpgme.h
generated
vendored
12
vendor/github.com/mtrmac/gpgme/go_gpgme.h
generated
vendored
@@ -6,12 +6,24 @@
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */
|
||||
#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402
|
||||
typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */
|
||||
#endif
|
||||
|
||||
extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
|
||||
extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
|
||||
extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
|
||||
extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd);
|
||||
extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle);
|
||||
extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle);
|
||||
extern gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence);
|
||||
|
||||
extern gpgme_error_t gogpgme_op_assuan_transact_ext(gpgme_ctx_t ctx, char *cmd, uintptr_t data_h, uintptr_t inquiry_h , uintptr_t status_h, gpgme_error_t *operr);
|
||||
|
||||
extern gpgme_error_t gogpgme_assuan_data_callback(void *opaque, void* data, size_t datalen );
|
||||
extern gpgme_error_t gogpgme_assuan_inquiry_callback(void *opaque, char* name, char* args);
|
||||
extern gpgme_error_t gogpgme_assuan_status_callback(void *opaque, char* status, char* args);
|
||||
|
||||
extern unsigned int key_revoked(gpgme_key_t k);
|
||||
extern unsigned int key_expired(gpgme_key_t k);
|
||||
|
||||
346
vendor/github.com/mtrmac/gpgme/gpgme.go
generated
vendored
346
vendor/github.com/mtrmac/gpgme/gpgme.go
generated
vendored
@@ -7,7 +7,6 @@ package gpgme
|
||||
// #include <gpgme.h>
|
||||
// #include "go_gpgme.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -48,9 +47,8 @@ const (
|
||||
ProtocolAssuan Protocol = C.GPGME_PROTOCOL_ASSUAN
|
||||
ProtocolG13 Protocol = C.GPGME_PROTOCOL_G13
|
||||
ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
|
||||
// ProtocolSpawn Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
|
||||
ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
|
||||
ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
|
||||
ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
|
||||
ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
|
||||
)
|
||||
|
||||
type PinEntryMode int
|
||||
@@ -70,7 +68,6 @@ const (
|
||||
EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
|
||||
EncryptPrepare EncryptFlag = C.GPGME_ENCRYPT_PREPARE
|
||||
EncryptExceptSign EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
|
||||
// EncryptNoCompress EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
|
||||
)
|
||||
|
||||
type HashAlgo int
|
||||
@@ -84,7 +81,6 @@ const (
|
||||
KeyListModeExtern KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
|
||||
KeyListModeSigs KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
|
||||
KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
|
||||
// KeyListModeWithSecret KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
|
||||
KeyListModeEphemeral KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
|
||||
KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
|
||||
)
|
||||
@@ -168,39 +164,60 @@ func EngineCheckVersion(p Protocol) error {
|
||||
}
|
||||
|
||||
type EngineInfo struct {
|
||||
info C.gpgme_engine_info_t
|
||||
next *EngineInfo
|
||||
protocol Protocol
|
||||
fileName string
|
||||
homeDir string
|
||||
version string
|
||||
requiredVersion string
|
||||
}
|
||||
|
||||
func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
|
||||
res := &EngineInfo{
|
||||
next: nil,
|
||||
protocol: Protocol(info.protocol),
|
||||
fileName: C.GoString(info.file_name),
|
||||
homeDir: C.GoString(info.home_dir),
|
||||
version: C.GoString(info.version),
|
||||
requiredVersion: C.GoString(info.req_version),
|
||||
}
|
||||
if info.next != nil {
|
||||
res.next = copyEngineInfo(info.next)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (e *EngineInfo) Next() *EngineInfo {
|
||||
if e.info.next == nil {
|
||||
return nil
|
||||
}
|
||||
return &EngineInfo{info: e.info.next}
|
||||
return e.next
|
||||
}
|
||||
|
||||
func (e *EngineInfo) Protocol() Protocol {
|
||||
return Protocol(e.info.protocol)
|
||||
return e.protocol
|
||||
}
|
||||
|
||||
func (e *EngineInfo) FileName() string {
|
||||
return C.GoString(e.info.file_name)
|
||||
return e.fileName
|
||||
}
|
||||
|
||||
func (e *EngineInfo) Version() string {
|
||||
return C.GoString(e.info.version)
|
||||
return e.version
|
||||
}
|
||||
|
||||
func (e *EngineInfo) RequiredVersion() string {
|
||||
return C.GoString(e.info.req_version)
|
||||
return e.requiredVersion
|
||||
}
|
||||
|
||||
func (e *EngineInfo) HomeDir() string {
|
||||
return C.GoString(e.info.home_dir)
|
||||
return e.homeDir
|
||||
}
|
||||
|
||||
func GetEngineInfo() (*EngineInfo, error) {
|
||||
info := &EngineInfo{}
|
||||
return info, handleError(C.gpgme_get_engine_info(&info.info))
|
||||
var cInfo C.gpgme_engine_info_t
|
||||
err := handleError(C.gpgme_get_engine_info(&cInfo))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
|
||||
}
|
||||
|
||||
func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
|
||||
@@ -261,9 +278,9 @@ type Context struct {
|
||||
KeyError error
|
||||
|
||||
callback Callback
|
||||
cbc uintptr
|
||||
cbc uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
|
||||
|
||||
ctx C.gpgme_ctx_t
|
||||
ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
|
||||
}
|
||||
|
||||
func New() (*Context, error) {
|
||||
@@ -281,49 +298,68 @@ func (c *Context) Release() {
|
||||
callbackDelete(c.cbc)
|
||||
}
|
||||
C.gpgme_release(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
c.ctx = nil
|
||||
}
|
||||
|
||||
func (c *Context) SetArmor(yes bool) {
|
||||
C.gpgme_set_armor(c.ctx, cbool(yes))
|
||||
runtime.KeepAlive(c)
|
||||
}
|
||||
|
||||
func (c *Context) Armor() bool {
|
||||
return C.gpgme_get_armor(c.ctx) != 0
|
||||
res := C.gpgme_get_armor(c.ctx) != 0
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetTextMode(yes bool) {
|
||||
C.gpgme_set_textmode(c.ctx, cbool(yes))
|
||||
runtime.KeepAlive(c)
|
||||
}
|
||||
|
||||
func (c *Context) TextMode() bool {
|
||||
return C.gpgme_get_textmode(c.ctx) != 0
|
||||
res := C.gpgme_get_textmode(c.ctx) != 0
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetProtocol(p Protocol) error {
|
||||
return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
|
||||
err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) Protocol() Protocol {
|
||||
return Protocol(C.gpgme_get_protocol(c.ctx))
|
||||
res := Protocol(C.gpgme_get_protocol(c.ctx))
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetKeyListMode(m KeyListMode) error {
|
||||
return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
|
||||
err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) KeyListMode() KeyListMode {
|
||||
return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
|
||||
res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
|
||||
runtime.KeepAlive(c)
|
||||
return res
|
||||
}
|
||||
|
||||
// Unavailable in 1.3.2:
|
||||
// func (c *Context) SetPinEntryMode(m PinEntryMode) error {
|
||||
// return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
|
||||
// err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
|
||||
// runtime.KeepAlive(c)
|
||||
// return err
|
||||
// }
|
||||
|
||||
// Unavailable in 1.3.2:
|
||||
// func (c *Context) PinEntryMode() PinEntryMode {
|
||||
// return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
|
||||
// res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
|
||||
// runtime.KeepAlive(c)
|
||||
// return res
|
||||
// }
|
||||
|
||||
func (c *Context) SetCallback(callback Callback) error {
|
||||
@@ -340,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error {
|
||||
c.cbc = 0
|
||||
_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
|
||||
}
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) EngineInfo() *EngineInfo {
|
||||
return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
|
||||
cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
// NOTE: c must be live as long as we are accessing cInfo.
|
||||
res := copyEngineInfo(cInfo)
|
||||
runtime.KeepAlive(c) // for accesses to cInfo
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
|
||||
@@ -357,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error
|
||||
chome = C.CString(homeDir)
|
||||
defer C.free(unsafe.Pointer(chome))
|
||||
}
|
||||
return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
|
||||
err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
|
||||
cpattern := C.CString(pattern)
|
||||
defer C.free(unsafe.Pointer(cpattern))
|
||||
err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
|
||||
return handleError(err)
|
||||
err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) KeyListNext() bool {
|
||||
c.Key = newKey()
|
||||
err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
|
||||
runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
|
||||
if err != nil {
|
||||
if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
|
||||
c.KeyError = nil
|
||||
@@ -383,7 +429,9 @@ func (c *Context) KeyListNext() bool {
|
||||
}
|
||||
|
||||
func (c *Context) KeyListEnd() error {
|
||||
return handleError(C.gpgme_op_keylist_end(c.ctx))
|
||||
err := handleError(C.gpgme_op_keylist_end(c.ctx))
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
|
||||
@@ -391,7 +439,11 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
|
||||
cfpr := C.CString(fingerprint)
|
||||
defer C.free(unsafe.Pointer(cfpr))
|
||||
err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
|
||||
if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF {
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(key)
|
||||
keyKIsNil := key.k == nil
|
||||
runtime.KeepAlive(key)
|
||||
if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
|
||||
return nil, fmt.Errorf("key %q not found", fingerprint)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -401,11 +453,19 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
|
||||
}
|
||||
|
||||
func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
|
||||
return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(ciphertext)
|
||||
runtime.KeepAlive(plaintext)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
|
||||
return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(ciphertext)
|
||||
runtime.KeepAlive(plaintext)
|
||||
return err
|
||||
}
|
||||
|
||||
type Signature struct {
|
||||
@@ -432,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
|
||||
plainPtr = plain.dh
|
||||
}
|
||||
err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(sig)
|
||||
if signedText != nil {
|
||||
runtime.KeepAlive(signedText)
|
||||
}
|
||||
if plain != nil {
|
||||
runtime.KeepAlive(plain)
|
||||
}
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
res := C.gpgme_op_verify_result(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
// NOTE: c must be live as long as we are accessing res.
|
||||
sigs := []Signature{}
|
||||
for s := res.signatures; s != nil; s = s.next {
|
||||
sig := Signature{
|
||||
@@ -455,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
|
||||
}
|
||||
sigs = append(sigs, sig)
|
||||
}
|
||||
return C.GoString(res.file_name), sigs, nil
|
||||
fileName := C.GoString(res.file_name)
|
||||
runtime.KeepAlive(c) // for all accesses to res above
|
||||
return fileName, sigs, nil
|
||||
}
|
||||
|
||||
func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
|
||||
@@ -467,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe
|
||||
*ptr = recipients[i].k
|
||||
}
|
||||
err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(recipients)
|
||||
runtime.KeepAlive(plaintext)
|
||||
runtime.KeepAlive(ciphertext)
|
||||
return handleError(err)
|
||||
}
|
||||
|
||||
func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
|
||||
C.gpgme_signers_clear(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
for _, k := range signers {
|
||||
if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
|
||||
err := handleError(C.gpgme_signers_add(c.ctx, k.k))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(k)
|
||||
if err != nil {
|
||||
C.gpgme_signers_clear(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
|
||||
err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(plain)
|
||||
runtime.KeepAlive(sig)
|
||||
return err
|
||||
}
|
||||
|
||||
type AssuanDataCallback func(data []byte) error
|
||||
type AssuanInquireCallback func(name, args string) error
|
||||
type AssuanStatusCallback func(status, args string) error
|
||||
|
||||
// AssuanSend sends a raw Assuan command to gpg-agent
|
||||
func (c *Context) AssuanSend(
|
||||
cmd string,
|
||||
data AssuanDataCallback,
|
||||
inquiry AssuanInquireCallback,
|
||||
status AssuanStatusCallback,
|
||||
) error {
|
||||
var operr C.gpgme_error_t
|
||||
|
||||
dataPtr := callbackAdd(&data)
|
||||
inquiryPtr := callbackAdd(&inquiry)
|
||||
statusPtr := callbackAdd(&status)
|
||||
cmdCStr := C.CString(cmd)
|
||||
defer C.free(unsafe.Pointer(cmdCStr))
|
||||
err := C.gogpgme_op_assuan_transact_ext(
|
||||
c.ctx,
|
||||
cmdCStr,
|
||||
C.uintptr_t(dataPtr),
|
||||
C.uintptr_t(inquiryPtr),
|
||||
C.uintptr_t(statusPtr),
|
||||
&operr,
|
||||
)
|
||||
runtime.KeepAlive(c)
|
||||
|
||||
if handleError(operr) != nil {
|
||||
return handleError(operr)
|
||||
}
|
||||
return handleError(err)
|
||||
}
|
||||
|
||||
//export gogpgme_assuan_data_callback
|
||||
func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
|
||||
c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
|
||||
if *c == nil {
|
||||
return 0
|
||||
}
|
||||
(*c)(C.GoBytes(data, C.int(datalen)))
|
||||
return 0
|
||||
}
|
||||
|
||||
//export gogpgme_assuan_inquiry_callback
|
||||
func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
|
||||
name := C.GoString(cName)
|
||||
args := C.GoString(cArgs)
|
||||
c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
|
||||
if *c == nil {
|
||||
return 0
|
||||
}
|
||||
(*c)(name, args)
|
||||
return 0
|
||||
}
|
||||
|
||||
//export gogpgme_assuan_status_callback
|
||||
func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
|
||||
status := C.GoString(cStatus)
|
||||
args := C.GoString(cArgs)
|
||||
c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
|
||||
if *c == nil {
|
||||
return 0
|
||||
}
|
||||
(*c)(status, args)
|
||||
return 0
|
||||
}
|
||||
|
||||
// ExportModeFlags defines how keys are exported from Export
|
||||
type ExportModeFlags uint
|
||||
|
||||
const (
|
||||
ExportModeExtern ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
|
||||
ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
|
||||
)
|
||||
|
||||
func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
|
||||
pat := C.CString(pattern)
|
||||
defer C.free(unsafe.Pointer(pat))
|
||||
err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
|
||||
@@ -517,10 +687,14 @@ type ImportResult struct {
|
||||
|
||||
func (c *Context) Import(keyData *Data) (*ImportResult, error) {
|
||||
err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
|
||||
runtime.KeepAlive(c)
|
||||
runtime.KeepAlive(keyData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := C.gpgme_op_import_result(c.ctx)
|
||||
runtime.KeepAlive(c)
|
||||
// NOTE: c must be live as long as we are accessing res.
|
||||
imports := []ImportStatus{}
|
||||
for s := res.imports; s != nil; s = s.next {
|
||||
imports = append(imports, ImportStatus{
|
||||
@@ -529,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
|
||||
Status: ImportStatusFlags(s.status),
|
||||
})
|
||||
}
|
||||
return &ImportResult{
|
||||
importResult := &ImportResult{
|
||||
Considered: int(res.considered),
|
||||
NoUserID: int(res.no_user_id),
|
||||
Imported: int(res.imported),
|
||||
@@ -544,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
|
||||
SecretUnchanged: int(res.secret_unchanged),
|
||||
NotImported: int(res.not_imported),
|
||||
Imports: imports,
|
||||
}, nil
|
||||
}
|
||||
runtime.KeepAlive(c) // for all accesses to res above
|
||||
return importResult, nil
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
k C.gpgme_key_t
|
||||
k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
|
||||
}
|
||||
|
||||
func newKey() *Key {
|
||||
@@ -559,85 +735,122 @@ func newKey() *Key {
|
||||
|
||||
func (k *Key) Release() {
|
||||
C.gpgme_key_release(k.k)
|
||||
runtime.KeepAlive(k)
|
||||
k.k = nil
|
||||
}
|
||||
|
||||
func (k *Key) Revoked() bool {
|
||||
return C.key_revoked(k.k) != 0
|
||||
res := C.key_revoked(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Expired() bool {
|
||||
return C.key_expired(k.k) != 0
|
||||
res := C.key_expired(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Disabled() bool {
|
||||
return C.key_disabled(k.k) != 0
|
||||
res := C.key_disabled(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Invalid() bool {
|
||||
return C.key_invalid(k.k) != 0
|
||||
res := C.key_invalid(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanEncrypt() bool {
|
||||
return C.key_can_encrypt(k.k) != 0
|
||||
res := C.key_can_encrypt(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanSign() bool {
|
||||
return C.key_can_sign(k.k) != 0
|
||||
res := C.key_can_sign(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanCertify() bool {
|
||||
return C.key_can_certify(k.k) != 0
|
||||
res := C.key_can_certify(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Secret() bool {
|
||||
return C.key_secret(k.k) != 0
|
||||
res := C.key_secret(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) CanAuthenticate() bool {
|
||||
return C.key_can_authenticate(k.k) != 0
|
||||
res := C.key_can_authenticate(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) IsQualified() bool {
|
||||
return C.key_is_qualified(k.k) != 0
|
||||
res := C.key_is_qualified(k.k) != 0
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) Protocol() Protocol {
|
||||
return Protocol(k.k.protocol)
|
||||
res := Protocol(k.k.protocol)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) IssuerSerial() string {
|
||||
return C.GoString(k.k.issuer_serial)
|
||||
res := C.GoString(k.k.issuer_serial)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) IssuerName() string {
|
||||
return C.GoString(k.k.issuer_name)
|
||||
res := C.GoString(k.k.issuer_name)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) ChainID() string {
|
||||
return C.GoString(k.k.chain_id)
|
||||
res := C.GoString(k.k.chain_id)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) OwnerTrust() Validity {
|
||||
return Validity(k.k.owner_trust)
|
||||
res := Validity(k.k.owner_trust)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
func (k *Key) SubKeys() *SubKey {
|
||||
if k.k.subkeys == nil {
|
||||
subKeys := k.k.subkeys
|
||||
runtime.KeepAlive(k)
|
||||
if subKeys == nil {
|
||||
return nil
|
||||
}
|
||||
return &SubKey{k: k.k.subkeys, parent: k}
|
||||
return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
|
||||
}
|
||||
|
||||
func (k *Key) UserIDs() *UserID {
|
||||
if k.k.uids == nil {
|
||||
uids := k.k.uids
|
||||
runtime.KeepAlive(k)
|
||||
if uids == nil {
|
||||
return nil
|
||||
}
|
||||
return &UserID{u: k.k.uids, parent: k}
|
||||
return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
|
||||
}
|
||||
|
||||
func (k *Key) KeyListMode() KeyListMode {
|
||||
return KeyListMode(k.k.keylist_mode)
|
||||
res := KeyListMode(k.k.keylist_mode)
|
||||
runtime.KeepAlive(k)
|
||||
return res
|
||||
}
|
||||
|
||||
type SubKey struct {
|
||||
@@ -737,12 +950,3 @@ func (u *UserID) Comment() string {
|
||||
func (u *UserID) Email() string {
|
||||
return C.GoString(u.u.email)
|
||||
}
|
||||
|
||||
// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
|
||||
// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
|
||||
// - and cgo can't be used in tests. So, provide this helper for test initialization.
|
||||
func unsetenvGPGAgentInfo() {
|
||||
v := C.CString("GPG_AGENT_INFO")
|
||||
defer C.free(unsafe.Pointer(v))
|
||||
C.unsetenv(v)
|
||||
}
|
||||
|
||||
18
vendor/github.com/mtrmac/gpgme/unset_agent_info.go
generated
vendored
Normal file
18
vendor/github.com/mtrmac/gpgme/unset_agent_info.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build !windows
|
||||
|
||||
package gpgme
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
|
||||
// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
|
||||
// - and cgo can't be used in tests. So, provide this helper for test initialization.
|
||||
func unsetenvGPGAgentInfo() {
|
||||
v := C.CString("GPG_AGENT_INFO")
|
||||
defer C.free(unsafe.Pointer(v))
|
||||
C.unsetenv(v)
|
||||
}
|
||||
14
vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
generated
vendored
Normal file
14
vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package gpgme
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// unsetenv is not available in mingw
|
||||
func unsetenvGPGAgentInfo() {
|
||||
v := C.CString("GPG_AGENT_INFO=")
|
||||
defer C.free(unsafe.Pointer(v))
|
||||
C.putenv(v)
|
||||
}
|
||||
Reference in New Issue
Block a user