Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Date: Fri, 19 Apr 2002 12:52:49 -0400 (EDT) From: Chris Metcalf To: cygwin AT cygwin DOT com Subject: FAQ entry for setting up /etc/passwd with both NT domain users and Samba servers under ntsec Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII I spent a while figuring out the right way to configure Cygwin's /etc/passwd in the face of CYGWIN=ntsec, domain users, and Samba servers. I thought I'd write a quick FAQ entry to save others time. Let's say you have a Windows domain "DOM" to which all your users belong. However, you also have a Samba server, which we'll call "SAMBA". Usernames are the same in the domain and on the Samba server; let's consider user "juser". Files created on the Windows machines will be correctly owned by "DOM\juser"; files on the Samba server will be owned by "SAMBA\juser". Unfortunately Samba does not yet handle forwarding user SIDs from the domain, even with "security = domain", though the documentation says work is ongoing in this area. Instead it just makes up a SID base when it first initializes itself, and uses a simple algorithm (2*uid+1000) to generate RIDs from uids. The older cygwins didn't have to worry about this issue, since they always mapped all the file ownership on remote shares to the username of the user who was active. (This is still the default behavior if you don't set CYGWIN=ntsec.) Unfortunately, in this mode you can't see file owners or permissions, which is a serious limitation. The question then is, how do we map the "SAMBA\juser" SIDs for cygwin? If you just do a standard "mkpasswd -d", you will get a password file that includes uids for all the DOM users, but doesn't include uids for the SIDs generated by the SAMBA server; files on that server will be shown as owned by (effectively) random uids with no names. What's more, since the uids won't match, programs will tend to get confused as to whether they're accessible. For example, if your Unix account owns a file with 644 permissions, access(file,W_OK) will report failure (specifically EACCESS, permission denied) if you check it from cygwin. At first I just wanted to give names to the uids owning the Samba server files. Following Corinna's advice from a while back, I created a series of /etc/passwd lines by taking the Unix uids, applying the Samba conversion to get RIDs, then writing out lines with the RID as the uid and the username as "SAMBA\juser". This gave real usernames to the uids, but didn't help with the access problems. I then decided the "SAMBA\" prefixes weren't buying me much, and removed them. At this point each user had two entries in the Cygwin /etc/passwd, one for the DOM RID mapping to one UID, and the other for the SAMBA RID mapping to another UID. This made the output of "ls -l", etc., look prettier, since users appeared to own their own files, but the underlying uids still didn't match for things like access(). Finally I realized that, unlike a normal Unix passwd file, it made sense for there to be multiple lines with the same name and uid. In normal Unix all you do is map from username to uid and back, so lines like this would be meaningless. With cygwin there's an extra mapping from SID to uid, and that's when it helps to have multiple lines. My final solution was to write a Perl script that digests the Cygwin "mkpasswd -d" output to get preferred name->uid mappings, then digests the Unix passwd file to generate SAMBA+RID->uid mappings that match the domain uids. (The Samba SID base is available in the MACHINE.SID file.) Combining the initial "mkpasswd -d" output with the output of this script gives us the final Cygwin /etc/passwd. Now both "DOM\juser" and "SAMBA\juser" files are mapped to the same uid and all the cygwin functionality just works. This still seems like something of an elaborate workaround, unfortunately. Ideally, of course, the Samba server would use the user's domain SID. But until that happens, it would be nice if there was a way to coerce it into using the right SID. Clearly we can reset the MACHINE.SID to the domain SID base. But the RIDs will still be out of wack; we would need a table mapping uids to RIDs that Samba could use. (We can't do it "just" by changing all the Unix uids, since the domain RIDs can be odd numbers, unlike Samba user RIDs.) I've appended my version of the perl script I use to do this. It should be reasonably easy to customize. I don't plan on pushing any further on this, but I'd be curious to hear if anyone has any better strategies they've used in this situation. Chris -- #!/usr/bin/perl # This script builds a piece of the password file for Cygwin. # It should be run on a Samba server; it parses the server's /etc/passwd # and /etc/group and creates matching files in $TARGET_DIR # suitable for appending to a cygwin /etc/{passwd,group}. # It requires that the "mkpasswd -d" output be available in $TARGET_DIR. # We use the SID of the host, from /etc/samba/MACHINE.SID, plus the # computed ID (1000+uid*2, 1001+gid*2). However, we map usernames # that appear in the domain not to that $uid, but to the domain $uid, # so that Cygwin thinks it's all the same. # # Hopefully this will all be unnecessary with a later release of Samba. # See the discussion of "security = domain" in the Samba-HOWTO-Collection. $TARGET_DIR = "/i/cygwin"; # Read the Samba server's SID into $sid. open(SID, "/etc/samba/MACHINE.SID") || die("Can't read /etc/samba/MACHINE.SID: $!\n"); $sid = ; close(SID); chomp $sid; die ("Bad format SID: $sid\n") if ($sid !~ /^S-/); # Read the "mkpasswd -d" output and create %domuid, %domgid mappings. open(DOMPASS, "$TARGET_DIR/passwd.domain") || die("Can't read $TARGET_DIR/passwd.domain: $!\n"); while () { ($name,$x,$uid,$gid) = split(":"); $domuid{$name} = $uid; $domgid{$name} = $gid; } close(DOMPASS); # Create the Cygwin passwd file piece from the Unix /etc/passwd. open(PASSWD, "/etc/passwd") || die("Can't read /etc/passwd: $!\n"); open(CYGPASS, ">$TARGET_DIR/passwd") || die("Can't write $TARGET_DIR/passwd: $!\n"); while () { chomp $_; ($name,$x,$uid,$gid,$full,$home,$shell) = split(":"); # Do any local home directory munging you need here. $home =~ s,^/u/,/h/,; $home = "/" if ($home !~ /^\/h\//); # Compute Samba-style uid/gid. $rid = ($uid*2)+1000; $uid = $rid; $uid = $domuid{$name} if (defined($domuid{$name})); $gid = ($gid*2)+1000; $gid = $domgid{$name} if (defined($domgid{$name})); # Generate appropriate new entry. print CYGPASS "$name:x:$uid:$gid:$full,U-RD\\$name,$sid-$rid:$home:$shell\n"; } close(PASSWD); close(CYGPASS); # Create the Cygwin group file piece from the Unix /etc/group. open(GROUP, "/etc/group") || die("Can't read /etc/group: $!\n"); open(CYGGRP, ">$TARGET_DIR/group") || die("Can't write $TARGET_DIR/group: $!\n"); while () { chomp $_; ($name,$x,$gid,$members) = split(":"); # Compute Samba-style gid. $gid = ($gid*2)+1001; # Generate appropriate new entry. print CYGGRP "$name:$sid-$gid:$gid:\n"; } close(GROUP); close(CYGGRP); -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/