Home | History | Annotate | Download | only in syscall
      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 	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 UTF16ToString((*[256]uint16)(unsafe.Pointer(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 
    225 	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
    226 		TOKEN_ASSIGN_PRIMARY |
    227 		TOKEN_DUPLICATE |
    228 		TOKEN_IMPERSONATE |
    229 		TOKEN_QUERY |
    230 		TOKEN_QUERY_SOURCE |
    231 		TOKEN_ADJUST_PRIVILEGES |
    232 		TOKEN_ADJUST_GROUPS |
    233 		TOKEN_ADJUST_DEFAULT
    234 	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
    235 	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
    236 		TOKEN_ADJUST_PRIVILEGES |
    237 		TOKEN_ADJUST_GROUPS |
    238 		TOKEN_ADJUST_DEFAULT
    239 	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
    240 )
    241 
    242 const (
    243 	// do not reorder
    244 	TokenUser = 1 + iota
    245 	TokenGroups
    246 	TokenPrivileges
    247 	TokenOwner
    248 	TokenPrimaryGroup
    249 	TokenDefaultDacl
    250 	TokenSource
    251 	TokenType
    252 	TokenImpersonationLevel
    253 	TokenStatistics
    254 	TokenRestrictedSids
    255 	TokenSessionId
    256 	TokenGroupsAndPrivileges
    257 	TokenSessionReference
    258 	TokenSandBoxInert
    259 	TokenAuditPolicy
    260 	TokenOrigin
    261 	TokenElevationType
    262 	TokenLinkedToken
    263 	TokenElevation
    264 	TokenHasRestrictions
    265 	TokenAccessInformation
    266 	TokenVirtualizationAllowed
    267 	TokenVirtualizationEnabled
    268 	TokenIntegrityLevel
    269 	TokenUIAccess
    270 	TokenMandatoryPolicy
    271 	TokenLogonSid
    272 	MaxTokenInfoClass
    273 )
    274 
    275 type SIDAndAttributes struct {
    276 	Sid        *SID
    277 	Attributes uint32
    278 }
    279 
    280 type Tokenuser struct {
    281 	User SIDAndAttributes
    282 }
    283 
    284 type Tokenprimarygroup struct {
    285 	PrimaryGroup *SID
    286 }
    287 
    288 //sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
    289 //sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
    290 //sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
    291 
    292 // An access token contains the security information for a logon session.
    293 // The system creates an access token when a user logs on, and every
    294 // process executed on behalf of the user has a copy of the token.
    295 // The token identifies the user, the user's groups, and the user's
    296 // privileges. The system uses the token to control access to securable
    297 // objects and to control the ability of the user to perform various
    298 // system-related operations on the local computer.
    299 type Token Handle
    300 
    301 // OpenCurrentProcessToken opens the access token
    302 // associated with current process.
    303 func OpenCurrentProcessToken() (Token, error) {
    304 	p, e := GetCurrentProcess()
    305 	if e != nil {
    306 		return 0, e
    307 	}
    308 	var t Token
    309 	e = OpenProcessToken(p, TOKEN_QUERY, &t)
    310 	if e != nil {
    311 		return 0, e
    312 	}
    313 	return t, nil
    314 }
    315 
    316 // Close releases access to access token.
    317 func (t Token) Close() error {
    318 	return CloseHandle(Handle(t))
    319 }
    320 
    321 // getInfo retrieves a specified type of information about an access token.
    322 func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
    323 	n := uint32(initSize)
    324 	for {
    325 		b := make([]byte, n)
    326 		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
    327 		if e == nil {
    328 			return unsafe.Pointer(&b[0]), nil
    329 		}
    330 		if e != ERROR_INSUFFICIENT_BUFFER {
    331 			return nil, e
    332 		}
    333 		if n <= uint32(len(b)) {
    334 			return nil, e
    335 		}
    336 	}
    337 }
    338 
    339 // GetTokenUser retrieves access token t user account information.
    340 func (t Token) GetTokenUser() (*Tokenuser, error) {
    341 	i, e := t.getInfo(TokenUser, 50)
    342 	if e != nil {
    343 		return nil, e
    344 	}
    345 	return (*Tokenuser)(i), nil
    346 }
    347 
    348 // GetTokenPrimaryGroup retrieves access token t primary group information.
    349 // A pointer to a SID structure representing a group that will become
    350 // the primary group of any objects created by a process using this access token.
    351 func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
    352 	i, e := t.getInfo(TokenPrimaryGroup, 50)
    353 	if e != nil {
    354 		return nil, e
    355 	}
    356 	return (*Tokenprimarygroup)(i), nil
    357 }
    358 
    359 // GetUserProfileDirectory retrieves path to the
    360 // root directory of the access token t user's profile.
    361 func (t Token) GetUserProfileDirectory() (string, error) {
    362 	n := uint32(100)
    363 	for {
    364 		b := make([]uint16, n)
    365 		e := GetUserProfileDirectory(t, &b[0], &n)
    366 		if e == nil {
    367 			return UTF16ToString(b), nil
    368 		}
    369 		if e != ERROR_INSUFFICIENT_BUFFER {
    370 			return "", e
    371 		}
    372 		if n <= uint32(len(b)) {
    373 			return "", e
    374 		}
    375 	}
    376 }
    377