Imported Upstream version 0.3.5
[debian/uanytun.git] / src / daemon.h
1 /*
2  *  uAnytun
3  *
4  *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5  *  featured implementation uAnytun has no support for multiple connections
6  *  or synchronisation. It is a small single threaded implementation intended
7  *  to act as a client on small platforms.
8  *  The secure anycast tunneling protocol (satp) defines a protocol used
9  *  for communication between any combination of unicast and anycast
10  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
11  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
12  *  ethernet, ip, arp ...). satp directly includes cryptography and
13  *  message authentication based on the methods used by SRTP.  It is
14  *  intended to deliver a generic, scaleable and secure solution for
15  *  tunneling and relaying of packets of any protocol.
16  *
17  *
18  *  Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
22  *  uAnytun is free software: you can redistribute it and/or modify
23  *  it under the terms of the GNU General Public License as published by
24  *  the Free Software Foundation, either version 3 of the License, or
25  *  any later version.
26  *
27  *  uAnytun is distributed in the hope that it will be useful,
28  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  *  GNU General Public License for more details.
31  *
32  *  You should have received a copy of the GNU General Public License
33  *  along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
34  *
35  *  In addition, as a special exception, the copyright holders give
36  *  permission to link the code of portions of this program with the
37  *  OpenSSL library under certain conditions as described in each
38  *  individual source file, and distribute linked combinations
39  *  including the two.
40  *  You must obey the GNU General Public License in all respects
41  *  for all of the code used other than OpenSSL.  If you modify
42  *  file(s) with this exception, you may extend this exception to your
43  *  version of the file(s), but you are not obligated to do so.  If you
44  *  do not wish to do so, delete this exception statement from your
45  *  version.  If you delete this exception statement from all source
46  *  files in the program, then also delete it here.
47  */
48
49 #ifndef UANYTUN_daemon_h_INCLUDED
50 #define UANYTUN_daemon_h_INCLUDED
51
52 #include <poll.h>
53 #include <fcntl.h>
54 #include <pwd.h>
55 #include <grp.h>
56 #include <sys/wait.h>
57 #include <sys/stat.h>
58 #include <unistd.h>
59
60 struct priv_info_struct {
61   struct passwd* pw_;
62   struct group* gr_;
63 };
64 typedef struct priv_info_struct priv_info_t;
65
66 int priv_init(priv_info_t* priv, const char* username, const char* groupname)
67 {
68   if(!priv)
69     return -1;
70
71   priv->pw_ = NULL;
72   priv->gr_ = NULL;
73
74   priv->pw_ = getpwnam(username);
75   if(!priv->pw_) {
76     log_printf(ERROR, "unknown user %s", username);
77     return -1;
78   }
79
80   if(groupname)
81     priv->gr_ = getgrnam(groupname);
82   else
83     priv->gr_ = getgrgid(priv->pw_->pw_gid);
84
85   if(!priv->gr_) {
86     log_printf(ERROR, "unknown group %s", groupname);
87     return -1;
88   }
89
90   return 0;
91 }
92
93 int priv_drop(priv_info_t* priv)
94 {
95   if(!priv || !priv->pw_ || !priv->gr_) {
96     log_printf(ERROR, "privileges not initialized properly");
97     return -1;
98   }
99
100   if(setgid(priv->gr_->gr_gid))  {
101     log_printf(ERROR, "setgid('%s') failed: %s", priv->gr_->gr_name, strerror(errno));
102     return -1;
103   }
104
105   gid_t gr_list[1];
106   gr_list[0] = priv->gr_->gr_gid;
107   if(setgroups (1, gr_list)) {
108     log_printf(ERROR, "setgroups(['%s']) failed: %s", priv->gr_->gr_name, strerror(errno));
109     return -1;
110   }
111
112   if(setuid(priv->pw_->pw_uid)) {
113     log_printf(ERROR, "setuid('%s') failed: %s", priv->pw_->pw_name, strerror(errno));
114     return -1;
115   }
116
117   log_printf(NOTICE, "dropped privileges to %s:%s", priv->pw_->pw_name, priv->gr_->gr_name);
118   return 0;
119 }
120
121
122 int do_chroot(const char* chrootdir)
123 {
124   if(getuid() != 0) {
125     log_printf(ERROR, "this program has to be run as root in order to run in a chroot");
126     return -1;
127   }
128
129   if(chroot(chrootdir)) {
130     log_printf(ERROR, "can't chroot to %s: %s", chrootdir, strerror(errno));
131     return -1;
132   }
133   log_printf(NOTICE, "we are in chroot jail (%s) now", chrootdir);
134   if(chdir("/")) {
135     log_printf(ERROR, "can't change to /: %s", strerror(errno));
136     return -1;
137   }
138
139   return 0;
140 }
141
142 void daemonize()
143 {
144   pid_t pid;
145
146   pid = fork();
147   if(pid < 0) {
148     log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno));
149     exit(-1);
150   }
151   if(pid) exit(0);
152
153   umask(0);
154
155   if(setsid() < 0) {
156     log_printf(ERROR, "daemonizing failed at setsid(): %s, exitting", strerror(errno));
157     exit(-1);
158   }
159
160   pid = fork();
161   if(pid < 0) {
162     log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno));
163     exit(-1);
164   }
165   if(pid) exit(0);
166
167   if ((chdir("/")) < 0) {
168     log_printf(ERROR, "daemonizing failed at chdir(): %s, exitting", strerror(errno));
169     exit(-1);
170   }
171
172   int fd;
173   for (fd=0;fd<=2;fd++) // close all file descriptors
174     close(fd);
175   fd = open("/dev/null",O_RDWR);        // stdin
176   if(fd == -1)
177     log_printf(WARNING, "can't open stdin (chroot and no link to /dev/null?)");
178   else {
179     if(dup(fd) == -1)   // stdout
180       log_printf(WARNING, "can't open stdout");
181     if(dup(fd) == -1)   // stderr
182       log_printf(WARNING, "can't open stderr");
183   }
184   umask(027);
185 }
186
187 #endif