]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/gssd/svcgssd.c
Set the verbosity level in both the librpcsecgss and
[nfs-utils.git] / utils / gssd / svcgssd.c
1 /*
2   gssd.c
3
4   Copyright (c) 2000 The Regents of the University of Michigan.
5   All rights reserved.
6
7   Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
8   Copyright (c) 2002 Andy Adamson <andros@UMICH.EDU>.
9   Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
10   Copyright (c) 2002 J. Bruce Fields <bfields@UMICH.EDU>.
11   All rights reserved, all wrongs reversed.
12
13   Redistribution and use in source and binary forms, with or without
14   modification, are permitted provided that the following conditions
15   are met:
16
17   1. Redistributions of source code must retain the above copyright
18      notice, this list of conditions and the following disclaimer.
19   2. Redistributions in binary form must reproduce the above copyright
20      notice, this list of conditions and the following disclaimer in the
21      documentation and/or other materials provided with the distribution.
22   3. Neither the name of the University nor the names of its
23      contributors may be used to endorse or promote products derived
24      from this software without specific prior written permission.
25
26   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
27   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
33   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
38 */
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif  /* HAVE_CONFIG_H */
43
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <sys/socket.h>
48 #include <rpc/rpc.h>
49 #include <fcntl.h>
50 #include <errno.h>
51
52
53 #include <unistd.h>
54 #include <err.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <signal.h>
59 #include <nfsidmap.h>
60 #include "nfslib.h"
61 #include "svcgssd.h"
62 #include "gss_util.h"
63 #include "err_util.h"
64
65 /*
66  * mydaemon creates a pipe between the partent and child
67  * process. The parent process will wait until the
68  * child dies or writes a '1' on the pipe signaling
69  * that it started successfully.
70  */
71 int pipefds[2] = { -1, -1};
72
73 static void
74 mydaemon(int nochdir, int noclose)
75 {
76         int pid, status, tempfd;
77
78         if (pipe(pipefds) < 0) {
79                 printerr(1, "mydaemon: pipe() failed: errno %d (%s)\n",
80                         errno, strerror(errno));
81                 exit(1);
82         }
83         if ((pid = fork ()) < 0) {
84                 printerr(1, "mydaemon: fork() failed: errno %d (%s)\n",
85                         errno, strerror(errno));
86                 exit(1);
87         }
88
89         if (pid != 0) {
90                 /*
91                  * Parent. Wait for status from child.
92                  */
93                 close(pipefds[1]);
94                 if (read(pipefds[0], &status, 1) != 1)
95                         exit(1);
96                 exit (0);
97         }
98         /* Child.       */
99         close(pipefds[0]);
100         setsid ();
101         if (nochdir == 0) {
102                 if (chdir ("/") == -1) {
103                         printerr(1, "mydaemon: chdir() failed: errno %d (%s)\n",
104                                 errno, strerror(errno));
105                         exit(1);
106                 }
107         }
108
109         while (pipefds[1] <= 2) {
110                 pipefds[1] = dup(pipefds[1]);
111                 if (pipefds[1] < 0) {
112                         printerr(1, "mydaemon: dup() failed: errno %d (%s)\n",
113                                 errno, strerror(errno));
114                         exit(1);
115                 }
116         }
117
118         if (noclose == 0) {
119                 tempfd = open("/dev/null", O_RDWR);
120                 dup2(tempfd, 0);
121                 dup2(tempfd, 1);
122                 dup2(tempfd, 2);
123                 closeall(3);
124         }
125
126         return;
127 }
128
129 static void
130 release_parent(void)
131 {
132         int status;
133
134         if (pipefds[1] > 0) {
135                 if (write(pipefds[1], &status, 1) != 1) {
136                         printerr(1, 
137                                 "WARN: writing to parent pipe failed: errno %d (%s)\n",
138                                 errno, strerror(errno));
139                 }
140                 close(pipefds[1]);
141                 pipefds[1] = -1;
142         }
143 }
144
145 void
146 sig_die(int signal)
147 {
148         /* destroy krb5 machine creds */
149         printerr(1, "exiting on signal %d\n", signal);
150         exit(1);
151 }
152
153 void
154 sig_hup(int signal)
155 {
156         /* don't exit on SIGHUP */
157         printerr(1, "Received SIGHUP... Ignoring.\n");
158         return;
159 }
160
161 static void
162 usage(char *progname)
163 {
164         fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n",
165                 progname);
166         exit(1);
167 }
168
169 int
170 main(int argc, char *argv[])
171 {
172         int get_creds = 1;
173         int fg = 0;
174         int verbosity = 0;
175         int rpc_verbosity = 0;
176         int idmap_verbosity = 0;
177         int opt;
178         extern char *optarg;
179         char *progname;
180
181         while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
182                 switch (opt) {
183                         case 'f':
184                                 fg = 1;
185                                 break;
186                         case 'i':
187                                 idmap_verbosity++;
188                                 break;
189                         case 'n':
190                                 get_creds = 0;
191                                 break;
192                         case 'v':
193                                 verbosity++;
194                                 break;
195                         case 'r':
196                                 rpc_verbosity++;
197                                 break;
198                         default:
199                                 usage(argv[0]);
200                                 break;
201                 }
202         }
203
204         if ((progname = strrchr(argv[0], '/')))
205                 progname++;
206         else
207                 progname = argv[0];
208
209         initerr(progname, verbosity, fg);
210 #ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
211         if (verbosity && rpc_verbosity == 0)
212                 rpc_verbosity = verbosity;
213         authgss_set_debug_level(rpc_verbosity);
214 #else
215         if (rpc_verbosity > 0)
216                 printerr(0, "Warning: rpcsec_gss library does not "
217                             "support setting debug level\n");
218 #endif
219 #ifdef HAVE_NFS4_SET_DEBUG
220                 if (verbosity && idmap_verbosity == 0)
221                         idmap_verbosity = verbosity;
222         nfs4_set_debug(idmap_verbosity, NULL);
223 #else
224         if (idmap_verbosity > 0)
225                 printerr(0, "Warning: your nfsidmap library does not "
226                             "support setting debug level\n");
227 #endif
228
229         if (gssd_check_mechs() != 0) {
230                 printerr(0, "ERROR: Problem with gssapi library\n");
231                 exit(1);
232         }
233
234         if (!fg)
235                 mydaemon(0, 0);
236
237         signal(SIGINT, sig_die);
238         signal(SIGTERM, sig_die);
239         signal(SIGHUP, sig_hup);
240
241         if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
242                 printerr(0, "unable to obtain root (machine) credentials\n");
243                 printerr(0, "do you have a keytab entry for "
244                             "nfs/<your.host>@<YOUR.REALM> in "
245                             "/etc/krb5.keytab?\n");
246                 exit(1);
247         }
248
249         if (!fg)
250                 release_parent();
251
252         gssd_run();
253         printerr(0, "gssd_run returned!\n");
254         abort();
255 }