Git Product home page Git Product logo

keyctl's Introduction

GoDoc Build Status

keyctl

A native Go API for the security key management system (aka "keyrings") found in Linux 2.6+

The keyctl interface is nominally provided by three or so Linux-specific syscalls, however it is almost always wrapped in a library named libkeyutils.so.

This package interacts directly with the syscall interface and does not require CGO for linkage to the helper library provided on most systems.

Example Usages

To access the default session keyring (and create it if it doesn't exist)

package main
   
import (
  "log"
  "github.com/jsipprell/keyctl"
)
    
func main() {
  keyring, err := keyctl.SessionKeyring()
  if err != nil {
    log.Fatal(err)
  }
      
  // default timeout of 10 seconds for new or updated keys
  keyring.SetDefaultTimeout(10)
  secureData := []byte{1,2,3,4}
  id, err := keyring.Add("some-data", secureData)
  if err != nil {
    log.Fatal(err)
  }
  log.Printf("created session key id %v", id)
}

To search for an existing key by name:

package main

import (
  "log"
  "github.com/jsipprell/keyctl"
)

func main() {
  keyring, err := keyctl.SessionKeyring()
  if err != nil {
    log.Fatal(err)
  }
  key, err := keyring.Search("some-data")
  if err != nil {
    log.Fatal(err)
  }
 
  data, err := key.Get()
  if err != nil {
    log.Fatal(err)
  }
  log.Printf("secure data: %v\n", data)
}

keyctl's People

Contributors

chlunde avatar doclambda avatar hallyn avatar jsipprell avatar nonoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

keyctl's Issues

Update README to reflect Issue #6 ?

Issue#6 points to PR#7 which is merged. However, that PR by itself doesn't fix the problem, it only allows the problem to be fixed.

The README still shows adding a key to the usersession keychain, and reading it from that. The keyring.Add should be updated to reflect this comment: #6 (comment) . That is, add the key to the session keyring, set the perms, link to usersession and unlink from session.

Without that, subsequent key.Get() will fail. With that, it works.

undefined keyId

Golinter complains about the keyId type in key.go on line 11. I don't see the type definition for keyId anywhere else in the project? Can we just assume that this value should be an int32?

go get github.com/jsipprell/keyctl

github.com/jsipprell/keyctl

../../jsipprell/keyctl/key.go:11:11: undefined: keyId

Permission denied when extracting key data in UserSessionKeyring

When adding a key to the UserSessionKeyring and directly afterwards reading that key again, I get a permission denied trying to extract the data from the key. The following code triggers the issue

package main

import (
	"fmt"

	"github.com/jsipprell/keyctl"
)

func main() {
	name := "some-key"
	value := "lala"

	fmt.Println("accessing keyring")
	keyring, err := keyctl.UserSessionKeyring()
	if err != nil {
		panic(err)
	}

	fmt.Println("adding key")
	if _, err := keyring.Add(name, []byte(value)); err != nil {
		panic(err)
	}

	fmt.Println("searching key")
	key, err := keyring.Search(name)
	if err != nil {
		panic(err)
	}
	fmt.Printf("key: %v\n", key)

	fmt.Println("extracting key info")
	info, err := key.Info()
	if err != nil {
		panic(err)
	}
	fmt.Printf("key info: %v\n", info)

	fmt.Println("extracting key data")
	data, err := key.Get()
	if err != nil {
		panic(err)
	}
	fmt.Printf("key data: %v\n", data)
}

generating the following output

accessing keyring
adding key
searching key
key: &{some-key 814656017 -5 0 0}
extracting key info
key info: {key some-key <uid> <gid> alswrv-----v------------ true}
extracting key data
panic: permission denied

Interestingly when changing keyring, err := keyctl.UserSessionKeyring() to keyring, err := keyctl.SessionKeyring() the error goes away. If I generate the same key via commandline keyctl add user some-data foo @u, and omit the keyring.Add() call I can extract the data successfully even though the permissions look identical.

Any idea what's going on?

keyctl function appears unsafe with respect to garbage collection

( @jsipprell , I think I've understood the following correctly - but I'd be delighted to be proved wrong :-) )

Syscalls in Go require that we follow a rule in which the final cast of parameters, from unsafe.Pointer to uintptr, must happen inside the syscall. Otherwise, the garbage collector may move the pointer after we create the uintptr, but before we use it - leaving the uintptr still pointing to the old location where the object used to be.

So for instance sys_linux.add_key is fine, because although pptr is prepared earlier, it is not cast to uintprt until inside the argument list of the syscall function. So far, so good.

But.. the "keyctl" wrapper function is not doing the same thing. It relies on its callers to do the cast to uintptr. Therefore that cast does not happen inside the arg list of the syscall, and it's unsafe.

