keyctl.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // +build linux
  2. package keyctl
  3. import (
  4. "fmt"
  5. "syscall"
  6. "strings"
  7. "strconv"
  8. "unsafe"
  9. )
  10. const KEYCTL_JOIN_SESSION_KEYRING = 1
  11. const KEYCTL_SETPERM = 5
  12. const KEYCTL_DESCRIBE = 6
  13. type KeySerial uint32
  14. func JoinSessionKeyring(name string) (KeySerial, error) {
  15. var _name *byte = nil
  16. var err error
  17. if len(name) > 0 {
  18. _name, err = syscall.BytePtrFromString(name)
  19. if err != nil {
  20. return KeySerial(0), err
  21. }
  22. }
  23. sessKeyId, _, errn := syscall.Syscall(syscall.SYS_KEYCTL, KEYCTL_JOIN_SESSION_KEYRING, uintptr(unsafe.Pointer(_name)), 0)
  24. if errn != 0 {
  25. return 0, fmt.Errorf("could not create session key: %v", errn)
  26. }
  27. return KeySerial(sessKeyId), nil
  28. }
  29. // modify permissions on a keyring by reading the current permissions,
  30. // anding the bits with the given mask (clearing permissions) and setting
  31. // additional permission bits
  32. func ModKeyringPerm(ringId KeySerial, mask, setbits uint32) error {
  33. dest := make([]byte, 1024)
  34. destBytes := unsafe.Pointer(&dest[0])
  35. if _, _, err := syscall.Syscall6(syscall.SYS_KEYCTL, uintptr(KEYCTL_DESCRIBE), uintptr(ringId), uintptr(destBytes), uintptr(len(dest)), 0, 0); err != 0 {
  36. return err
  37. }
  38. res := strings.Split(string(dest), ";")
  39. if len(res) < 5 {
  40. return fmt.Errorf("Destination buffer for key description is too small")
  41. }
  42. // parse permissions
  43. perm64, err := strconv.ParseUint(res[3], 16, 32)
  44. if err != nil {
  45. return err
  46. }
  47. perm := (uint32(perm64) & mask) | setbits
  48. if _, _, err := syscall.Syscall(syscall.SYS_KEYCTL, uintptr(KEYCTL_SETPERM), uintptr(ringId), uintptr(perm)); err != 0 {
  49. return err
  50. }
  51. return nil
  52. }