Mapping Samba's S-1-22-[12]-* SID into names
Asked Answered
N

1

20

Samba3 uses SID's in the range S-1-22-1 for users and S-1-22-2 for groups. For instance, S-1-22-1-1-10042 is the UNIX user with uid 10042. I would like to be either able to map such a SID into a name, like 'myunixaccount', similar to this functionality for Windows account mapping:

SecurityIdentifier sid = ...; // For instance from FileSystemAccessRule.
name = sid.Translate(typeof(NTAccount)).Value;

Windows itself is able to make this mapping, but I seem unable to find a mapping algorithm.

ADDED: Environment Description

Tested proposed solution on Convert SID to Username in C#. It did not help. Therefore some extra environment description:

  • Windows PC, either joined to a domain or standalone, running W7 Professional, x86.
  • File located on Samba-based drive. Samba authenticates to AD controller of domain.
  • Samba version: 4.0.3, running on Linux 2.6.18-238, x64.
  • PAM for Samba, interactive sessions etc.
  • AD controller is W2012 with some default UNIX extension attribute in the directory to allow mapping UID etc.
  • .NET Framework libraries 4.5.2.
  • ldap.conf:

piece of ldap.conf

nss_base_passwd=OU=nl,OU=xxx,dc=yyy,dc=local?sub(objectCategory=user)
nss_map_objectclass     posixAccount    User
nss_map_objectclass     shadowAccount   User
nss_map_attribute       uid             sAMAccountName
nss_map_attribute       uidNumber       uidNumber
nss_map_attribute       gidNumber       gidNumber
nss_map_attribute       cn              sAMAccountName
nss_map_attribute       uniqueMember    member
nss_map_attribute       userPassword    msSFUPassword
nss_map_attribute       homeDirectory   unixHomeDirectory
nss_map_attribute       loginShell      loginShell
nss_map_attribute       gecos           cn
nss_map_objectclass     posixGroup      Group
nss_map_attribute       shadowLastChange        pwdLastSet

Interactive logons on UNIX with Windows authentication work fine, dito for Samba shares. When using a PC on the domain, it doesn't ask for credentials.

Some samples, the user gle3 (highlighted in 1) also exists in the domain but with a different SID. The SID used here is the Samba SID, like S-1-22-1-1-10001.

In (2) you can see that the user exists in the used passwd configuration. The following of course yields no results: grep gle3 /etc/passwd, since the entries are used from remote server. The remote server maps the user SID of gle3 to UNIX uid 10001 and default group 10003.

In (3) you can see that the default group does not exist, and that is why the permissions can not resolve it to a name.

So obviously Windows somehow asks the file server: "give me the data on these SIDs" and the Samba file server respons somehow: Ok, that is "Unix User\gle3" and "Unix Group\10003" but I do not have a group name for that last one.

Windows Explorer (Dutch) UNIX getent passwd UNIX getent group

Nonmaterial answered 29/6, 2015 at 7:17 Comment(7)
#7593505 Or is it something else with Samba?Stiffnecked
Tested it, but same results. It seems that the .NET 2.0 framework already encapsulated that one as described on pinvoke.net. Thanks anyhow!Nonmaterial
Would you please describe more details about your environment? The code worked on my machine.Esma
I'm still not very clear about your requirement. Do you want to get the mapping on the Samba server (Linux)? I think in Linux you can get mapping from user ID to name from /etc/passwd.Esma
This is a bit tricky, since this is not actually part of SMB. On Windows, the translation occurs through Active Directory or Workgroups, which is pretty handy since the information there is easily accessible to both the client and the server. On *nix systems, this isn't quite so simple. That said, if you're using Samba 4+, it should have it's own Active Directory client/server. Where exactly does the mapping fail, on the client or the server?Sunglass
@YueLiu I do not need to get the /etc/passwd or ypcat or getent passwd, but solely the mapping from the SID on Windows to the associated login code. For instance, going from S-1-22-1-1-10042 to the UNIX login code "ftp" or whatever login code Samba uses (Samba might use another authentication server also).Nonmaterial
@Sunglass the mapping using question 7593005 and my own code returns null. However, in the Windows Explorer -> Right click -> Properties -> Security windows somehow manages to retrieve the login code from the Samba server.Nonmaterial
A
1

I've been toying around with this some time ago for building a local LAN crawler on a 2000+ computer network. I'm pretty sure that what you're asking is not part of the SMB protocol. You can actually see that: if Windows cannot resolve the credentials, it will show the SID's in the security properties.

Basically what happens is that a SID is an object ID (like a username / group) that's mapped to a unique ID. They work like GUID's. Usually PC's communicate in SID's, not in usernames.

Now, there's different kinds of SID you need to consider:

  1. You have the Active Directory SID that you can resolve using the standard methods. Note that these include group and user SID's.
  2. There's the local PC SID's that you can resolve using the standard methods. Again, group and user SID's. This probably works for Samba as well as Windows, although I've only tested it on Windows in the past.
  3. There's SID's on remote PC's that normally cannot be resolved. Basically this is what happens if you get a NTLM token in any different way.

There's actually a lot more than this... certificate credentials, reserved users, etc are all also object ID's which can be used for logging in - but I'll just keep it simple. The key takeaway from this comment is that while all usernames have a SID, it's not true that all SID's also have a username.

If you have an AD somewhere (you seem to do), a proper setup contains all users here. The easiest way to get the complete mapping is to simply enumerate the complete active directory. That should contain all the mappings. Basically that works like this:

DirectoryEntry root = new DirectoryEntry("LDAP://dc=MyCompany,dc=com");

DirectorySearcher search = new DirectorySearcher(root);
search.Filter = "(objectCategory=Person)";
search.SearchScope = SearchScope.Subtree;

search.PropertiesToLoad.Add("objectSid");
search.PropertiesToLoad.Add("displayName");

foreach(SearchResult result in search.FindAll())
{
   // grab the data - if present
   if(result.Properties["objectSid"] != null && result.Properties["objectSid"].Count > 1)
   {
       var sid = result.Properties["objectSid"][0];
   }

   if(result.Properties["displayName"] != null && result.Properties["displayName"].Count > 0)
   {
       var userName = result.Properties["displayName"][0].ToString();
   }
}
Airedale answered 10/7, 2015 at 6:25 Comment(4)
Thank you @atlaste. Querying through LDAP on the server could be a solution, but in this case the SID presented through Samba is different from the original SID of the user in the Active Directory domain, please see above. What could be a good way to map the Samba SID to a login code similar to Windows manages to do it?Nonmaterial
@GuidoLeenders Yes, samba generates SIDs the same way as you would normally generate GUID's and store them in a database. If you encounter a linux ID, you can just do the NTLM challenge-response, get the SID and that makes the pair complete. There is no easy solution for this; the information is simply not there. PS: Windows won't show these as well.Airedale
PS I spent countless hours using wireshark to figure out the RPC codes that windows is using on samba.. if you really want this and can replicate it with Windows Explorer, that's the way to go.Airedale
@GuidoLeenders here's a link: samba.org/samba/docs/man/manpages/rpcclient.1.html - you're looking for the 'lookupsids' RPC call. The easiest way to do that is use the cygwin ported version (exe) and call exactly that.Airedale

© 2022 - 2024 — McMap. All rights reserved.