func keyctl(cmd keyctlCommand, args ...uintptr) (r1 int32, r2 int32, err error) {

This could, in theory, result in various types of undefined behavior when keyctl is used in an app with any non-trivial amount of garbage collector activity. I have not observed any such behavior in practice. (I just noticed the code structure while trying to debug something else).

Still Supported?

Just wondering if this library is still supported, I'm trying the examples in the README in Ubuntu 20 and they don't seem to work.

After running the first example, the second example (run from the same terminal) is unable to find the "some-data" key.

Golint is not very happy with code in this module

[vodolaz095@alarmpi keyctl]$ golint
key.go:7:1: comment on exported type Key should be of the form "Key ..." (with optional leading article)
key.go:18:1: comment on exported method Key.Id should be of the form "Id ..."
key.go:19:15: method Id should be ID
key.go:23:1: comment on exported method Key.ExpireAfter should be of the form "ExpireAfter ..."
key.go:30:1: comment on exported method Key.Info should be of the form "Info ..."
keyring.go:7:1: package comment should be of the form "Package keyctl ..."
keyring.go:10:1: comment on exported type Id should be of the form "Id ..." (with optional leading article)
keyring.go:11:6: type Id should be ID
keyring.go:18:1: comment on exported type Keyring should be of the form "Keyring ..." (with optional leading article)
keyring.go:26:1: comment on exported type NamedKeyring should be of the form "NamedKeyring ..." (with optional leading article)
keyring.go:37:2: struct field defaultTtl should be defaultTTL
keyring.go:50:20: method Id should be ID
keyring.go:96:1: comment on exported function SessionKeyring should be of the form "SessionKeyring ..."
keyring.go:101:1: comment on exported function UserSessionKeyring should be of the form "UserSessionKeyring ..."
keyring.go:107:1: comment on exported function GroupKeyring should be of the form "GroupKeyring ..."
keyring.go:112:1: comment on exported function ThreadKeyring should be of the form "ThreadKeyring ..."
keyring.go:117:1: comment on exported function ProcessKeyring should be of the form "ProcessKeyring ..."
keyring.go:122:1: comment on exported function CreateKeyring should be of the form "CreateKeyring ..."
keyring.go:132:2: var parentId should be parentID
keyring.go:155:1: comment on exported function OpenKeyring should be of the form "OpenKeyring ..."
keyring.go:158:2: var parentId should be parentID
keyring.go:171:1: comment on exported function SetKeyringTTL should be of the form "SetKeyringTTL ..."
keyring.go:192:1: comment on exported function UnlinkKeyring should be of the form "UnlinkKeyring ..."
perms.go:9:2: exported const PermOtherView should have comment (or a comment on this block) or be unexported
perms.go:18:2: exported const PermGroupView should have comment (or a comment on this block) or be unexported
perms.go:27:2: exported const PermUserView should have comment (or a comment on this block) or be unexported
perms.go:36:2: exported const PermProcessView should have comment (or a comment on this block) or be unexported
perms.go:45:2: exported const PermOtherAll should have comment (or a comment on this block) or be unexported
perms.go:69:1: comment on exported method KeyPerm.Process should be of the form "Process ..."
perms.go:74:1: comment on exported method KeyPerm.Group should be of the form "Group ..."
perms.go:79:1: comment on exported method KeyPerm.User should be of the form "User ..."
perms.go:84:1: comment on exported method KeyPerm.Other should be of the form "Other ..."
perms.go:93:1: comment on exported function Chown should be of the form "Chown ..."
perms.go:100:1: comment on exported function Chgrp should be of the form "Chgrp ..."
perms.go:107:1: comment on exported function SetPerm should be of the form "SetPerm ..."
reader.go:32:1: comment on exported function NewReader should be of the form "NewReader ..."
reader.go:38:1: comment on exported function OpenReader should be of the form "OpenReader ..."
ref.go:11:2: comment on exported var ErrUnsupportedKeyType should be of the form "ErrUnsupportedKeyType ..."
ref.go:14:2: comment on exported var ErrInvalidReference should be of the form "ErrInvalidReference ..."
ref.go:23:2: struct field Id should be ID
ref.go:29:1: comment on exported type Info should be of the form "Info ..." (with optional leading article)
ref.go:32:2: struct field Uid should be UID
ref.go:72:1: comment on exported method Info.Permissions should be of the form "Permissions ..."
ref.go:76:9: if block ends with a return statement, so drop this else and outdent its block
ref.go:85:1: comment on exported method Reference.Info should be of the form "Info ..."
ref.go:96:1: comment on exported method Info.Valid should be of the form "Valid ..."
ref.go:101:1: comment on exported method Reference.Valid should be of the form "Valid ..."
ref.go:110:1: comment on exported method Reference.Get should be of the form "Get ..."
ref.go:142:1: comment on exported function ListKeyring should be of the form "ListKeyring ..."
sys_linux.go:10:6: type keyId should be keyID
sys_linux.go:23:2: const keyctlGetKeyringId should be keyctlGetKeyringID
sys_linux.go:44:17: method Id should be ID
sys_linux.go:88:6: don't use underscores in Go names; func keyctl_SetTimeout should be keyctlSetTimeout
sys_linux.go:96:6: don't use underscores in Go names; func keyctl_Read should be keyctlRead
sys_linux.go:105:6: don't use underscores in Go names; func keyctl_Link should be keyctlLink
sys_linux.go:113:6: don't use underscores in Go names; func keyctl_Unlink should be keyctlUnlink
sys_linux.go:121:6: don't use underscores in Go names; func keyctl_Chown should be keyctlChown
sys_linux.go:129:6: don't use underscores in Go names; func keyctl_SetPerm should be keyctlSetPerm
sys_linux.go:137:6: don't use underscores in Go names; func add_key should be addKey
sys_linux.go:228:6: func describeKeyId should be describeKeyID
sys_linux_arm.go:4:2: don't use underscores in Go names; const syscall_keyctl should be syscallKeyctl
sys_linux_arm.go:5:2: don't use underscores in Go names; const syscall_add_key should be syscallAddKey
sys_linux_arm.go:6:2: don't use underscores in Go names; const syscall_setfsgid should be syscallSetfsgid
writer.go:9:6: exported type Flusher should have comment or be unexported
writer.go:15:1: comment on exported var ErrStreamClosed should be of the form "ErrStreamClosed ..."
writer.go:61:1: comment on exported function NewWriter should be of the form "NewWriter ..."
writer.go:67:1: comment on exported function CreateWriter should be of the form "CreateWriter ..."

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.