116 lines
5.0 KiB
Go
116 lines
5.0 KiB
Go
|
// Package pac implements Microsoft Privilege Attribute Certificate (PAC) processing.
|
||
|
package pac
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
|
||
|
"gopkg.in/jcmturner/rpc.v1/mstypes"
|
||
|
"gopkg.in/jcmturner/rpc.v1/ndr"
|
||
|
)
|
||
|
|
||
|
// KERB_VALIDATION_INFO flags.
|
||
|
const (
|
||
|
USERFLAG_GUEST = 31 // Authentication was done via the GUEST account; no password was used.
|
||
|
USERFLAG_NO_ENCRYPTION_AVAILABLE = 30 // No encryption is available.
|
||
|
USERFLAG_LAN_MANAGER_KEY = 28 // LAN Manager key was used for authentication.
|
||
|
USERFLAG_SUB_AUTH = 25 // Sub-authentication used; session key came from the sub-authentication package.
|
||
|
USERFLAG_EXTRA_SIDS = 26 // Indicates that the ExtraSids field is populated and contains additional SIDs.
|
||
|
USERFLAG_MACHINE_ACCOUNT = 24 // Indicates that the account is a machine account.
|
||
|
USERFLAG_DC_NTLM2 = 23 // Indicates that the domain controller understands NTLMv2.
|
||
|
USERFLAG_RESOURCE_GROUPIDS = 22 // Indicates that the ResourceGroupIds field is populated.
|
||
|
USERFLAG_PROFILEPATH = 21 // Indicates that ProfilePath is populated.
|
||
|
USERFLAG_NTLM2_NTCHALLENGERESP = 20 // The NTLMv2 response from the NtChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and session key generation.
|
||
|
USERFLAG_LM2_LMCHALLENGERESP = 19 // The LMv2 response from the LmChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and session key generation.
|
||
|
USERFLAG_AUTH_LMCHALLENGERESP_KEY_NTCHALLENGERESP = 18 // The LMv2 response from the LmChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and the NTLMv2 response from the NtChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used session key generation.
|
||
|
)
|
||
|
|
||
|
// KerbValidationInfo implement https://msdn.microsoft.com/en-us/library/cc237948.aspx
|
||
|
// The KERB_VALIDATION_INFO structure defines the user's logon and authorization information
|
||
|
// provided by the DC. The KERB_VALIDATION_INFO structure is a subset of the
|
||
|
// NETLOGON_VALIDATION_SAM_INFO4 structure ([MS-NRPC] section 2.2.1.4.13).
|
||
|
// It is a subset due to historical reasons and to the use of the common Active Directory to generate this information.
|
||
|
// The KERB_VALIDATION_INFO structure is marshaled by RPC [MS-RPCE].
|
||
|
type KerbValidationInfo struct {
|
||
|
LogOnTime mstypes.FileTime
|
||
|
LogOffTime mstypes.FileTime
|
||
|
KickOffTime mstypes.FileTime
|
||
|
PasswordLastSet mstypes.FileTime
|
||
|
PasswordCanChange mstypes.FileTime
|
||
|
PasswordMustChange mstypes.FileTime
|
||
|
EffectiveName mstypes.RPCUnicodeString
|
||
|
FullName mstypes.RPCUnicodeString
|
||
|
LogonScript mstypes.RPCUnicodeString
|
||
|
ProfilePath mstypes.RPCUnicodeString
|
||
|
HomeDirectory mstypes.RPCUnicodeString
|
||
|
HomeDirectoryDrive mstypes.RPCUnicodeString
|
||
|
LogonCount uint16
|
||
|
BadPasswordCount uint16
|
||
|
UserID uint32
|
||
|
PrimaryGroupID uint32
|
||
|
GroupCount uint32
|
||
|
GroupIDs []mstypes.GroupMembership `ndr:"pointer,conformant"`
|
||
|
UserFlags uint32
|
||
|
UserSessionKey mstypes.UserSessionKey
|
||
|
LogonServer mstypes.RPCUnicodeString
|
||
|
LogonDomainName mstypes.RPCUnicodeString
|
||
|
LogonDomainID mstypes.RPCSID `ndr:"pointer"`
|
||
|
Reserved1 [2]uint32 // Has 2 elements
|
||
|
UserAccountControl uint32
|
||
|
SubAuthStatus uint32
|
||
|
LastSuccessfulILogon mstypes.FileTime
|
||
|
LastFailedILogon mstypes.FileTime
|
||
|
FailedILogonCount uint32
|
||
|
Reserved3 uint32
|
||
|
SIDCount uint32
|
||
|
ExtraSIDs []mstypes.KerbSidAndAttributes `ndr:"pointer,conformant"`
|
||
|
ResourceGroupDomainSID mstypes.RPCSID `ndr:"pointer"`
|
||
|
ResourceGroupCount uint32
|
||
|
ResourceGroupIDs []mstypes.GroupMembership `ndr:"pointer,conformant"`
|
||
|
}
|
||
|
|
||
|
// Unmarshal bytes into the DeviceInfo struct
|
||
|
func (k *KerbValidationInfo) Unmarshal(b []byte) (err error) {
|
||
|
dec := ndr.NewDecoder(bytes.NewReader(b))
|
||
|
err = dec.Decode(k)
|
||
|
if err != nil {
|
||
|
err = fmt.Errorf("error unmarshaling KerbValidationInfo: %v", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// GetGroupMembershipSIDs returns a slice of strings containing the group membership SIDs found in the PAC.
|
||
|
func (k *KerbValidationInfo) GetGroupMembershipSIDs() []string {
|
||
|
var g []string
|
||
|
lSID := k.LogonDomainID.String()
|
||
|
for i := range k.GroupIDs {
|
||
|
g = append(g, fmt.Sprintf("%s-%d", lSID, k.GroupIDs[i].RelativeID))
|
||
|
}
|
||
|
for _, s := range k.ExtraSIDs {
|
||
|
var exists = false
|
||
|
for _, es := range g {
|
||
|
if es == s.SID.String() {
|
||
|
exists = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if !exists {
|
||
|
g = append(g, s.SID.String())
|
||
|
}
|
||
|
}
|
||
|
for _, r := range k.ResourceGroupIDs {
|
||
|
var exists = false
|
||
|
s := fmt.Sprintf("%s-%d", k.ResourceGroupDomainSID.String(), r.RelativeID)
|
||
|
for _, es := range g {
|
||
|
if es == s {
|
||
|
exists = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if !exists {
|
||
|
g = append(g, s)
|
||
|
}
|
||
|
}
|
||
|
return g
|
||
|
}
|