use new ensc_wrappers/ headers
[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
34 #define ENSC_WRAPPERS_VSERVER   1
35 #define ENSC_WRAPPERS_UNISTD    1
36 #define ENSC_WRAPPERS_FCNTL     1
37 #include <wrappers.h>
38
39 #define MAX_RQSIZE      0x1000
40
41 int wrapper_exit_code = 1;
42
43 struct ArgInfo {
44     xid_t               ctx;
45     uid_t               uid;
46     gid_t               gid;
47     bool                do_fork;
48     char const *        pid_file;
49     char const *        chroot;
50 };
51
52 static struct option const
53 CMDLINE_OPTIONS[] = {
54   { "help",     no_argument,  0, 'h' },
55   { "version",  no_argument,  0, 'v' },
56   { 0,0,0,0 }
57 };
58
59 static void
60 showHelp(int fd, char const *cmd, int res)
61 {
62   WRITE_MSG(fd, "Usage:  ");
63   WRITE_STR(fd, cmd);
64   WRITE_MSG(fd,
65             " [-c <ctx>] [-u <uid>] [-g <gid>] [-r <chroot>] [-n]\n"
66             "Please report bugs to " PACKAGE_BUGREPORT "\n");
67   exit(res);
68 }
69
70 static void
71 showVersion()
72 {
73   WRITE_MSG(1,
74             "rpm-fake-resolver " VERSION " -- NSS resovler for rpm-fake\n"
75             "This program is part of " PACKAGE_STRING "\n\n"
76             "Copyright (C) 2003 Enrico Scholz\n"
77             VERSION_COPYRIGHT_DISCLAIMER);
78   exit(0);
79 }
80
81
82 inline static void
83 parseArgs(struct ArgInfo *args, int argc, char *argv[])
84 {
85   while (1) {
86     int         c = getopt_long(argc, argv, "c:u:g:r:n", CMDLINE_OPTIONS, 0);
87     if (c==-1) break;
88
89     switch (c) {
90       case 'h'          :  showHelp(1, argv[0], 0);
91       case 'v'          :  showVersion();
92
93       case 'c'          :  args->ctx = atoi(optarg); break;
94       case 'u'          :  args->uid = atoi(optarg); break;
95       case 'g'          :  args->gid = atoi(optarg); break;
96       case 'r'          :  args->chroot  = optarg;   break;
97       case 'n'          :  args->do_fork = false;    break;
98       default           :
99         WRITE_MSG(2, "Try '");
100         WRITE_STR(2, argv[0]);
101         WRITE_MSG(2, " --help\" for more information.\n");
102         exit(1);
103         break;
104     }
105   }
106
107   if (optind!=argc) {
108     WRITE_MSG(2, "No further options allowed; aborting ...\n");
109     exit(1);
110   }
111   
112   if (args->chroot==0) {
113     WRITE_MSG(2, "No chroot specified; aborting...\n");
114     exit(1);
115   }
116 }
117
118 static void
119 sendResult(bool state, uint32_t res)
120 {
121   if (state) {
122     static uint8_t      ONE = 1;
123     Ewrite(1, &ONE, sizeof ONE);
124   }
125   else {
126     static uint8_t      ZERO = 0;
127     Ewrite(1, &ZERO, sizeof ZERO);
128   }
129
130   Ewrite(1, &res, sizeof res);
131 }
132
133 static void
134 do_getpwnam()
135 {
136   uint32_t      len;
137   Eread(0, &len, sizeof len);
138
139   if (len<MAX_RQSIZE) {
140     char                buf[len+1];
141     struct passwd *     res;
142     
143     Eread(0, buf, len);
144     buf[len] = '\0';
145     res = getpwnam(buf);
146     if (res!=0) sendResult(true,  res->pw_uid);
147     else        sendResult(false, -1);
148   }
149   // TODO: logging
150 }
151
152 static void
153 do_getgrnam()
154 {
155   uint32_t      len;
156   Eread(0, &len, sizeof len);
157
158   if (len<MAX_RQSIZE) {
159     char                buf[len+1];
160     struct group *      res;
161     
162     Eread(0, buf, len);
163     buf[len] = '\0';
164     res = getgrnam(buf);
165     if (res!=0) sendResult(true,  res->gr_gid);
166     else        sendResult(false, -1);
167   }
168   // TODO: logging
169 }
170
171 static void
172 do_closenss()
173 {
174   uint8_t       what;
175   Eread(0, &what, sizeof what);
176   switch (what) {
177     case 'p'    :  endpwent(); break;
178     case 'g'    :  endgrent(); break;
179     default     :  break;
180   }
181 }
182
183 static void
184 run()
185 {
186   uint8_t       c;
187
188   while (true) {
189     Ewrite(3, ".", 1);
190     Eread (0, &c,  sizeof c);
191     switch (c) {
192       case 'P'  :  do_getpwnam(); break;
193       case 'G'  :  do_getgrnam(); break;
194       case 'Q'  :  exit(0);
195       case 'C'  :  do_closenss(); break;
196       case '.'  :  Ewrite(1, ".", 1); break;
197       default   :  Ewrite(1, "?", 1); break;
198     }
199   }
200 }
201
202 static void
203 daemonize(struct ArgInfo const UNUSED * args, int pid_fd)
204 {
205   int           p[2];
206   pid_t         pid;
207   char          c;
208   
209   Epipe(p);
210   pid = Efork();
211   
212   if (pid!=0) {
213     if (pid_fd!=-1) {
214       char      buf[sizeof(id_t)*3 + 2];
215       size_t    l;
216
217       l = utilvserver_fmt_uint(buf, pid);
218       Ewrite(pid_fd, buf, l);
219       Ewrite(pid_fd, "\n", 1);
220     }
221     _exit(0);
222   }
223   Eclose(p[1]);
224   read(p[0], &c, 1);
225   Eclose(p[0]);
226 }
227
228 int main(int argc, char * argv[])
229 {
230   struct ArgInfo        args = {
231     .ctx      = VC_RANDCTX,
232     .uid      = 99,
233     .gid      = 99,
234     .do_fork  = true,
235     .pid_file = 0,
236     .chroot   = 0
237   };
238   int                   pid_fd = -1;
239
240   parseArgs(&args, argc, argv);
241   if (args.pid_file && args.do_fork)
242     pid_fd = Eopen(args.pid_file, O_CREAT|O_WRONLY, 0644);
243   
244   if (args.chroot) Echroot(args.chroot);
245   Echdir("/");
246
247   //Evc_new_s_context(args.ctx, ~(VC_CAP_SETGID|VC_CAP_SETUID), S_CTX_INFO_LOCK);
248   Evc_new_s_context(args.ctx, 0, S_CTX_INFO_LOCK);
249   Esetgroups(0, &args.gid);
250   Esetgid(args.gid);
251   Esetuid(args.uid);
252
253   if (args.do_fork) daemonize(&args, pid_fd);
254   if (pid_fd!=-1)   close(pid_fd);
255   run();
256 }