github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/syscall/security_windows.go (about)

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