use VC_DYNAMIC_XID instead of VC_RANDCTX
[util-vserver.git] / util-vserver / src / rpm-fake-resolver.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "internal.h"
24 #include "vserver.h"
25 #include "util.h"
26
27 #include <getopt.h>
28 #include <stdlib.h>
29 #include <stdbool.h>
30 #include <grp.h>
31 #include <pwd.h>
32 #include <fcntl.h>
33 #include <errno.h>
34
35 #define ENSC_WRAPPERS_PREFIX    "rpm-fake-resolver: "
36 #define ENSC_WRAPPERS_VSERVER   1
37 #define ENSC_WRAPPERS_UNISTD    1
38 #define ENSC_WRAPPERS_FCNTL     1
39 #include <wrappers.h>
40
41 #define MAX_RQSIZE      0x1000
42
43 int wrapper_exit_code = 1;
44
45 struct ArgInfo {
46     xid_t               ctx;
47     uid_t               uid;
48     gid_t               gid;
49     bool                do_fork;
50     char const *        pid_file;
51     char const *        chroot;
52 };
53
54 static struct option const
55 CMDLINE_OPTIONS[] = {
56   { "help",     no_argument,  0, 'h' },
57   { "version",  no_argument,  0, 'v' },
58   { 0,0,0,0 }
59 };
60
61 static void
62 showHelp(int fd, char const *cmd, int res)
63 {
64   WRITE_MSG(fd, "Usage:  ");
65   WRITE_STR(fd, cmd);
66   WRITE_MSG(fd,
67             " [-c <ctx>] [-u <uid>] [-g <gid>] [-r <chroot>] [-n]\n"
68             "Please report bugs to " PACKAGE_BUGREPORT "\n");
69   exit(res);
70 }
71
72 static void
73 showVersion()
74 {
75   WRITE_MSG(1,
76             "rpm-fake-resolver " VERSION " -- NSS resovler for rpm-fake\n"
77             "This program is part of " PACKAGE_STRING "\n\n"
78             "Copyright (C) 2003 Enrico Scholz\n"
79             VERSION_COPYRIGHT_DISCLAIMER);
80   exit(0);
81 }
82
83
84 inline static void
85 parseArgs(struct ArgInfo *args, int argc, char *argv[])
86 {
87   while (1) {
88     int         c = getopt_long(argc, argv, "c:u:g:r:n", CMDLINE_OPTIONS, 0);
89     if (c==-1) break;
90
91     switch (c) {
92       case 'h'          :  showHelp(1, argv[0], 0);
93       case 'v'          :  showVersion();
94
95       case 'c'          :  args->ctx = atoi(optarg); break;
96       case 'u'          :  args->uid = atoi(optarg); break;
97       case 'g'          :  args->gid = atoi(optarg); break;
98       case 'r'          :  args->chroot  = optarg;   break;
99       case 'n'          :  args->do_fork = false;    break;
100       default           :
101         WRITE_MSG(2, "Try '");
102         WRITE_STR(2, argv[0]);
103         WRITE_MSG(2, " --help\" for more information.\n");
104         exit(1);
105         break;
106     }
107   }
108
109   if (optind!=argc) {
110     WRITE_MSG(2, "No further options allowed; aborting ...\n");
111     exit(1);
112   }
113   
114   if (args->chroot==0) {
115     WRITE_MSG(2, "No chroot specified; aborting...\n");
116     exit(1);
117   }
118 }
119
120 static void
121 sendResult(bool state, uint32_t res)
122 {
123   if (state) {
124     static uint8_t      ONE = 1;
125     Ewrite(1, &ONE, sizeof ONE);
126   }
127   else {
128     static uint8_t      ZERO = 0;
129     Ewrite(1, &ZERO, sizeof ZERO);
130   }
131
132   Ewrite(1, &res, sizeof res);
133 }
134
135 static void
136 do_getpwnam()
137 {
138   uint32_t      len;
139   Eread(0, &len, sizeof len);
140
141   if (len<MAX_RQSIZE) {
142     char                buf[len+1];
143     struct passwd *     res;
144     
145     Eread(0, buf, len);
146     buf[len] = '\0';
147     res = getpwnam(buf);
148     if (res!=0) sendResult(true,  res->pw_uid);
149     else        sendResult(false, -1);
150   }
151   // TODO: logging
152 }
153
154 static void
155 do_getgrnam()
156 {
157   uint32_t      len;
158   Eread(0, &len, sizeof len);
159
160   if (len<MAX_RQSIZE) {
161     char                buf[len+1];
162     struct group *      res;
163     
164     Eread(0, buf, len);
165     buf[len] = '\0';
166     res = getgrnam(buf);
167     if (res!=0) sendResult(true,  res->gr_gid);
168     else        sendResult(false, -1);
169   }
170   // TODO: logging
171 }
172
173 static void
174 do_closenss()
175 {
176   uint8_t       what;
177   Eread(0, &what, sizeof what);
178   switch (what) {
179     case 'p'    :  endpwent(); break;
180     case 'g'    :  endgrent(); break;
181     default     :  break;
182   }
183 }
184
185 static void
186 run()
187 {
188   uint8_t       c;
189
190   while (true) {
191     Ewrite(3, ".", 1);
192     Eread (0, &c,  sizeof c);
193     switch (c) {
194       case 'P'  :  do_getpwnam(); break;
195       case 'G'  :  do_getgrnam(); break;
196       case 'Q'  :  exit(0);
197       case 'C'  :  do_closenss(); break;
198       case '.'  :  Ewrite(1, ".", 1); break;
199       default   :  Ewrite(1, "?", 1); break;
200     }
201   }
202 }
203
204 static void
205 daemonize(struct ArgInfo const UNUSED * args, int pid_fd)
206 {
207   int           p[2];
208   pid_t         pid;
209   char          c;
210   
211   Epipe(p);
212   pid = Efork();
213   
214   if (pid!=0) {
215     if (pid_fd!=-1) {
216       char      buf[sizeof(id_t)*3 + 2];
217       size_t    l;
218
219       l = utilvserver_fmt_uint(buf, pid);
220       Ewrite(pid_fd, buf, l);
221       Ewrite(pid_fd, "\n", 1);
222     }
223     _exit(0);
224   }
225   Eclose(p[1]);
226   read(p[0], &c, 1);
227   Eclose(p[0]);
228 }
229
230 int main(int argc, char * argv[])
231 {
232   struct ArgInfo        args = {
233     .ctx      = VC_DYNAMIC_XID,
234     .uid      = 99,
235     .gid      = 99,
236     .do_fork  = true,
237     .pid_file = 0,
238     .chroot   = 0
239   };
240   int                   pid_fd = -1;
241
242 #ifndef __dietlibc__
243 #  warning  *** rpm-fake-resolver is built against glibc; please do not report errors before trying a dietlibc version ***
244   WRITE_MSG(2,
245             "***  rpm-fake-resolver was built with glibc;  please do  ***\n"
246             "***  not report errors before trying a dietlibc version. ***\n");
247 #endif
248
249   parseArgs(&args, argc, argv);
250   if (args.pid_file && args.do_fork)
251     pid_fd = Eopen(args.pid_file, O_CREAT|O_WRONLY, 0644);
252   
253   if (args.chroot) Echroot(args.chroot);
254   Echdir("/");
255
256   //Evc_new_s_context(args.ctx, ~(VC_CAP_SETGID|VC_CAP_SETUID), S_CTX_INFO_LOCK);
257   Evc_new_s_context(args.ctx, 0, S_CTX_INFO_LOCK);
258   Esetgroups(0, &args.gid);
259   Esetgid(args.gid);
260   Esetuid(args.uid);
261
262   if (args.do_fork) daemonize(&args, pid_fd);
263   if (pid_fd!=-1)   close(pid_fd);
264   run();
265 }