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