0

I have the following simple python code on Linux

import smtpd
proxy = smtpd.PureProxy(('0.0.0.0',25), None)

which runs fine when run as sudo, but gives an socket.error: [Errno 13] Permission denied error when running as standard user. My question: How can I make this snippet to run with a normal user.

Thanks,

Alex

Alex
  • 41,580
  • 88
  • 260
  • 469
  • 2
    Linux only allows root processes to listen on ports below 1024. At a minimum your process would have to start as root, open the socket, then drop root permissions – Joe Day Sep 11 '12 at 16:45
  • I see... Is there any code snippet showing how this could be done? What I could imagine is to start one python file with sudo (opening the socket, running in the background), and another python code to be able to be run by a normal user using this socket. Is that possible, is there some code? – Alex Sep 11 '12 at 16:50
  • This answer might help: http://stackoverflow.com/questions/1770209/run-child-processes-as-different-user-from-a-long-running-process – Joe Day Sep 11 '12 at 17:01

1 Answers1

2

If you want to bind to port 25 (or any port under 1024) you MUST be root. You can however, change to a different user once the socket bind is complete.

>>> import os
>>> import smtpd
>>> import pwd
>>> uid = pwd.getpwnam('nobody').pw_uid
>>> gid = pwd.getpwnam('nobody').pw_gid
>>> proxy = smtpd.PureProxy(('0.0.0.0',25), None)
>>> os.setgid(gid)
>>> os.setuid(uid)
>>> os.system('whoami')
nobody
0
>>> 

This is, of course, a one way operation. Once you change to another user, you can't change users again.

tMC
  • 18,105
  • 14
  • 62
  • 98
  • This kind of seem to work, but is not answering my question. If I want the impossible, my question will never be answered. But still, even if I use this snippet, I am not able to use the environment variables I have set in my local bash/terminal whatsoever. I will try something completely different to solve my actual problem . Thanks for your answer. – Alex Sep 12 '12 at 06:12
  • 1
    @Alex if you MUST start the process as your user you will have to use a port above 1024. You could create a host based firewall rule (iptables) to forward all traffic from port 25 to the port you bind to above 1024. Please note however, my answer is the accepted or standard way; the way majority of daemons are written. I would suggest you change your implementation to not require environment vars if thats what is preventing you from doing it the 'correct' way. – tMC Sep 12 '12 at 13:05