LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Security
User Name
Password
Linux - Security This forum is for all security related questions.
Questions, tips, system compromises, firewalls, etc. are all included here.

Notices


Reply
  Search this Thread
Old 09-08-2006, 02:46 PM   #1
LinuxGeek
Member
 
Registered: Jun 2002
Posts: 302

Rep: Reputation: 31
How to Open Privileged Ports?


Hi,
I was just wondering how applications such as Apache, Bind, etc. open privileged ports and then drop privilieges. I know that Apache has a root process that's always running, but bind opens port 53 and then drops privileges. Does the application start up as root and then change it's uid/gid through some system call? Thanks for your help.
 
Old 09-08-2006, 02:59 PM   #2
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
apache has a something in httpd.conf wherein the original httpd runs as root but the user of the httpd that users attach to from browsers is different. (You REALLY want to do that - otherwise browsers get root access to your server.) I forget the setting off the top of my head.

named (BIND/DNS) typically is started with the -u option to specify what user to run. From the man page of named:
Quote:
-u user
setuid() to user after completing privileged operations, such
as creating sockets that listen on privileged ports.
The above tells you it runs as the user you specified but only AFTER it has opened port 53 or other privileged ports.
 
Old 09-08-2006, 04:18 PM   #3
win32sux
LQ Guru
 
Registered: Jul 2003
Location: Los Angeles
Distribution: Ubuntu
Posts: 9,870

Rep: Reputation: 380Reputation: 380Reputation: 380Reputation: 380
Quote:
Originally Posted by jlightner
apache has a something in httpd.conf wherein the original httpd runs as root but the user of the httpd that users attach to from browsers is different. (You REALLY want to do that - otherwise browsers get root access to your server.) I forget the setting off the top of my head.

named (BIND/DNS) typically is started with the -u option to specify what user to run. From the man page of named:


The above tells you it runs as the user you specified but only AFTER it has opened port 53 or other privileged ports.
i'm pretty sure the OP already knows all this... i think what he's asking is exactly how the change is done - at system level... sounds like he might be trying to implement this behavior in a program he's written or something like that...
 
Old 09-09-2006, 12:32 AM   #4
LinuxGeek
Member
 
Registered: Jun 2002
Posts: 302

Original Poster
Rep: Reputation: 31
Thanks for your replies. What I'm looking for is the actual mechanism. Is there a system call that changes the process's ownership? Kind of like chown but for processes instead of files or is more of an su?
 
Old 09-09-2006, 01:07 AM   #5
win32sux
LQ Guru
 
Registered: Jul 2003
Location: Los Angeles
Distribution: Ubuntu
Posts: 9,870

Rep: Reputation: 380Reputation: 380Reputation: 380Reputation: 380
sounds like your best bet (while you wait for a reply from someone who knows about the inner workings of this stuff) might be to take a look at some source code... i'd suggest dnsmasq, as it's a rather small program... it binds to port 53/UDP as root and then changes to a non-root user... the code is available here:

http://www.thekelleys.org.uk/dnsmasq...sq-2.33.tar.gz

