Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/auth/windows/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,18 @@ const (
ClassContainer = "container"
// ClassGMSA is the object class for group managed service accounts in Active Directory.
ClassGMSA = "msDS-GroupManagedServiceAccount"
// ClassUser is the object class for users in Active Directory
ClassUser = "user"

// CategoryPerson is object category for persons in Active Directory
CategoryPerson = "person"
// AccountTypeUser is the SAM account type for user accounts.
// See https://learn.microsoft.com/en-us/windows/win32/adschema/a-samaccounttype
// (SAM_USER_OBJECT)
AccountTypeUser = "805306368"

// AttrName is the name of an LDAP object
AttrName = "name"
// AttrSAMAccountName is the SAM Account name of an LDAP object
AttrSAMAccountName = "sAMAccountName"
// AttrSAMAccountType is the SAM Account type for an LDAP object
AttrSAMAccountType = "sAMAccountType"
// AttrCommonName is the common name of an LDAP object, or "CN"
AttrCommonName = "cn"
// AttrDistinguishedName is the distinguished name of an LDAP object, or "DN"
Expand Down
7 changes: 5 additions & 2 deletions lib/srv/desktop/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,19 @@ func (s *WindowsService) lookupDesktop(ctx context.Context, hostname string) (ad
return addrs, nil
}
if s.dnsResolver == nil {
return nil, trace.NewAggregate(err, trace.Errorf("DNS lookup for %v failed and there's no LDAP server to fallback to", hostname))
return nil, trace.NewAggregate(err, trace.Errorf("DNS lookup for %q failed and there's no LDAP server to fallback to", hostname))
}
s.cfg.Log.WithError(err).Debugf("DNS lookup for %v failed, falling back to LDAP server", hostname)
s.cfg.Log.WithError(err).Debugf("DNS lookup for %q failed, falling back to LDAP server", hostname)
return s.dnsResolver.LookupHost(ctx, hostname)
}

// ldapEntryToWindowsDesktop generates the Windows Desktop resource
// from an LDAP search result
func (s *WindowsService) ldapEntryToWindowsDesktop(ctx context.Context, entry *ldap.Entry, getHostLabels func(string) map[string]string) (types.ResourceWithLabels, error) {
hostname := entry.GetAttributeValue(windows.AttrDNSHostName)
if hostname == "" {
return nil, trace.BadParameter("LDAP entry missing hostname, has attributes: %v", entry.Attributes)
}
labels := getHostLabels(hostname)
labels[types.TeleportNamespace+"/windows_domain"] = s.cfg.Domain
s.applyLabelsFromLDAP(entry, labels)
Expand Down
23 changes: 13 additions & 10 deletions lib/srv/desktop/windows_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,11 @@ func (s *WindowsService) handleConnection(proxyConn *tls.Conn) {

if err := s.connectRDP(ctx, log, tdpConn, desktop, authContext); err != nil {
log.Errorf("RDP connection failed: %v", err)
sendTDPError("RDP connection failed.")
msg := "RDP connection failed."
if um, ok := err.(trace.UserMessager); ok {
msg = um.UserMessage()
}
sendTDPError(msg)
return
}
}
Expand Down Expand Up @@ -1112,28 +1116,27 @@ func (s *WindowsService) generateUserCert(ctx context.Context, username string,
var activeDirectorySID string
if !desktop.NonAD() {
// Find the user's SID
s.cfg.Log.Debugf("querying LDAP for objectSid of Windows username: %v", username)
filters := []string{
fmt.Sprintf("(%s=%s)", windows.AttrObjectCategory, windows.CategoryPerson),
fmt.Sprintf("(%s=%s)", windows.AttrObjectClass, windows.ClassUser),
filter := windows.CombineLDAPFilters([]string{
fmt.Sprintf("(%s=%s)", windows.AttrSAMAccountType, windows.AccountTypeUser),
fmt.Sprintf("(%s=%s)", windows.AttrSAMAccountName, username),
}
})
s.cfg.Log.Debugf("querying LDAP for objectSid of Windows username %q with filter %v", username, filter)

entries, err := s.lc.ReadWithFilter(s.cfg.LDAPConfig.DomainDN(), windows.CombineLDAPFilters(filters), []string{windows.AttrObjectSid})
entries, err := s.lc.ReadWithFilter(s.cfg.LDAPConfig.DomainDN(), filter, []string{windows.AttrObjectSid})
// if LDAP-based desktop discovery is not enabled, there may not be enough
// traffic to keep the connection open. Attempt to open a new LDAP connection
// in this case.
if trace.IsConnectionProblem(err) {
s.initializeLDAP() // ignore error, this is a best effort attempt
entries, err = s.lc.ReadWithFilter(s.cfg.LDAPConfig.DomainDN(), windows.CombineLDAPFilters(filters), []string{windows.AttrObjectSid})
entries, err = s.lc.ReadWithFilter(s.cfg.LDAPConfig.DomainDN(), filter, []string{windows.AttrObjectSid})
}
if err != nil {
return nil, nil, trace.Wrap(err)
}
if len(entries) == 0 {
return nil, nil, trace.NotFound("LDAP failed to return objectSid for Windows username: %v", username)
return nil, nil, trace.NotFound("could not find Windows account %q", username)
} else if len(entries) > 1 {
s.cfg.Log.Warnf("LDAP unexpectedly returned multiple entries for objectSid for username: %v, taking the first", username)
s.cfg.Log.Warnf("found multiple entries for username %q, taking the first", username)
}
activeDirectorySID, err = windows.ADSIDStringFromLDAPEntry(entries[0])
if err != nil {
Expand Down