Source file src/syscall/security_windows.go

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package syscall
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  const (
    12  	STANDARD_RIGHTS_REQUIRED = 0xf0000
    13  	STANDARD_RIGHTS_READ     = 0x20000
    14  	STANDARD_RIGHTS_WRITE    = 0x20000
    15  	STANDARD_RIGHTS_EXECUTE  = 0x20000
    16  	STANDARD_RIGHTS_ALL      = 0x1F0000
    17  )
    18  
    19  const (
    20  	NameUnknown          = 0
    21  	NameFullyQualifiedDN = 1
    22  	NameSamCompatible    = 2
    23  	NameDisplay          = 3
    24  	NameUniqueId         = 6
    25  	NameCanonical        = 7
    26  	NameUserPrincipal    = 8
    27  	NameCanonicalEx      = 9
    28  	NameServicePrincipal = 10
    29  	NameDnsDomain        = 12
    30  )
    31  
    32  // This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
    33  // https://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
    34  //sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
    35  //sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
    36  
    37  // TranslateAccountName converts a directory service
    38  // object name from one format to another.
    39  func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
    40  	u, e := UTF16PtrFromString(username)
    41  	if e != nil {
    42  		return "", e
    43  	}
    44  	n := uint32(50)
    45  	for {
    46  		b := make([]uint16, n)
    47  		e = TranslateName(u, from, to, &b[0], &n)
    48  		if e == nil {
    49  			return UTF16ToString(b[:n]), nil
    50  		}
    51  		if e != ERROR_INSUFFICIENT_BUFFER {
    52  			return "", e
    53  		}
    54  		if n <= uint32(len(b)) {
    55  			return "", e
    56  		}
    57  	}
    58  }
    59  
    60  const (
    61  	// do not reorder
    62  	NetSetupUnknownStatus = iota
    63  	NetSetupUnjoined
    64  	NetSetupWorkgroupName
    65  	NetSetupDomainName
    66  )
    67  
    68  type UserInfo10 struct {
    69  	Name       *uint16
    70  	Comment    *uint16
    71  	UsrComment *uint16
    72  	FullName   *uint16
    73  }
    74  
    75  //sys	NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
    76  //sys	NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
    77  //sys	NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
    78  
    79  const (
    80  	// do not reorder
    81  	SidTypeUser = 1 + iota
    82  	SidTypeGroup
    83  	SidTypeDomain
    84  	SidTypeAlias
    85  	SidTypeWellKnownGroup
    86  	SidTypeDeletedAccount
    87  	SidTypeInvalid
    88  	SidTypeUnknown
    89  	SidTypeComputer
    90  	SidTypeLabel
    91  )
    92  
    93  //sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
    94  //sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
    95  //sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
    96  //sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
    97  //sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
    98  //sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
    99  
   100  // The security identifier (SID) structure is a variable-length
   101  // structure used to uniquely identify users or groups.
   102  type SID struct{}
   103  
   104  // StringToSid converts a string-format security identifier
   105  // sid into a valid, functional sid.
   106  func StringToSid(s string) (*SID, error) {
   107  	var sid *SID
   108  	p, e := UTF16PtrFromString(s)
   109  	if e != nil {
   110  		return nil, e
   111  	}
   112  	e = ConvertStringSidToSid(p, &sid)
   113  	if e != nil {
   114  		return nil, e
   115  	}
   116  	defer LocalFree((Handle)(unsafe.Pointer(sid)))
   117  	return sid.Copy()
   118  }
   119  
   120  // LookupSID retrieves a security identifier sid for the account
   121  // and the name of the domain on which the account was found.
   122  // System specify target computer to search.
   123  func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
   124  	if len(account) == 0 {
   125  		return nil, "", 0, EINVAL
   126  	}
   127  	acc, e := UTF16PtrFromString(account)
   128  	if e != nil {
   129  		return nil, "", 0, e
   130  	}
   131  	var sys *uint16
   132  	if len(system) > 0 {
   133  		sys, e = UTF16PtrFromString(system)
   134  		if e != nil {
   135  			return nil, "", 0, e
   136  		}
   137  	}
   138  	n := uint32(50)
   139  	dn := uint32(50)
   140  	for {
   141  		b := make([]byte, n)
   142  		db := make([]uint16, dn)
   143  		sid = (*SID)(unsafe.Pointer(&b[0]))
   144  		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
   145  		if e == nil {
   146  			return sid, UTF16ToString(db), accType, nil
   147  		}
   148  		if e != ERROR_INSUFFICIENT_BUFFER {
   149  			return nil, "", 0, e
   150  		}
   151  		if n <= uint32(len(b)) {
   152  			return nil, "", 0, e
   153  		}
   154  	}
   155  }
   156  
   157  // String converts sid to a string format
   158  // suitable for display, storage, or transmission.
   159  func (sid *SID) String() (string, error) {
   160  	var s *uint16
   161  	e := ConvertSidToStringSid(sid, &s)
   162  	if e != nil {
   163  		return "", e
   164  	}
   165  	defer LocalFree((Handle)(unsafe.Pointer(s)))
   166  	return utf16PtrToString(s), nil
   167  }
   168  
   169  // Len returns the length, in bytes, of a valid security identifier sid.
   170  func (sid *SID) Len() int {
   171  	return int(GetLengthSid(sid))
   172  }
   173  
   174  // Copy creates a duplicate of security identifier sid.
   175  func (sid *SID) Copy() (*SID, error) {
   176  	b := make([]byte, sid.Len())
   177  	sid2 := (*SID)(unsafe.Pointer(&b[0]))
   178  	e := CopySid(uint32(len(b)), sid2, sid)
   179  	if e != nil {
   180  		return nil, e
   181  	}
   182  	return sid2, nil
   183  }
   184  
   185  // LookupAccount retrieves the name of the account for this sid
   186  // and the name of the first domain on which this sid is found.
   187  // System specify target computer to search for.
   188  func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
   189  	var sys *uint16
   190  	if len(system) > 0 {
   191  		sys, err = UTF16PtrFromString(system)
   192  		if err != nil {
   193  			return "", "", 0, err
   194  		}
   195  	}
   196  	n := uint32(50)
   197  	dn := uint32(50)
   198  	for {
   199  		b := make([]uint16, n)
   200  		db := make([]uint16, dn)
   201  		e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
   202  		if e == nil {
   203  			return UTF16ToString(b), UTF16ToString(db), accType, nil
   204  		}
   205  		if e != ERROR_INSUFFICIENT_BUFFER {
   206  			return "", "", 0, e
   207  		}
   208  		if n <= uint32(len(b)) {
   209  			return "", "", 0, e
   210  		}
   211  	}
   212  }
   213  
   214  const (
   215  	// do not reorder
   216  	TOKEN_ASSIGN_PRIMARY = 1 << iota
   217  	TOKEN_DUPLICATE
   218  	TOKEN_IMPERSONATE
   219  	TOKEN_QUERY
   220  	TOKEN_QUERY_SOURCE
   221  	TOKEN_ADJUST_PRIVILEGES
   222  	TOKEN_ADJUST_GROUPS
   223  	TOKEN_ADJUST_DEFAULT
   224  	TOKEN_ADJUST_SESSIONID
   225  
   226  	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
   227  		TOKEN_ASSIGN_PRIMARY |
   228  		TOKEN_DUPLICATE |
   229  		TOKEN_IMPERSONATE |
   230  		TOKEN_QUERY |
   231  		TOKEN_QUERY_SOURCE |
   232  		TOKEN_ADJUST_PRIVILEGES |
   233  		TOKEN_ADJUST_GROUPS |
   234  		TOKEN_ADJUST_DEFAULT |
   235  		TOKEN_ADJUST_SESSIONID
   236  	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
   237  	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
   238  		TOKEN_ADJUST_PRIVILEGES |
   239  		TOKEN_ADJUST_GROUPS |
   240  		TOKEN_ADJUST_DEFAULT
   241  	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
   242  )
   243  
   244  const (
   245  	// do not reorder
   246  	TokenUser = 1 + iota
   247  	TokenGroups
   248  	TokenPrivileges
   249  	TokenOwner
   250  	TokenPrimaryGroup
   251  	TokenDefaultDacl
   252  	TokenSource
   253  	TokenType
   254  	TokenImpersonationLevel
   255  	TokenStatistics
   256  	TokenRestrictedSids
   257  	TokenSessionId
   258  	TokenGroupsAndPrivileges
   259  	TokenSessionReference
   260  	TokenSandBoxInert
   261  	TokenAuditPolicy
   262  	TokenOrigin
   263  	TokenElevationType
   264  	TokenLinkedToken
   265  	TokenElevation
   266  	TokenHasRestrictions
   267  	TokenAccessInformation
   268  	TokenVirtualizationAllowed
   269  	TokenVirtualizationEnabled
   270  	TokenIntegrityLevel
   271  	TokenUIAccess
   272  	TokenMandatoryPolicy
   273  	TokenLogonSid
   274  	MaxTokenInfoClass
   275  )
   276  
   277  type SIDAndAttributes struct {
   278  	Sid        *SID
   279  	Attributes uint32
   280  }
   281  
   282  type Tokenuser struct {
   283  	User SIDAndAttributes
   284  }
   285  
   286  type Tokenprimarygroup struct {
   287  	PrimaryGroup *SID
   288  }
   289  
   290  //sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
   291  //sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
   292  //sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
   293  //sys	getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
   294  
   295  // An access token contains the security information for a logon session.
   296  // The system creates an access token when a user logs on, and every
   297  // process executed on behalf of the user has a copy of the token.
   298  // The token identifies the user, the user's groups, and the user's
   299  // privileges. The system uses the token to control access to securable
   300  // objects and to control the ability of the user to perform various
   301  // system-related operations on the local computer.
   302  type Token Handle
   303  
   304  // OpenCurrentProcessToken opens the access token
   305  // associated with current process.
   306  func OpenCurrentProcessToken() (Token, error) {
   307  	p, e := GetCurrentProcess()
   308  	if e != nil {
   309  		return 0, e
   310  	}
   311  	var t Token
   312  	e = OpenProcessToken(p, TOKEN_QUERY, &t)
   313  	if e != nil {
   314  		return 0, e
   315  	}
   316  	return t, nil
   317  }
   318  
   319  // Close releases access to access token.
   320  func (t Token) Close() error {
   321  	return CloseHandle(Handle(t))
   322  }
   323  
   324  // getInfo retrieves a specified type of information about an access token.
   325  func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
   326  	n := uint32(initSize)
   327  	for {
   328  		b := make([]byte, n)
   329  		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
   330  		if e == nil {
   331  			return unsafe.Pointer(&b[0]), nil
   332  		}
   333  		if e != ERROR_INSUFFICIENT_BUFFER {
   334  			return nil, e
   335  		}
   336  		if n <= uint32(len(b)) {
   337  			return nil, e
   338  		}
   339  	}
   340  }
   341  
   342  // GetTokenUser retrieves access token t user account information.
   343  func (t Token) GetTokenUser() (*Tokenuser, error) {
   344  	i, e := t.getInfo(TokenUser, 50)
   345  	if e != nil {
   346  		return nil, e
   347  	}
   348  	return (*Tokenuser)(i), nil
   349  }
   350  
   351  // GetTokenPrimaryGroup retrieves access token t primary group information.
   352  // A pointer to a SID structure representing a group that will become
   353  // the primary group of any objects created by a process using this access token.
   354  func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
   355  	i, e := t.getInfo(TokenPrimaryGroup, 50)
   356  	if e != nil {
   357  		return nil, e
   358  	}
   359  	return (*Tokenprimarygroup)(i), nil
   360  }
   361  
   362  // GetUserProfileDirectory retrieves path to the
   363  // root directory of the access token t user's profile.
   364  func (t Token) GetUserProfileDirectory() (string, error) {
   365  	n := uint32(100)
   366  	for {
   367  		b := make([]uint16, n)
   368  		e := GetUserProfileDirectory(t, &b[0], &n)
   369  		if e == nil {
   370  			return UTF16ToString(b), nil
   371  		}
   372  		if e != ERROR_INSUFFICIENT_BUFFER {
   373  			return "", e
   374  		}
   375  		if n <= uint32(len(b)) {
   376  			return "", e
   377  		}
   378  	}
   379  }
   380  

View as plain text