diff --git a/.github/workflows/fixtures/generate.sh b/.github/workflows/fixtures/generate.sh old mode 100644 new mode 100755 index 2f2af822..17ffd777 --- a/.github/workflows/fixtures/generate.sh +++ b/.github/workflows/fixtures/generate.sh @@ -1,7 +1,9 @@ #!/usr/bin/env sh set -ex -gpg --batch --gen-key <<-EOF +# shellcheck disable=SC2155 +export GPG_TTY=$(tty) +gpg --batch --gen-key --no-tty <<-EOF %echo Generating a standard key Key-Type: DSA Key-Length: 1024 @@ -9,8 +11,18 @@ Subkey-Type: ELG-E Subkey-Length: 1024 Name-Real: Meshuggah Rocks Name-Email: meshuggah@example.com +Passphrase: with stupid passphrase Expire-Date: 0 # Do a commit here, so that we can later print "done" :-) %commit %echo done EOF + +# doesn't work; still asks for passphrase interactively +# gpg --output private.pgp --armor --export-secret-key meshuggah@example.com + +# doesn't work; still asks for passphrase interactively +# gpg --passphrase 'with stupid passphrase' --output private.pgp --armor --export-secret-key meshuggah@example.com + +# doesn't work; still asks for passphrase interactively +# gpg --batch --passphrase 'with stupid passphrase' --no-tty --output private.pgp --armor --export-secret-key meshuggah@example.com diff --git a/Dockerfile b/Dockerfile index 06cfe40f..488b9789 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,7 +68,7 @@ RUN xx-apt-get install -y binutils gcc libc6-dev libgcc-10-dev libsecret-1-dev p FROM base AS test ARG DEBIAN_FRONTEND -RUN xx-apt-get install -y dbus-x11 gnome-keyring gpg-agent gpgconf libsecret-1-dev pass +RUN xx-apt-get install -y dbus-x11 gnome-keyring gpg-agent gpgconf keyutils libsecret-1-dev pass RUN --mount=type=bind,target=. \ --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/go/pkg/mod < size { + r1, err := keyctl_Read(k.id, &b[0], size) + if err != nil { + return nil, err + } + + if sizeRead = int(r1); sizeRead > size { + b = make([]byte, sizeRead) + size = sizeRead + sizeRead = size + 1 + } else { + k.size = sizeRead + } + } + return b[:k.size], err +} + +// Set the key's value from a bytes slice. Expiration, if active, is reset by calling this method. +func (k *Key) Set(b []byte) error { + err := updateKey(k.id, b) + if err == nil && k.ttl > 0 { + err = k.ExpireAfter(uint(k.ttl.Seconds())) + } + return err +} + +// Unlink a key from the keyring it was loaded from (or added to). If the key +// is not linked to any other keyrings, it is destroyed. +func (k *Key) Unlink() error { + return keyctl_Unlink(k.id, k.ring) +} diff --git a/vendor/github.com/jsipprell/keyctl/keyring.go b/vendor/github.com/jsipprell/keyctl/keyring.go new file mode 100644 index 00000000..5c5a9b93 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/keyring.go @@ -0,0 +1,195 @@ +// Copyright 2015 Jesse Sipprell. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux + +// A Go interface to linux kernel keyrings (keyctl interface) +package keyctl + +// All Keys and Keyrings have unique 32-bit serial number identifiers. +type Id interface { + Id() int32 + Info() (Info, error) + + private() +} + +// Basic interface to a linux keyctl keyring. +type Keyring interface { + Id + Add(string, []byte) (*Key, error) + Search(string) (*Key, error) + SetDefaultTimeout(uint) +} + +// Named keyrings are user-created keyrings linked to a parent keyring. The +// parent can be either named or one of the in-built keyrings (session, group +// etc). The in-built keyrings have no parents. Keyring searching is performed +// hierarchically. +type NamedKeyring interface { + Keyring + Name() string +} + +type keyring struct { + id keyId + defaultTtl uint +} + +type namedKeyring struct { + *keyring + parent keyId + name string // for non-anonymous keyrings + ttl uint +} + +func (kr *keyring) private() {} + +// Returns the 32-bit kernel identifier of a keyring +func (kr *keyring) Id() int32 { + return int32(kr.id) +} + +// Returns information about a keyring. +func (kr *keyring) Info() (Info, error) { + return getInfo(kr.id) +} + +// Return the name of a NamedKeyring that was set when the keyring was created +// or opened. +func (kr *namedKeyring) Name() string { + return kr.name +} + +// Set a default timeout, in seconds, after which newly added keys will be +// destroyed. +func (kr *keyring) SetDefaultTimeout(nsecs uint) { + kr.defaultTtl = nsecs +} + +// Add a new key to a keyring. The key can be searched for later by name. +func (kr *keyring) Add(name string, key []byte) (*Key, error) { + r, err := add_key("user", name, key, int32(kr.id)) + if err == nil { + key := &Key{Name: name, id: keyId(r), ring: kr.id} + if kr.defaultTtl != 0 { + err = key.ExpireAfter(kr.defaultTtl) + } + return key, err + } + + return nil, err +} + +// Search for a key by name, this also searches child keyrings linked to this +// one. The key, if found, is linked to the top keyring that Search() was called +// from. +func (kr *keyring) Search(name string) (*Key, error) { + id, err := searchKeyring(kr.id, name, "user") + if err == nil { + return &Key{Name: name, id: id, ring: kr.id}, nil + } + return nil, err +} + +// Return the current login session keyring +func SessionKeyring() (Keyring, error) { + return newKeyring(keySpecSessionKeyring) +} + +// Return the current user-session keyring (part of session, but private to +// current user) +func UserSessionKeyring() (Keyring, error) { + return newKeyring(keySpecUserSessionKeyring) +} + +// Return the current group keyring. +func GroupKeyring() (Keyring, error) { + return newKeyring(keySpecGroupKeyring) +} + +// Return the keyring specific to the current executing thread. +func ThreadKeyring() (Keyring, error) { + return newKeyring(keySpecThreadKeyring) +} + +// Return the keyring specific to the current executing process. +func ProcessKeyring() (Keyring, error) { + return newKeyring(keySpecProcessKeyring) +} + +// Creates a new named-keyring linked to a parent keyring. The parent may be +// one of those returned by SessionKeyring(), UserSessionKeyring() and friends +// or it may be an existing named-keyring. When searching is performed, all +// keyrings form a hierarchy and are searched top-down. If the keyring already +// exists it will be destroyed and a new one with the same name created. Named +// sub-keyrings inherit their initial ttl (if set) from the parent but can +// outlive the parent as the timer is restarted at creation. +func CreateKeyring(parent Keyring, name string) (NamedKeyring, error) { + var ttl uint + + parentId := keyId(parent.Id()) + kr, err := createKeyring(parentId, name) + if err != nil { + return nil, err + } + + if pkr, ok := parent.(*namedKeyring); ok { + ttl = pkr.ttl + } + ring := &namedKeyring{ + keyring: kr, + parent: parentId, + name: name, + ttl: ttl, + } + + if ttl > 0 { + err = keyctl_SetTimeout(ring.id, ttl) + } + + return ring, nil +} + +// Search for and open an existing keyring with the given name linked to a +// parent keyring (at any depth). +func OpenKeyring(parent Keyring, name string) (NamedKeyring, error) { + parentId := keyId(parent.Id()) + id, err := searchKeyring(parentId, name, "keyring") + if err != nil { + return nil, err + } + + return &namedKeyring{ + keyring: &keyring{id: id}, + parent: parentId, + name: name, + }, nil +} + +// Set the time to live in seconds for an entire keyring and all of its keys. +// Only named keyrings can have their time-to-live set, the in-built keyrings +// cannot (Session, UserSession, etc). +func SetKeyringTTL(kr NamedKeyring, nsecs uint) error { + err := keyctl_SetTimeout(keyId(kr.Id()), nsecs) + if err == nil { + kr.(*namedKeyring).ttl = nsecs + } + return err +} + +// Link an object to a keyring +func Link(parent Keyring, child Id) error { + return keyctl_Link(keyId(child.Id()), keyId(parent.Id())) +} + +// Unlink an object from a keyring +func Unlink(parent Keyring, child Id) error { + return keyctl_Unlink(keyId(child.Id()), keyId(parent.Id())) +} + +// Unlink a named keyring from its parent. +func UnlinkKeyring(kr NamedKeyring) error { + return keyctl_Unlink(keyId(kr.Id()), kr.(*namedKeyring).parent) +} diff --git a/vendor/github.com/jsipprell/keyctl/perms.go b/vendor/github.com/jsipprell/keyctl/perms.go new file mode 100644 index 00000000..41138203 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/perms.go @@ -0,0 +1,110 @@ +package keyctl + +// KeyPerm represents in-kernel access control permission to keys and keyrings +// as a 32-bit integer broken up into four permission sets, one per byte. +// In MSB order, the perms are: Processor, User, Group, Other. +type KeyPerm uint32 + +const ( + PermOtherView KeyPerm = 1 << iota + PermOtherRead + PermOtherWrite + PermOtherSearch + PermOtherLink + PermOtherSetattr +) + +const ( + PermGroupView KeyPerm = 1 << (8 + iota) + PermGroupRead + PermGroupWrite + PermGroupSearch + PermGroupLink + PermGroupSetattr +) + +const ( + PermUserView KeyPerm = 1 << (16 + iota) + PermUserRead + PermUserWrite + PermUserSearch + PermUserLink + PermUserSetattr +) + +const ( + PermProcessView KeyPerm = 1 << (24 + iota) + PermProcessRead + PermProcessWrite + PermProcessSearch + PermProcessLink + PermProcessSetattr +) + +const ( + PermOtherAll KeyPerm = 0x3f << (8 * iota) + PermGroupAll + PermUserAll + PermProcessAll +) + +var permsChars = []byte("--alswrv") + +func encodePerms(p uint8) string { + l := uint(len(permsChars)) + out := make([]byte, l) + + l-- + for i, c := range permsChars { + if p&(1<<(l-uint(i))) == 0 { + out[i] = '-' + } else { + out[i] = c + } + } + + return string(out) +} + +// Returns processor permissions in symbolic form +func (p KeyPerm) Process() string { + return encodePerms(uint8(uint(p) >> 24)) +} + +// Returns the group permissions in symbolic form +func (p KeyPerm) Group() string { + return encodePerms(uint8(uint(p) >> 8)) +} + +// Returns the user permissions in symbolic form +func (p KeyPerm) User() string { + return encodePerms(uint8(uint(p) >> 16)) +} + +// Returns other (default) permissions in symbolic form +func (p KeyPerm) Other() string { + return encodePerms(uint8(p)) +} + +func (p KeyPerm) String() string { + return p.Process()[2:] + p.User()[2:] + p.Group()[2:] + p.Other()[2:] +} + +// Change user ownership on a key or keyring. +func Chown(k Id, user int) error { + group := -1 + + return keyctl_Chown(keyId(k.Id()), user, group) +} + +// Change group ownership on a key or keyring. +func Chgrp(k Id, group int) error { + user := -1 + + return keyctl_Chown(keyId(k.Id()), user, group) +} + +// Set permissions on a key or keyring. +func SetPerm(k Id, p KeyPerm) error { + return keyctl_SetPerm(keyId(k.Id()), uint32(p)) +} diff --git a/vendor/github.com/jsipprell/keyctl/reader.go b/vendor/github.com/jsipprell/keyctl/reader.go new file mode 100644 index 00000000..c4213d17 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/reader.go @@ -0,0 +1,45 @@ +package keyctl + +import ( + "bytes" + "io" + "sync" +) + +type reader struct { + *bytes.Buffer + key *Key + err error + once sync.Once +} + +func (r *reader) Read(b []byte) (int, error) { + r.once.Do(func() { + buf, err := r.key.Get() + if err != nil { + r.err = err + } else { + r.Buffer = bytes.NewBuffer(buf) + } + }) + if r.err != nil { + return -1, r.err + } + + return r.Buffer.Read(b) +} + +// Returns an io.Reader interface object which will read the key's data from +// the kernel. +func NewReader(key *Key) io.Reader { + return &reader{key: key} +} + +// Open an existing key on a keyring given its name +func OpenReader(name string, ring Keyring) (io.Reader, error) { + key, err := ring.Search(name) + if err == nil { + return NewReader(key), nil + } + return nil, err +} diff --git a/vendor/github.com/jsipprell/keyctl/ref.go b/vendor/github.com/jsipprell/keyctl/ref.go new file mode 100644 index 00000000..ea82f768 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/ref.go @@ -0,0 +1,160 @@ +package keyctl + +import ( + "bytes" + "errors" + "os" + "strconv" +) + +var ( + // Error returned if the Get() method is called on a Reference that doesn't + // represent a key or keychain. + ErrUnsupportedKeyType = errors.New("unsupported keyctl key type") + // Error returned if a reference is stale when Info() or Get() is called on + // it. + ErrInvalidReference = errors.New("invalid keyctl reference") +) + +// Reference is a reference to an unloaded keyctl Key or Keychain. It can be +// dereferenced by calling the Get() method. +type Reference struct { + // Id is the kernel key or keychain identifier referenced. + Id int32 + + info *Info + parent keyId +} + +// Information about a keyctl reference as returned by ref.Info() +type Info struct { + Type, Name string + Uid, Gid int + Perm KeyPerm + + valid bool +} + +func getInfo(id keyId) (i Info, err error) { + var desc []byte + + if desc, err = describeKeyId(id); err != nil { + i.Name = err.Error() + return + } + + fields := bytes.Split(desc, []byte{';'}) + switch len(fields) { + case 5: + i.Name = string(fields[4]) + fallthrough + case 4: + p, _ := strconv.ParseUint(string(fields[3]), 16, 32) + i.Perm = KeyPerm(p) + fallthrough + case 3: + i.Gid, _ = strconv.Atoi(string(fields[2])) + fallthrough + case 2: + i.Uid, _ = strconv.Atoi(string(fields[1])) + fallthrough + case 1: + if i.Type = string(fields[0]); i.Type == "user" { + i.Type = "key" + } + i.valid = true + default: + panic("invalid field count from kernel keyctl describe sysctl") + } + return +} + +// Returns permissions in symbolic format. +func (i Info) Permissions() string { + if i.Uid == os.Geteuid() { + return encodePerms(uint8(i.Perm >> KeyPerm(16))) + } else { + fsgid, err := getfsgid() + if (err == nil && i.Gid == int(fsgid)) || i.Gid == os.Getegid() { + return encodePerms(uint8(i.Perm >> KeyPerm(8))) + } + } + return encodePerms(uint8(i.Perm)) +} + +// Return Information about a keyctl reference. +func (r *Reference) Info() (i Info, err error) { + if r.info == nil { + i, err = getInfo(keyId(r.Id)) + r.info = &i + return + } + + return *r.info, err +} + +// Returns true if the Info fetched by ref.Info() is valid. +func (i Info) Valid() bool { + return i.valid +} + +// Returns true if the keyctl reference is valid. Refererences can become +// invalid if they have expired since the reference was created. +func (r *Reference) Valid() bool { + if r.info == nil { + r.Info() + } + return r.info.valid +} + +// Loads the referenced keyctl object, which must either be a key or a +// keyring otherwise ErrUnsupportedKeyType will be returned. +func (r *Reference) Get() (Id, error) { + if r.info == nil { + _, err := r.Info() + if err != nil { + return nil, err + } + } + + if !r.info.valid { + return nil, ErrInvalidReference + } + + switch r.info.Type { + case "key", "big_key": + return &Key{Name: r.info.Name, id: keyId(r.Id), ring: r.parent}, nil + case "keyring": + ring := &keyring{id: keyId(r.Id)} + if r.Id > 0 && r.info.Name != "" { + return &namedKeyring{ + keyring: ring, + parent: r.parent, + name: r.info.Name, + }, nil + } + return ring, nil + default: + return nil, ErrUnsupportedKeyType + } +} + +// List the contents of a keyring. Each contained object is represented by a +// Reference struct. Addl information is available by calling ref.Info(), and +// contained objects which are keys or subordinate keyrings can be fetched by +// calling ref.Get() +func ListKeyring(kr Keyring) ([]Reference, error) { + id := keyId(kr.Id()) + keys, err := listKeys(id) + if err != nil { + return nil, err + } + + refs := make([]Reference, len(keys)) + + for i, k := range keys { + refs[i].Id, refs[i].parent = int32(k), id + } + + return refs, nil +} diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux.go b/vendor/github.com/jsipprell/keyctl/sys_linux.go new file mode 100644 index 00000000..0c4c1943 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux.go @@ -0,0 +1,296 @@ +package keyctl + +import ( + "syscall" + "unsafe" +) + +type keyctlCommand int + +type keyId int32 + +const ( + keySpecThreadKeyring keyId = -1 + keySpecProcessKeyring keyId = -2 + keySpecSessionKeyring keyId = -3 + keySpecUserKeyring keyId = -4 + keySpecUserSessionKeyring keyId = -5 + keySpecGroupKeyring keyId = -6 + keySpecReqKeyAuthKey keyId = -7 +) + +const ( + keyctlGetKeyringId keyctlCommand = iota + keyctlJoinSessionKeyring + keyctlUpdate + keyctlRevoke + keyctlChown + keyctlSetPerm + keyctlDescribe + keyctlClear + keyctlLink + keyctlUnlink + keyctlSearch + keyctlRead + keyctlInstantiate + keyctlNegate + keyctlSetReqKeyKeyring + keyctlSetTimeout + keyctlAssumeAuthority +) + +var debugSyscalls bool + +func (id keyId) Id() int32 { + return int32(id) +} + +func (cmd keyctlCommand) String() string { + switch cmd { + case keyctlGetKeyringId: + return "keyctlGetKeyringId" + case keyctlJoinSessionKeyring: + return "keyctlJoinSessionKeyring" + case keyctlUpdate: + return "keyctlUpdate" + case keyctlRevoke: + return "keyctlRevoke" + case keyctlChown: + return "keyctlChown" + case keyctlSetPerm: + return "keyctlSetPerm" + case keyctlDescribe: + return "keyctlDescribe" + case keyctlClear: + return "keyctlClear" + case keyctlLink: + return "keyctlLink" + case keyctlUnlink: + return "keyctlUnlink" + case keyctlSearch: + return "keyctlSearch" + case keyctlRead: + return "keyctlRead" + case keyctlInstantiate: + return "keyctlInstantiate" + case keyctlNegate: + return "keyctlNegate" + case keyctlSetReqKeyKeyring: + return "keyctlSetReqKeyKeyring" + case keyctlSetTimeout: + return "keyctlSetTimeout" + case keyctlAssumeAuthority: + return "keyctlAssumeAuthority" + } + panic("bad arg") +} + +func keyctl_SetTimeout(id keyId, nsecs uint) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlSetTimeout), uintptr(id), uintptr(nsecs)) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_Read(id keyId, b *byte, size int) (int32, error) { + v1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlRead), uintptr(id), uintptr(unsafe.Pointer(b)), uintptr(size), 0, 0) + if errno != 0 { + return -1, errno + } + + return int32(v1), nil +} + +func keyctl_Link(id, ring keyId) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlLink), uintptr(id), uintptr(ring)) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_Unlink(id, ring keyId) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlUnlink), uintptr(id), uintptr(ring)) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_Chown(id keyId, user, group int) error { + _, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlChown), uintptr(id), uintptr(user), uintptr(group), 0, 0) + if errno != 0 { + return errno + } + return nil +} + +func keyctl_SetPerm(id keyId, perm uint32) error { + _, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlSetPerm), uintptr(id), uintptr(perm)) + if errno != 0 { + return errno + } + return nil +} + +func add_key(keyType, keyDesc string, payload []byte, id int32) (int32, error) { + var ( + err error + errno syscall.Errno + b1, b2 *byte + r1 uintptr + pptr unsafe.Pointer + ) + + if b1, err = syscall.BytePtrFromString(keyType); err != nil { + return 0, err + } + + if b2, err = syscall.BytePtrFromString(keyDesc); err != nil { + return 0, err + } + + if len(payload) > 0 { + pptr = unsafe.Pointer(&payload[0]) + } + r1, _, errno = syscall.Syscall6(syscall_add_key, + uintptr(unsafe.Pointer(b1)), + uintptr(unsafe.Pointer(b2)), + uintptr(pptr), + uintptr(len(payload)), + uintptr(id), + 0) + + if errno != 0 { + err = errno + return 0, err + } + return int32(r1), nil +} + +func getfsgid() (int32, error) { + var ( + a1 int32 + err error + errno syscall.Errno + r1 uintptr + ) + + a1 = -1 + if r1, _, errno = syscall.Syscall(syscall_setfsgid, uintptr(a1), 0, 0); errno != 0 { + err = errno + return int32(-1), err + } + return int32(r1), nil +} + +func newKeyring(id keyId) (*keyring, error) { + r1, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlGetKeyringId), uintptr(id), uintptr(1)) + if errno != 0 { + return nil, errno + } + + if id >= 0 { + id = keyId(r1) + } + return &keyring{id: id}, nil +} + +func createKeyring(parent keyId, name string) (*keyring, error) { + id, err := add_key("keyring", name, nil, int32(parent)) + if err != nil { + return nil, err + } + + return &keyring{id: keyId(id)}, nil +} + +func searchKeyring(id keyId, name, keyType string) (keyId, error) { + var ( + b1, b2 *byte + err error + ) + + if b1, err = syscall.BytePtrFromString(keyType); err != nil { + return 0, err + } + if b2, err = syscall.BytePtrFromString(name); err != nil { + return 0, err + } + r1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlSearch), uintptr(id), uintptr(unsafe.Pointer(b1)), uintptr(unsafe.Pointer(b2)), 0, 0) + if errno != 0 { + err = errno + } + return keyId(r1), err +} + +func describeKeyId(id keyId) ([]byte, error) { + var ( + b1 []byte + size, sizeRead int + ) + + b1 = make([]byte, 64) + size = len(b1) + sizeRead = size + 1 + for sizeRead > size { + r1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlDescribe), uintptr(id), uintptr(unsafe.Pointer(&b1[0])), uintptr(size), 0, 0) + if errno != 0 { + return nil, errno + } + if sizeRead = int(r1); sizeRead > size { + b1 = make([]byte, sizeRead) + size = sizeRead + sizeRead++ + } else { + size = sizeRead + } + } + + return b1[:size-1], nil +} + +func listKeys(id keyId) ([]keyId, error) { + var ( + b1 []byte + size, sizeRead int + ) + + bsz := 4 + b1 = make([]byte, 16*bsz) + size = len(b1) + sizeRead = size + 1 + for sizeRead > size { + r1, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlRead), uintptr(id), uintptr(unsafe.Pointer(&b1[0])), uintptr(size), 0, 0) + if errno != 0 { + return nil, errno + } + + if sizeRead = int(r1); sizeRead > size { + b1 = make([]byte, sizeRead) + size = sizeRead + sizeRead++ + } else { + size = sizeRead + } + } + keys := make([]keyId, size/bsz) + for i := range keys { + keys[i] = *((*keyId)(unsafe.Pointer(&b1[i*bsz]))) + } + + return keys, nil +} + +func updateKey(id keyId, payload []byte) error { + size := len(payload) + if size == 0 { + payload = make([]byte, 1) + } + _, _, errno := syscall.Syscall6(syscall_keyctl, uintptr(keyctlUpdate), uintptr(id), uintptr(unsafe.Pointer(&payload[0])), uintptr(size), 0, 0) + if errno != 0 { + return errno + } + return nil +} diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux_386.go b/vendor/github.com/jsipprell/keyctl/sys_linux_386.go new file mode 100644 index 00000000..0442bee5 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux_386.go @@ -0,0 +1,7 @@ +package keyctl + +const ( + syscall_keyctl uintptr = 288 + syscall_add_key uintptr = 286 + syscall_setfsgid uintptr = 139 +) diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go b/vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go new file mode 100644 index 00000000..f36f316b --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux_amd64.go @@ -0,0 +1,7 @@ +package keyctl + +const ( + syscall_keyctl uintptr = 250 + syscall_add_key uintptr = 248 + syscall_setfsgid uintptr = 123 +) diff --git a/vendor/github.com/jsipprell/keyctl/sys_linux_arm.go b/vendor/github.com/jsipprell/keyctl/sys_linux_arm.go new file mode 100644 index 00000000..0542a614 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/sys_linux_arm.go @@ -0,0 +1,7 @@ +package keyctl + +const ( + syscall_keyctl uintptr = 311 + syscall_add_key uintptr = 309 + syscall_setfsgid uintptr = 139 +) diff --git a/vendor/github.com/jsipprell/keyctl/writer.go b/vendor/github.com/jsipprell/keyctl/writer.go new file mode 100644 index 00000000..35736889 --- /dev/null +++ b/vendor/github.com/jsipprell/keyctl/writer.go @@ -0,0 +1,70 @@ +package keyctl + +import ( + "bytes" + "errors" + "io" +) + +type Flusher interface { + io.Writer + io.Closer + Flush() error +} + +// Error returned when attempting to close or flush an already closed stream +var ErrStreamClosed = errors.New("keyctl write stream closed") + +type writer struct { + *bytes.Buffer + key Id + name string + closed bool +} + +// Close a stream writer. *This or Flush() MUST be called in order to flush +// the key value to the kernel. +func (w *writer) Close() error { + if !w.closed { + defer setClosed(w) + return w.Flush() + } + return ErrStreamClosed +} + +// Flush the current stream writer buffer key data to the kernel. New writes +// after this will need to be re-flushed or have Close() called. +func (w *writer) Flush() (err error) { + if !w.closed { + switch t := w.key.(type) { + case Keyring: + var key Id + key, err = t.Add(w.name, w.Bytes()) + if err == nil { + w.key = key + } + case *Key: + err = updateKey(t.id, w.Bytes()) + if err == nil && t.ttl != 0 { + err = t.ExpireAfter(uint(t.ttl.Seconds())) + } + } + return + } + return ErrStreamClosed +} + +func setClosed(w *writer) { + w.closed = true +} + +// Create a new stream writer to write key data to. The writer MUST Close() or +// Flush() the stream before the data will be flushed to the kernel. +func NewWriter(key *Key) Flusher { + return &writer{Buffer: bytes.NewBuffer(make([]byte, 0, 1024)), key: key} +} + +// Create a new key and stream writer with a given name on an open keyring. +func CreateWriter(name string, ring Keyring) (Flusher, error) { + return &writer{Buffer: bytes.NewBuffer(make([]byte, 0, 1024)), key: ring, name: name}, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 20b4760a..42c9df81 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,6 +1,9 @@ # github.com/danieljoos/wincred v1.2.1 ## explicit; go 1.18 github.com/danieljoos/wincred +# github.com/jsipprell/keyctl v1.0.3 +## explicit +github.com/jsipprell/keyctl # golang.org/x/sys v0.15.0 ## explicit; go 1.18 golang.org/x/sys/windows