sid.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package mstypes
  2. import (
  3. "encoding/binary"
  4. "encoding/hex"
  5. "fmt"
  6. "gopkg.in/jcmturner/gokrb5.v2/ndr"
  7. )
  8. // RPCSID implements https://msdn.microsoft.com/en-us/library/cc230364.aspx
  9. type RPCSID struct {
  10. Revision uint8 // An 8-bit unsigned integer that specifies the revision level of the SID. This value MUST be set to 0x01.
  11. SubAuthorityCount uint8 // An 8-bit unsigned integer that specifies the number of elements in the SubAuthority array. The maximum number of elements allowed is 15.
  12. IdentifierAuthority RPCSIDIdentifierAuthority // An RPC_SID_IDENTIFIER_AUTHORITY structure that indicates the authority under which the SID was created. It describes the entity that created the SID. The Identifier Authority value {0,0,0,0,0,5} denotes SIDs created by the NT SID authority.
  13. SubAuthority []uint32 // A variable length array of unsigned 32-bit integers that uniquely identifies a principal relative to the IdentifierAuthority. Its length is determined by SubAuthorityCount.
  14. }
  15. // RPCSIDIdentifierAuthority implements https://msdn.microsoft.com/en-us/library/cc230372.aspx
  16. type RPCSIDIdentifierAuthority struct {
  17. Value []byte // 6 bytes
  18. }
  19. // ReadRPCSID reads a RPC_SID from the bytes slice.
  20. func ReadRPCSID(b *[]byte, p *int, e *binary.ByteOrder) (RPCSID, error) {
  21. size := int(ndr.ReadUint32(b, p, e)) // This is part of the NDR encoding rather than the data type.
  22. r := ndr.ReadUint8(b, p)
  23. if r != uint8(1) {
  24. return RPCSID{}, ndr.Malformed{EText: fmt.Sprintf("SID revision value read as %d when it must be 1", r)}
  25. }
  26. c := ndr.ReadUint8(b, p)
  27. a := ReadRPCSIDIdentifierAuthority(b, p, e)
  28. s := make([]uint32, c, c)
  29. if size != len(s) {
  30. return RPCSID{}, ndr.Malformed{EText: fmt.Sprintf("Number of elements (%d) within SID in the byte stream does not equal the SubAuthorityCount (%d)", size, c)}
  31. }
  32. for i := 0; i < len(s); i++ {
  33. s[i] = ndr.ReadUint32(b, p, e)
  34. }
  35. return RPCSID{
  36. Revision: r,
  37. SubAuthorityCount: c,
  38. IdentifierAuthority: a,
  39. SubAuthority: s,
  40. }, nil
  41. }
  42. // ReadRPCSIDIdentifierAuthority reads a RPC_SIDIdentifierAuthority from the bytes slice.
  43. func ReadRPCSIDIdentifierAuthority(b *[]byte, p *int, e *binary.ByteOrder) RPCSIDIdentifierAuthority {
  44. return RPCSIDIdentifierAuthority{
  45. Value: ndr.ReadBytes(b, p, 6, e),
  46. }
  47. }
  48. // ToString returns the string representation of the RPC_SID.
  49. func (s *RPCSID) ToString() string {
  50. var str string
  51. b := append(make([]byte, 2, 2), s.IdentifierAuthority.Value...)
  52. // For a strange reason this is read big endian: https://msdn.microsoft.com/en-us/library/dd302645.aspx
  53. i := binary.BigEndian.Uint64(b)
  54. if i >= 4294967296 {
  55. str = fmt.Sprintf("S-1-0x%s", hex.EncodeToString(s.IdentifierAuthority.Value))
  56. } else {
  57. str = fmt.Sprintf("S-1-%d", i)
  58. }
  59. for _, sub := range s.SubAuthority {
  60. str = fmt.Sprintf("%s-%d", str, sub)
  61. }
  62. return str
  63. }