X-Recipient: archive-cygwin AT delorie DOT com DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:date:message-id:references :mime-version:content-type:content-transfer-encoding; q=dns; s= default; b=rQCsKXAcwjU4k9vgmdsGMIVeoEvNUdMgjJUMw3h4HWJOh6VHzXYv3 aeavntsx0lZ/T9jEN4+teMfqDSb3xydIpSjTwQLu/ewSRLzagAFI10LsTkc7H3iQ 8vNV8x4zcwD4IkEiUedw7jiGJJpe480g3kTByZZScRBrDmKUjaQPRg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:date:message-id:references :mime-version:content-type:content-transfer-encoding; s=default; bh=lDMUDA2y4iVQ3icfHOWLvzMjArw=; b=c5dI8v+8TN+YLDuiJjfKh0Qw3Xbi il6Oz2rBgYEuO+iVO2qY7i7vrgxqqTEwz3y01dvB8k5V/2hi1iPvugelrnIjOk9g YxKcYRWvM6cPhqroLkUT1yz+6iqNnFbZfbIvDdLob4Re+Jf4p9TiwUvQrkx3X+Iz Oza80RFRboTICaI= Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: 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 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: plane.gmane.org To: cygwin AT cygwin DOT com From: "D. Boland" Subject: Re: The eternal uid issue Date: Thu, 24 Jul 2014 08:52:42 +0200 Lines: 175 Message-ID: <53D0AD3A.1FDF0B3F@boland.nl> References: <53CF6CEC DOT 6D68E485 AT boland DOT nl> <20140723091409 DOT GH27005 AT calimero DOT vinschen DOT de> <53CF9E0F DOT F596FC60 AT boland DOT nl> <20140723152357 DOT GA24446 AT calimero DOT vinschen DOT de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Hi Corinna, Thanks for the reply. Corinna Vinschen wrote: > > On Jul 23 13:35, D. Boland wrote: > > Corinna Vinschen wrote: > > > Not in relation to the uid. In contrast to Linux we don't have the one > > > single root user. We have potentially endless numbers of them, and one > > > of them, not necessarily SYSTEM, is used to run the service. Keep in > > > mind that there may also be company policy in place which disallows > > > installing services under specific accounts unless absolutely necessary. > > > > > > Therefore, while we mostly strive to make Cygwin accommodate user > > > space, we're not able to do it related to the root uid. > > > > Thanks for your lengthly and detailed answer. I appreciate that. But > > don't you think upstream maintainers will raise at least one eyebrow > > if we propose code that makes any user who starts the program the > > root/admin user? You suggest only those who are in the admin group. > > But that will soon be any service that starts up. > > You're getting this wrong. Cygwin is not the OS. We do not make > every user an admin since we're in no position to do that. We can't > give the user any more rights the OS is already giving the user. Yes, Cygwin is not the OS. But to the user-software, it re-presents the OS as if it were Linux. That's what an emulator does. > > The idea of such a test is to make the test independent of the actual > uid. There are two cases. One is to check if the user has admin > rights to perform certain actions, the other is to check if a file > ownership is safe. A safe ownership is one where the file belongs > to the user running the service. On Linux or BSD systems that's > usually the root user, in our case it's some arbitrary user account. > The check is basically the same. > > > It actually is my solution to running Sendmail: create the Sendmail > > user, called 'smmsp' and make it an Administrator, so it can > > impersonate users on my system. But I don't like my solution, because > > this would mean I have to create an admin-user for any Linux service > > that I install. So now my Cygwin setup would be crowded with highly > > privileged daemons, listening, waiting to get hacked. > > That's what the cyg_server account is meant for. It's the one account > which has the right to change the user context even when using method 1 > from the setuid overview of the User's Guide. > > Other services don't need this permissions, they just have to have > the right to create certain objects. Cygserver is such a service, > for instance. It's perfectly fine for cygserver to run under SYSTEM > or, FWIW, any other account with local administrative privileges. > > > The more elegant solution would be to create only one secondary > > privileged user, let's call it 'root' ;-). Now Sendmail can start as > > root, switch to the totally *unprivileged* 'smmsp' user and receive > > mail. Of course the real bonus is that these unprivileged users > > wouldn't need passwords, since they are impersonated, not logged on. > > These would consequently be *super-secure* users, because it is > > impossible to login with an empty password. > > Same thing with cyg_server. > > > Why is this related to the uid issue? I already tested the second > > solution. I found out that if I assign my 'root' user the '0' id in > > /etc/passwd, it actually works. I was delighted, because I could > > roll-back all these weird changes I put in the > > Sendmail/procmail/mail.local source to fix the getuid != 0 problem. > > Yes, you can do that and it was always possible, but it requires > unnecessary user changes. Also, passwd and group files are going > to become entirely superfluous at one point, and there's not a > single account which is translated to uid 0 on the fly. There > simply isn't one. That's my point. All Linux software expects one. So Cygwin has to provide one. Otherwise, the emulation breaks. Sendmail, for instance, is filled to the brim with uid checks, all assuming that there is a '0' account. Its whole idea of security is based around it. Below a sample: $ grep -r getuid * sendmail/deliver.c: if (RealUid != 0 && RealUid != getuid()) sendmail/deliver.c: (int) getuid(), (int) geteuid(), sendmail/deliver.c: ret = safefile(m->m_mailer, getuid(), getgid(), sendmail/deliver.c: (int) getuid(), (int) geteuid(), sendmail/main.c: RealUid = getuid(); sendmail/main.c: (geteuid() != getuid() || getegid() != getgid())); sendmail/main.c: (int) geteuid(), (int) getuid(), sendmail/main.c: (int) geteuid(), (int) getuid()); sendmail/main.c: (int) geteuid(), (int) getuid()); sendmail/main.c: if (dp == EX_OK && UseMSP && (geteuid() == 0 || getuid() == 0)) sendmail/main.c: (int) getuid(), (int) getgid(), sendmail/main.c: (getuid() != RunAsUid && sendmail/main.c: (to_real_uid || geteuid() == 0 || getuid() == 0))) sendmail/main.c: getuid() != 0 && geteuid() != 0) sendmail/main.c: (int) geteuid(), (int) getuid(), $ grep -r setuid * sendmail/deliver.c: if (new_euid != geteuid() && setuid(new_euid) < 0 && suidwarn) sendmail/deliver.c: syserr("openmailer: setuid(%ld) failed", sendmail/deliver.c: if (setuid(new_ruid) < 0 && suidwarn) sendmail/deliver.c: syserr("openmailer: setuid(%ld) failed", sendmail/deliver.c: /* we have to open the data file BEFORE setuid() */ sendmail/deliver.c: if (setuid(RealUid) < 0 && suidwarn) sendmail/deliver.c: syserr("mailfile: setuid(%ld) failed", (long) RealUid); sendmail/deliver.c: (void) setuid(RealUid); sendmail/main.c: if (setuid(new_uid) < 0) sendmail/main.c: syserr("main: setuid(%d) failed", (int) new_uid); sendmail/main.c: (void) setuid(RealUid); sendmail/main.c: syserr("drop_privileges: second setuid(%d) attempt failed", sendmail/main.c: syserr("drop_privileges: setuid(%d) failed", sendmail/main.c: if (RunAsUid != 0 && setuid(0) == 0) sendmail/main.c: ** allows a non-root process to override setuid() sendmail/main.c: syserr("drop_privileges: setuid(0) succeeded (when it should not)"); sendmail/main.c: else if (RunAsUid != euid && setuid(euid) == 0) sendmail/main.c: ** if a non-root effective-uid calls setuid(real-uid) sendmail/readcf.c: bool can_setuid = RunAsUid == 0; sendmail/readcf.c: if (can_setuid) sendmail/readcf.c: else if (can_setuid) sendmail/readcf.c: if (can_setuid || EffGid == runasgid) sendmail/readcf.c: else if (can_setuid || EffGid == gr->gr_gid) These greps are only a small sample. Changing all these lines of code would be insane. I would instantly introduce bugs, which will haunt me until I finally decide to rewrite the whole thing. This is *not* how emulating works. In your previous mail, you propose the following function to check for 'root' privileges, which an upstream maintainer could put in his code: int is_admin (uid_t uid) { #ifdef __CYGWIN__ return [getgrouplist(uid, ...) contains group 544]; #else [other platform] return [different test]; #else return uid == 0; #endif } But this only introduces a new function which she has to put into multiple locations of the original code. So again, why not just modify the 'getuid' function in cygwin1.dll to return '0' if the current user is actually SYSTEM or one of the administrators? Then you have rock-solid emulation. I would not have to modify a single line of code. Sincerely, Daniel -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple