mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 08:11:32 +01:00 
			
		
		
		
	This PR ties together pseudoconsoles, user profiles, s4u logons, and process creation into what is (hopefully) a simple API for various Tailscale services to obtain Windows access tokens without requiring knowledge of any Windows passwords. It works both for domain-joined machines (Kerberos) and non-domain-joined machines. The former case is fairly straightforward as it is fully documented. OTOH, the latter case is not documented, though it is fully defined in the C headers in the Windows SDK. The documentation blanks were filled in by reading the source code of Microsoft's Win32 port of OpenSSH. We need to do a bit of acrobatics to make conpty work correctly while creating a child process with an s4u token; see the doc comments above startProcessInternal for details. Updates #12383 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
		
			
				
	
	
		
			105 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Code generated by 'go generate'; DO NOT EDIT.
 | |
| 
 | |
| package s4u
 | |
| 
 | |
| import (
 | |
| 	"syscall"
 | |
| 	"unsafe"
 | |
| 
 | |
| 	"golang.org/x/sys/windows"
 | |
| )
 | |
| 
 | |
| var _ unsafe.Pointer
 | |
| 
 | |
| // Do the interface allocations only once for common
 | |
| // Errno values.
 | |
| const (
 | |
| 	errnoERROR_IO_PENDING = 997
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
 | |
| 	errERROR_EINVAL     error = syscall.EINVAL
 | |
| )
 | |
| 
 | |
| // errnoErr returns common boxed Errno values, to prevent
 | |
| // allocations at runtime.
 | |
| func errnoErr(e syscall.Errno) error {
 | |
| 	switch e {
 | |
| 	case 0:
 | |
| 		return errERROR_EINVAL
 | |
| 	case errnoERROR_IO_PENDING:
 | |
| 		return errERROR_IO_PENDING
 | |
| 	}
 | |
| 	// TODO: add more here, after collecting data on the common
 | |
| 	// error values see on Windows. (perhaps when running
 | |
| 	// all.bat?)
 | |
| 	return e
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
 | |
| 	modsecur32  = windows.NewLazySystemDLL("secur32.dll")
 | |
| 
 | |
| 	procAllocateLocallyUniqueId        = modadvapi32.NewProc("AllocateLocallyUniqueId")
 | |
| 	procImpersonateLoggedOnUser        = modadvapi32.NewProc("ImpersonateLoggedOnUser")
 | |
| 	procLsaConnectUntrusted            = modsecur32.NewProc("LsaConnectUntrusted")
 | |
| 	procLsaDeregisterLogonProcess      = modsecur32.NewProc("LsaDeregisterLogonProcess")
 | |
| 	procLsaFreeReturnBuffer            = modsecur32.NewProc("LsaFreeReturnBuffer")
 | |
| 	procLsaLogonUser                   = modsecur32.NewProc("LsaLogonUser")
 | |
| 	procLsaLookupAuthenticationPackage = modsecur32.NewProc("LsaLookupAuthenticationPackage")
 | |
| 	procLsaRegisterLogonProcess        = modsecur32.NewProc("LsaRegisterLogonProcess")
 | |
| )
 | |
| 
 | |
| func allocateLocallyUniqueId(luid *windows.LUID) (err error) {
 | |
| 	r1, _, e1 := syscall.Syscall(procAllocateLocallyUniqueId.Addr(), 1, uintptr(unsafe.Pointer(luid)), 0, 0)
 | |
| 	if int32(r1) == 0 {
 | |
| 		err = errnoErr(e1)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func impersonateLoggedOnUser(token windows.Token) (err error) {
 | |
| 	r1, _, e1 := syscall.Syscall(procImpersonateLoggedOnUser.Addr(), 1, uintptr(token), 0, 0)
 | |
| 	if int32(r1) == 0 {
 | |
| 		err = errnoErr(e1)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func lsaConnectUntrusted(lsaHandle *_LSAHANDLE) (ret windows.NTStatus) {
 | |
| 	r0, _, _ := syscall.Syscall(procLsaConnectUntrusted.Addr(), 1, uintptr(unsafe.Pointer(lsaHandle)), 0, 0)
 | |
| 	ret = windows.NTStatus(r0)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func lsaDeregisterLogonProcess(lsaHandle _LSAHANDLE) (ret windows.NTStatus) {
 | |
| 	r0, _, _ := syscall.Syscall(procLsaDeregisterLogonProcess.Addr(), 1, uintptr(lsaHandle), 0, 0)
 | |
| 	ret = windows.NTStatus(r0)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func lsaFreeReturnBuffer(buffer uintptr) (ret windows.NTStatus) {
 | |
| 	r0, _, _ := syscall.Syscall(procLsaFreeReturnBuffer.Addr(), 1, uintptr(buffer), 0, 0)
 | |
| 	ret = windows.NTStatus(r0)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func lsaLogonUser(lsaHandle _LSAHANDLE, originName *windows.NTString, logonType _SECURITY_LOGON_TYPE, authenticationPackage uint32, authenticationInformation unsafe.Pointer, authenticationInformationLength uint32, localGroups *windows.Tokengroups, sourceContext *_TOKEN_SOURCE, profileBuffer *uintptr, profileBufferLength *uint32, logonID *windows.LUID, token *windows.Token, quotas *_QUOTA_LIMITS, subStatus *windows.NTStatus) (ret windows.NTStatus) {
 | |
| 	r0, _, _ := syscall.Syscall15(procLsaLogonUser.Addr(), 14, uintptr(lsaHandle), uintptr(unsafe.Pointer(originName)), uintptr(logonType), uintptr(authenticationPackage), uintptr(authenticationInformation), uintptr(authenticationInformationLength), uintptr(unsafe.Pointer(localGroups)), uintptr(unsafe.Pointer(sourceContext)), uintptr(unsafe.Pointer(profileBuffer)), uintptr(unsafe.Pointer(profileBufferLength)), uintptr(unsafe.Pointer(logonID)), uintptr(unsafe.Pointer(token)), uintptr(unsafe.Pointer(quotas)), uintptr(unsafe.Pointer(subStatus)), 0)
 | |
| 	ret = windows.NTStatus(r0)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func lsaLookupAuthenticationPackage(lsaHandle _LSAHANDLE, packageName *windows.NTString, authenticationPackage *uint32) (ret windows.NTStatus) {
 | |
| 	r0, _, _ := syscall.Syscall(procLsaLookupAuthenticationPackage.Addr(), 3, uintptr(lsaHandle), uintptr(unsafe.Pointer(packageName)), uintptr(unsafe.Pointer(authenticationPackage)))
 | |
| 	ret = windows.NTStatus(r0)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func lsaRegisterLogonProcess(logonProcessName *windows.NTString, lsaHandle *_LSAHANDLE, securityMode *_LSA_OPERATIONAL_MODE) (ret windows.NTStatus) {
 | |
| 	r0, _, _ := syscall.Syscall(procLsaRegisterLogonProcess.Addr(), 3, uintptr(unsafe.Pointer(logonProcessName)), uintptr(unsafe.Pointer(lsaHandle)), uintptr(unsafe.Pointer(securityMode)))
 | |
| 	ret = windows.NTStatus(r0)
 | |
| 	return
 | |
| }
 |