Subject: Re: [1.7] passwd: useless if used with a logged on domain user
From: Júlio Costa <[email-masked]>
To: [email-masked]
Date: Mon, 23 Mar 2009 14:35:02 +0000
List-Id: <cygwin.cygwin.com>

On Sun, Mar 22, 2009 at 19:22, Corinna Vinschen wrote:
> On Mar 22 17:34, J?lio Costa wrote:
>> ~ $ # Just typed Ctrl-C. Not in the mood right now :)
>> ~ $ # And now for the interesting part:
>> ~ $ ./my_passwd.exe -S SYSTEM
>> my_passwd: unknown user SYSTEM
>
> The SYSTEM user is not in the user database.  So that's an expected
> result.
>

It is in mine:
~ $ grep system /etc/passwd
system:*:18:544:,S-1-5-18::

>> ~ $ # Ooops. And what about
>> ~ $ ./my_passwd.exe -S Administrator
>> You have no maintenance privileges.
>
> I can't reproduce this one, but maybe that's just a different case of
> the same as this one:
>

No. Actually this is the core of the problem. More on this below.

>> ~ $ # Ouch. If I may insist:
>> ~ $ ./my_passwd.exe -d $HOSTNAME -S Administrator
>> my_passwd: unknown user security
>
> I applied another fix to passwd to decouple the logonserver for fetching
> the user info for the running user account from the user info for the
> user account which is going to be manipulated by passwd.
>

Ok. I've tested the last CVS version and things are still bad:

~/passwd $ ./my_passwd_117.exe -v
my_passwd_117 (cygwin) 1.5
Password Utility
Copyright 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
Compiled on Mar 23 2009
~/passwd $ ./my_passwd_117.exe -S Administrator
You have no maintenance privileges.
~/passwd $ ./my_passwd_117.exe -S cyg_server
my_passwd_117: unknown user cyg_server
~/passwd $ # But this should really work:
~/passwd $ ./my_passwd_117.exe -S -d $HOSTNAME cyg_server
You have no maintenance privileges.

I've come to some conclusions in this process. Here they are:
#1 li -> usri3_priv (line 552, 587 and 594) will only tell you if the
logged on user is (isn't) admin in his/her LOGON domain! But what is
needed here is to know if the logged on user is (isn't) admin in the
TARGET domain/server, where is the TARGET account!
#2 Just querying (-S) the account characteristics does not need Admin
priviledges, so the test in 552 should be done instead inside the
if@576; And should be a different test, from what is said in #1;
#3 Generally, commands in Windows without providing additional
information defaults to the local machine. So should passwd.
Currently, I'm forced to say '-d $HOSTNAME' to ensure that the target
user is really on the local machine. This is not coherent behaviour
because it depends or not on if the current logged on user cames from
a domain or is local. Currently the csih script breaks in his call to
passwd due to this. Which breaks sshd-host-config (and maybe others?)
I think the most coherent behaviour should be: 'if '-d' is not
supplied, the TARGET domain is always LOCAL; otherwise, follow
supplied domain'. It is precisely how NET USER and friends works, with
the '/DOMAIN' parameter, with the added tweak that you don't even have
to name the logon domain (although it could be done like this in
passwd also, i think...)

Changes #2 and #3 are trivial, and are in the patch below:

~/passwd $ diff -u passwd_117.c passwd_118.c
--- passwd_117.c        2009-03-23 14:14:20.564919200 +0000
+++ passwd_118.c        2009-03-23 14:28:53.431014000 +0000
@@ -524,8 +524,6 @@
       if (len > 0 && len != (size_t) -1)
        mbstowcs (my_server = alloca ((len + 1) * sizeof (wchar_t)),
                  logonserver, len + 1);
-      if (!server)
-       server = my_server;
     }

   if (Larg >= 0 || xarg >= 0 || narg >= 0 || iarg >= 0)
@@ -549,8 +547,6 @@
     {
       USER_INFO_1008 uif;

-      if (li->usri3_priv != USER_PRIV_ADMIN)
-        return eprint (0, "You have no maintenance privileges.");
       uif.usri1008_flags = ui->usri3_flags;
       if (lopt)
         {
@@ -575,6 +571,8 @@

       if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt)
        {
+          if (li->usri3_priv != USER_PRIV_ADMIN)
+            return eprint (0, "You have no maintenance privileges.");
           ret = NetUserSetInfo (server, ui->usri3_name, 1008, (LPBYTE) &uif,
                                NULL);
           return EvalRet (ret, NULL);

Change #1 is not so trivial, because I'm a little 'rusty' about C and
Windows Functions... and I'm having trouble linking with the
CheckTokenMembership API function...

~ $ gcc -g passwd.c -o my_passwd -lnetapi32 -ladvapi32
/cygdrive/c/DOCUME~1/security/LOCALS~1/Temp/ccpUixM2.o: In function
`IsUserAdmin':
/home/security/passwd.c:164: undefined reference to `_CheckTokenMembership'
collect2: ld returned 1 exit status

But I'll keep trying to achieve a stable version. Unless, of course,
you think that this is not "the way"(tm) to do it...

Stay  tuned.

___________
Julio Costa

Phyllis Diller  - "Never go to bed mad. Stay up and fight."

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/