i took a look at the dnsmasq.c file, and i think this is the part that takes care of the binding and dropping of root privilages (keep in mind i know nothing about programming):
Code:
  else
    {
      FILE *pidfile;
      struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
      fd_set test_set;
      int maxfd, i; 
      int nullfd = open("/dev/null", O_RDWR);

#ifdef HAVE_LINUX_NETWORK
      cap_user_header_t hdr = NULL;
      cap_user_data_t data = NULL; 
      
      /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
	 CAP_NET_RAW (for icmp) if we're doing dhcp */
      if (ent_pw && ent_pw->pw_uid != 0)
	{
	  hdr = safe_malloc(sizeof(*hdr));
	  data = safe_malloc(sizeof(*data));
	  hdr->version = _LINUX_CAPABILITY_VERSION;
	  hdr->pid = 0; /* this process */
	  data->effective = data->permitted = data->inheritable =
	    (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
	    (1 << CAP_SETGID) | (1 << CAP_SETUID);
	  	  
	  /* Tell kernel to not clear capabilities when dropping root */
	  if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
	    {
	      bad_capabilities = errno;
	      ent_pw = NULL;
	    }
	}
#endif

      FD_ZERO(&test_set);
      maxfd = set_dns_listeners(daemon, &test_set, -1);
#ifdef HAVE_DBUS
      maxfd = set_dbus_listeners(daemon, maxfd, &test_set, &test_set, &test_set);
#endif
      
      /* The following code "daemonizes" the process.
	 See Stevens section 12.4 */
      
#ifndef NO_FORK
      if (!(daemon->options & OPT_NO_FORK))
	{
	  if (fork() != 0 )
	    _exit(0);
	  
	  setsid();
	  
	  if (fork() != 0)
	    _exit(0);
	}
#endif
      
      chdir("/");
      umask(022); /* make pidfile 0644 */
      
      /* write pidfile _after_ forking ! */
      if (daemon->runfile && (pidfile = fopen(daemon->runfile, "w")))
      	{
	  fprintf(pidfile, "%d\n", (int) getpid());
	  fclose(pidfile);
	}
      
      umask(0);

      for (i=0; i<64; i++)
	{
	  if (i == piperead || i == pipewrite)
	    continue;

#ifdef HAVE_LINUX_NETWORK
	  if (i == daemon->netlinkfd)
	    continue;
#endif
	  
	  if (daemon->dhcp && 
	      ((daemon->lease_stream && i == fileno(daemon->lease_stream)) || 
#ifndef HAVE_LINUX_NETWORK
	       i == daemon->dhcp_raw_fd ||
	       i == daemon->dhcp_icmp_fd ||
#endif
	       i == daemon->dhcpfd))
	    continue;

	  if (i <= maxfd && FD_ISSET(i, &test_set))
	    continue;

	  /* open  stdout etc to /dev/null */
	  if (i == STDOUT_FILENO || i == STDERR_FILENO || i == STDIN_FILENO)
	    dup2(nullfd, i);
	  else
	    close(i);
	}

      if (daemon->groupname || ent_pw)
	{
	  gid_t dummy;
	  struct group *gp;
	  
	  /* change group for /etc/ppp/resolv.conf otherwise get the group for "nobody" */
	  if ((daemon->groupname && (gp = getgrnam(daemon->groupname))) || 
	      (ent_pw && (gp = getgrgid(ent_pw->pw_gid))))
	    {
	      /* remove all supplimentary groups */
	      setgroups(0, &dummy);
	      setgid(gp->gr_gid);
	    } 
	}

      if (ent_pw && ent_pw->pw_uid != 0)
	{
	  /* finally drop root */
	  setuid(ent_pw->pw_uid);
	  
#ifdef HAVE_LINUX_NETWORK
	  data->effective = data->permitted = 
	    (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
	  data->inheritable = 0;
	  
	  /* lose the setuid and setgid capbilities */
	  capset(hdr, data);
#endif
	}

      openlog("dnsmasq", LOG_PID, daemon->log_fac);
    }
 
Old 09-09-2006, 01:58 PM   #6
randyding
Member
 
Registered: May 2004
Posts: 552

Rep: Reputation: 31
If you have a program that's setuid root, your process can "drop privilages" and become owned by the user that invoked the program by doing this.
Code:
setgid(getgid());
setuid(getuid());
Notice setting gid first is necessary because after you change uid you can no longer change gid (you lost privilages to do so).

On the other hand if the program is started by root, such is the case when its started from an init.d script, then instead of specifying getgid() and getuid(), preplace these with the user id of the user you want the program to run as (from cmdline -u <userid> option normally).
 
Old 09-10-2006, 08:37 AM   #7
LinuxGeek
Member
 
Registered: Jun 2002
Posts: 302

Original Poster
Rep: Reputation: 31
Thanks a lot
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Cannot Open Mail Server Ports 25, 110, and 220. Other Ports will open. Binxter Linux - Newbie 9 11-29-2007 02:03 AM
open ports on linksys, i have ssh open but thats it PlatinumRik Linux - Security 1 07-07-2005 10:38 AM
Privileged ports can only be forwarded by root??? sovietpower Linux - Networking 1 03-10-2005 05:45 AM
using privileged ports below 1024 not possible AS ROOT??? flipper333 Slackware 2 01-23-2004 07:35 PM
Change UID of process/Privileged ports syntac Linux - General 1 04-17-2003 07:07 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Security

All times are GMT -5. The time now is 08:03 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration