github.com/as/shiny@v0.8.2/sys/windows/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 windows
     6  
     7  import (
     8  	"syscall"
     9  	"unsafe"
    10  )
    11  
    12  const (
    13  	STANDARD_RIGHTS_REQUIRED = 0xf0000
    14  	STANDARD_RIGHTS_READ     = 0x20000
    15  	STANDARD_RIGHTS_WRITE    = 0x20000
    16  	STANDARD_RIGHTS_EXECUTE  = 0x20000
    17  	STANDARD_RIGHTS_ALL      = 0x1F0000
    18  )
    19  
    20  const (
    21  	NameUnknown          = 0
    22  	NameFullyQualifiedDN = 1
    23  	NameSamCompatible    = 2
    24  	NameDisplay          = 3
    25  	NameUniqueId         = 6
    26  	NameCanonical        = 7
    27  	NameUserPrincipal    = 8
    28  	NameCanonicalEx      = 9
    29  	NameServicePrincipal = 10
    30  	NameDnsDomain        = 12
    31  )
    32  
    33  // This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
    34  // http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
    35  //sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
    36  //sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
    37  
    38  // TranslateAccountName converts a directory service
    39  // object name from one format to another.
    40  func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
    41  	u, e := UTF16PtrFromString(username)
    42  	if e != nil {
    43  		return "", e
    44  	}
    45  	n := uint32(50)
    46  	for {
    47  		b := make([]uint16, n)
    48  		e = TranslateName(u, from, to, &b[0], &n)
    49  		if e == nil {
    50  			return UTF16ToString(b[:n]), nil
    51  		}
    52  		if e != ERROR_INSUFFICIENT_BUFFER {
    53  			return "", e
    54  		}
    55  		if n <= uint32(len(b)) {
    56  			return "", e
    57  		}
    58  	}
    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  type SidIdentifierAuthority struct {
    95  	Value [6]byte
    96  }
    97  
    98  var (
    99  	SECURITY_NULL_SID_AUTHORITY        = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
   100  	SECURITY_WORLD_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
   101  	SECURITY_LOCAL_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
   102  	SECURITY_CREATOR_SID_AUTHORITY     = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
   103  	SECURITY_NON_UNIQUE_AUTHORITY      = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
   104  	SECURITY_NT_AUTHORITY              = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
   105  	SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
   106  )
   107  
   108  const (
   109  	SECURITY_NULL_RID                   = 0
   110  	SECURITY_WORLD_RID                  = 0
   111  	SECURITY_LOCAL_RID                  = 0
   112  	SECURITY_CREATOR_OWNER_RID          = 0
   113  	SECURITY_CREATOR_GROUP_RID          = 1
   114  	SECURITY_DIALUP_RID                 = 1
   115  	SECURITY_NETWORK_RID                = 2
   116  	SECURITY_BATCH_RID                  = 3
   117  	SECURITY_INTERACTIVE_RID            = 4
   118  	SECURITY_LOGON_IDS_RID              = 5
   119  	SECURITY_SERVICE_RID                = 6
   120  	SECURITY_LOCAL_SYSTEM_RID           = 18
   121  	SECURITY_BUILTIN_DOMAIN_RID         = 32
   122  	SECURITY_PRINCIPAL_SELF_RID         = 10
   123  	SECURITY_CREATOR_OWNER_SERVER_RID   = 0x2
   124  	SECURITY_CREATOR_GROUP_SERVER_RID   = 0x3
   125  	SECURITY_LOGON_IDS_RID_COUNT        = 0x3
   126  	SECURITY_ANONYMOUS_LOGON_RID        = 0x7
   127  	SECURITY_PROXY_RID                  = 0x8
   128  	SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
   129  	SECURITY_SERVER_LOGON_RID           = SECURITY_ENTERPRISE_CONTROLLERS_RID
   130  	SECURITY_AUTHENTICATED_USER_RID     = 0xb
   131  	SECURITY_RESTRICTED_CODE_RID        = 0xc
   132  	SECURITY_NT_NON_UNIQUE_RID          = 0x15
   133  )
   134  
   135  // Predefined domain-relative RIDs for local groups.
   136  // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
   137  const (
   138  	DOMAIN_ALIAS_RID_ADMINS                         = 0x220
   139  	DOMAIN_ALIAS_RID_USERS                          = 0x221
   140  	DOMAIN_ALIAS_RID_GUESTS                         = 0x222
   141  	DOMAIN_ALIAS_RID_POWER_USERS                    = 0x223
   142  	DOMAIN_ALIAS_RID_ACCOUNT_OPS                    = 0x224
   143  	DOMAIN_ALIAS_RID_SYSTEM_OPS                     = 0x225
   144  	DOMAIN_ALIAS_RID_PRINT_OPS                      = 0x226
   145  	DOMAIN_ALIAS_RID_BACKUP_OPS                     = 0x227
   146  	DOMAIN_ALIAS_RID_REPLICATOR                     = 0x228
   147  	DOMAIN_ALIAS_RID_RAS_SERVERS                    = 0x229
   148  	DOMAIN_ALIAS_RID_PREW2KCOMPACCESS               = 0x22a
   149  	DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS           = 0x22b
   150  	DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS      = 0x22c
   151  	DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
   152  	DOMAIN_ALIAS_RID_MONITORING_USERS               = 0X22e
   153  	DOMAIN_ALIAS_RID_LOGGING_USERS                  = 0x22f
   154  	DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS            = 0x230
   155  	DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS             = 0x231
   156  	DOMAIN_ALIAS_RID_DCOM_USERS                     = 0x232
   157  	DOMAIN_ALIAS_RID_IUSERS                         = 0x238
   158  	DOMAIN_ALIAS_RID_CRYPTO_OPERATORS               = 0x239
   159  	DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP     = 0x23b
   160  	DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
   161  	DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP        = 0x23d
   162  	DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP      = 0x23e
   163  )
   164  
   165  //sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
   166  //sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
   167  //sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
   168  //sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
   169  //sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
   170  //sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
   171  //sys	AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
   172  //sys	FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
   173  //sys	EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
   174  
   175  // The security identifier (SID) structure is a variable-length
   176  // structure used to uniquely identify users or groups.
   177  type SID struct{}
   178  
   179  // StringToSid converts a string-format security identifier
   180  // sid into a valid, functional sid.
   181  func StringToSid(s string) (*SID, error) {
   182  	var sid *SID
   183  	p, e := UTF16PtrFromString(s)
   184  	if e != nil {
   185  		return nil, e
   186  	}
   187  	e = ConvertStringSidToSid(p, &sid)
   188  	if e != nil {
   189  		return nil, e
   190  	}
   191  	defer LocalFree((Handle)(unsafe.Pointer(sid)))
   192  	return sid.Copy()
   193  }
   194  
   195  // LookupSID retrieves a security identifier sid for the account
   196  // and the name of the domain on which the account was found.
   197  // System specify target computer to search.
   198  func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
   199  	if len(account) == 0 {
   200  		return nil, "", 0, syscall.EINVAL
   201  	}
   202  	acc, e := UTF16PtrFromString(account)
   203  	if e != nil {
   204  		return nil, "", 0, e
   205  	}
   206  	var sys *uint16
   207  	if len(system) > 0 {
   208  		sys, e = UTF16PtrFromString(system)
   209  		if e != nil {
   210  			return nil, "", 0, e
   211  		}
   212  	}
   213  	n := uint32(50)
   214  	dn := uint32(50)
   215  	for {
   216  		b := make([]byte, n)
   217  		db := make([]uint16, dn)
   218  		sid = (*SID)(unsafe.Pointer(&b[0]))
   219  		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
   220  		if e == nil {
   221  			return sid, UTF16ToString(db), accType, nil
   222  		}
   223  		if e != ERROR_INSUFFICIENT_BUFFER {
   224  			return nil, "", 0, e
   225  		}
   226  		if n <= uint32(len(b)) {
   227  			return nil, "", 0, e
   228  		}
   229  	}
   230  }
   231  
   232  // String converts sid to a string format
   233  // suitable for display, storage, or transmission.
   234  func (sid *SID) String() (string, error) {
   235  	var s *uint16
   236  	e := ConvertSidToStringSid(sid, &s)
   237  	if e != nil {
   238  		return "", e
   239  	}
   240  	defer LocalFree((Handle)(unsafe.Pointer(s)))
   241  	return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
   242  }
   243  
   244  // Len returns the length, in bytes, of a valid security identifier sid.
   245  func (sid *SID) Len() int {
   246  	return int(GetLengthSid(sid))
   247  }
   248  
   249  // Copy creates a duplicate of security identifier sid.
   250  func (sid *SID) Copy() (*SID, error) {
   251  	b := make([]byte, sid.Len())
   252  	sid2 := (*SID)(unsafe.Pointer(&b[0]))
   253  	e := CopySid(uint32(len(b)), sid2, sid)
   254  	if e != nil {
   255  		return nil, e
   256  	}
   257  	return sid2, nil
   258  }
   259  
   260  // LookupAccount retrieves the name of the account for this sid
   261  // and the name of the first domain on which this sid is found.
   262  // System specify target computer to search for.
   263  func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
   264  	var sys *uint16
   265  	if len(system) > 0 {
   266  		sys, err = UTF16PtrFromString(system)
   267  		if err != nil {
   268  			return "", "", 0, err
   269  		}
   270  	}
   271  	n := uint32(50)
   272  	dn := uint32(50)
   273  	for {
   274  		b := make([]uint16, n)
   275  		db := make([]uint16, dn)
   276  		e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
   277  		if e == nil {
   278  			return UTF16ToString(b), UTF16ToString(db), accType, nil
   279  		}
   280  		if e != ERROR_INSUFFICIENT_BUFFER {
   281  			return "", "", 0, e
   282  		}
   283  		if n <= uint32(len(b)) {
   284  			return "", "", 0, e
   285  		}
   286  	}
   287  }
   288  
   289  const (
   290  	// do not reorder
   291  	TOKEN_ASSIGN_PRIMARY = 1 << iota
   292  	TOKEN_DUPLICATE
   293  	TOKEN_IMPERSONATE
   294  	TOKEN_QUERY
   295  	TOKEN_QUERY_SOURCE
   296  	TOKEN_ADJUST_PRIVILEGES
   297  	TOKEN_ADJUST_GROUPS
   298  	TOKEN_ADJUST_DEFAULT
   299  
   300  	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
   301  		TOKEN_ASSIGN_PRIMARY |
   302  		TOKEN_DUPLICATE |
   303  		TOKEN_IMPERSONATE |
   304  		TOKEN_QUERY |
   305  		TOKEN_QUERY_SOURCE |
   306  		TOKEN_ADJUST_PRIVILEGES |
   307  		TOKEN_ADJUST_GROUPS |
   308  		TOKEN_ADJUST_DEFAULT
   309  	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
   310  	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
   311  		TOKEN_ADJUST_PRIVILEGES |
   312  		TOKEN_ADJUST_GROUPS |
   313  		TOKEN_ADJUST_DEFAULT
   314  	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
   315  )
   316  
   317  const (
   318  	// do not reorder
   319  	TokenUser = 1 + iota
   320  	TokenGroups
   321  	TokenPrivileges
   322  	TokenOwner
   323  	TokenPrimaryGroup
   324  	TokenDefaultDacl
   325  	TokenSource
   326  	TokenType
   327  	TokenImpersonationLevel
   328  	TokenStatistics
   329  	TokenRestrictedSids
   330  	TokenSessionId
   331  	TokenGroupsAndPrivileges
   332  	TokenSessionReference
   333  	TokenSandBoxInert
   334  	TokenAuditPolicy
   335  	TokenOrigin
   336  	TokenElevationType
   337  	TokenLinkedToken
   338  	TokenElevation
   339  	TokenHasRestrictions
   340  	TokenAccessInformation
   341  	TokenVirtualizationAllowed
   342  	TokenVirtualizationEnabled
   343  	TokenIntegrityLevel
   344  	TokenUIAccess
   345  	TokenMandatoryPolicy
   346  	TokenLogonSid
   347  	MaxTokenInfoClass
   348  )
   349  
   350  type SIDAndAttributes struct {
   351  	Sid        *SID
   352  	Attributes uint32
   353  }
   354  
   355  type Tokenuser struct {
   356  	User SIDAndAttributes
   357  }
   358  
   359  type Tokenprimarygroup struct {
   360  	PrimaryGroup *SID
   361  }
   362  
   363  type Tokengroups struct {
   364  	GroupCount uint32
   365  	Groups     [1]SIDAndAttributes
   366  }
   367  
   368  // Authorization Functions
   369  //sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
   370  //sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
   371  //sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
   372  //sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
   373  
   374  // An access token contains the security information for a logon session.
   375  // The system creates an access token when a user logs on, and every
   376  // process executed on behalf of the user has a copy of the token.
   377  // The token identifies the user, the user's groups, and the user's
   378  // privileges. The system uses the token to control access to securable
   379  // objects and to control the ability of the user to perform various
   380  // system-related operations on the local computer.
   381  type Token Handle
   382  
   383  // OpenCurrentProcessToken opens the access token
   384  // associated with current process.
   385  func OpenCurrentProcessToken() (Token, error) {
   386  	p, e := GetCurrentProcess()
   387  	if e != nil {
   388  		return 0, e
   389  	}
   390  	var t Token
   391  	e = OpenProcessToken(p, TOKEN_QUERY, &t)
   392  	if e != nil {
   393  		return 0, e
   394  	}
   395  	return t, nil
   396  }
   397  
   398  // Close releases access to access token.
   399  func (t Token) Close() error {
   400  	return CloseHandle(Handle(t))
   401  }
   402  
   403  // getInfo retrieves a specified type of information about an access token.
   404  func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
   405  	n := uint32(initSize)
   406  	for {
   407  		b := make([]byte, n)
   408  		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
   409  		if e == nil {
   410  			return unsafe.Pointer(&b[0]), nil
   411  		}
   412  		if e != ERROR_INSUFFICIENT_BUFFER {
   413  			return nil, e
   414  		}
   415  		if n <= uint32(len(b)) {
   416  			return nil, e
   417  		}
   418  	}
   419  }
   420  
   421  // GetTokenUser retrieves access token t user account information.
   422  func (t Token) GetTokenUser() (*Tokenuser, error) {
   423  	i, e := t.getInfo(TokenUser, 50)
   424  	if e != nil {
   425  		return nil, e
   426  	}
   427  	return (*Tokenuser)(i), nil
   428  }
   429  
   430  // GetTokenGroups retrieves group accounts associated with access token t.
   431  func (t Token) GetTokenGroups() (*Tokengroups, error) {
   432  	i, e := t.getInfo(TokenGroups, 50)
   433  	if e != nil {
   434  		return nil, e
   435  	}
   436  	return (*Tokengroups)(i), nil
   437  }
   438  
   439  // GetTokenPrimaryGroup retrieves access token t primary group information.
   440  // A pointer to a SID structure representing a group that will become
   441  // the primary group of any objects created by a process using this access token.
   442  func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
   443  	i, e := t.getInfo(TokenPrimaryGroup, 50)
   444  	if e != nil {
   445  		return nil, e
   446  	}
   447  	return (*Tokenprimarygroup)(i), nil
   448  }
   449  
   450  // GetUserProfileDirectory retrieves path to the
   451  // root directory of the access token t user's profile.
   452  func (t Token) GetUserProfileDirectory() (string, error) {
   453  	n := uint32(100)
   454  	for {
   455  		b := make([]uint16, n)
   456  		e := GetUserProfileDirectory(t, &b[0], &n)
   457  		if e == nil {
   458  			return UTF16ToString(b), nil
   459  		}
   460  		if e != ERROR_INSUFFICIENT_BUFFER {
   461  			return "", e
   462  		}
   463  		if n <= uint32(len(b)) {
   464  			return "", e
   465  		}
   466  	}
   467  }
   468  
   469  // IsMember reports whether the access token t is a member of the provided SID.
   470  func (t Token) IsMember(sid *SID) (bool, error) {
   471  	var b int32
   472  	if e := checkTokenMembership(t, sid, &b); e != nil {
   473  		return false, e
   474  	}
   475  	return b != 0, nil
   476  }