]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/gssd/svcgssd.c
mount.nfs: Always preset nfs_mount_version
[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 #include "config.h"
41
42 #include <sys/param.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/socket.h>
46 #include <rpc/rpc.h>
47 #include <fcntl.h>
48 #include <errno.h>
49
50
51 #include <unistd.h>
52 #include <err.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <signal.h>
57 #include <nfsidmap.h>
58 #include "nfslib.h"
59 #include "svcgssd.h"
60 #include "gss_util.h"
61 #include "err_util.h"
62
63 /*
64  * mydaemon creates a pipe between the partent and child
65  * process. The parent process will wait until the
66  * child dies or writes a '1' on the pipe signaling
67  * that it started successfully.
68  */
69 int pipefds[2] = { -1, -1};
70
71 static void
72 mydaemon(int nochdir, int noclose)
73 {
74         int pid, status, tempfd;
75
76         if (pipe(pipefds) < 0) {
77                 printerr(1, "mydaemon: pipe() failed: errno %d (%s)\n",
78                         errno, strerror(errno));
79                 exit(1);
80         }
81         if ((pid = fork ()) < 0) {
82                 printerr(1, "mydaemon: fork() failed: errno %d (%s)\n",
83                         errno, strerror(errno));
84                 exit(1);
85         }
86
87         if (pid != 0) {
88                 /*
89                  * Parent. Wait for status from child.
90                  */
91                 close(pipefds[1]);
92                 if (read(pipefds[0], &status, 1) != 1)
93                         exit(1);
94                 exit (0);
95         }
96         /* Child.       */
97         close(pipefds[0]);
98         setsid ();
99         if (nochdir == 0) {
100                 if (chdir ("/") == -1) {
101                         printerr(1, "mydaemon: chdir() failed: errno %d (%s)\n",
102                                 errno, strerror(errno));
103                         exit(1);
104                 }
105         }
106
107         while (pipefds[1] <= 2) {
108                 pipefds[1] = dup(pipefds[1]);
109                 if (pipefds[1] < 0) {
110                         printerr(1, "mydaemon: dup() failed: errno %d (%s)\n",
111                                 errno, strerror(errno));
112                         exit(1);
113                 }
114         }
115
116         if (noclose == 0) {
117                 tempfd = open("/dev/null", O_RDWR);
118                 dup2(tempfd, 0);
119                 dup2(tempfd, 1);
120                 dup2(tempfd, 2);
121                 closeall(3);
122         }
123
124         return;
125 }
126
127 static void
128 release_parent()
129 {
130         int status;
131
132         if (pipefds[1] > 0) {
133                 write(pipefds[1], &status, 1);
134                 close(pipefds[1]);
135                 pipefds[1] = -1;
136         }
137 }
138
139 void
140 sig_die(int signal)
141 {
142         /* destroy krb5 machine creds */
143         printerr(1, "exiting on signal %d\n", signal);
144         exit(1);
145 }
146
147 void
148 sig_hup(int signal)
149 {
150         /* don't exit on SIGHUP */
151         printerr(1, "Received SIGHUP... Ignoring.\n");
152         return;
153 }
154
155 static void
156 usage(char *progname)
157 {
158         fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n",
159                 progname);
160         exit(1);
161 }
162
163 int
164 main(int argc, char *argv[])
165 {
166         int get_creds = 1;
167         int fg = 0;
168         int verbosity = 0;
169         int rpc_verbosity = 0;
170         int idmap_verbosity = 0;
171         int opt;
172         extern char *optarg;
173         char *progname;
174
175         while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
176                 switch (opt) {
177                         case 'f':
178                                 fg = 1;
179                                 break;
180                         case 'i':
181                                 idmap_verbosity++;
182                                 break;
183                         case 'n':
184                                 get_creds = 0;
185                                 break;
186                         case 'v':
187                                 verbosity++;
188                                 break;
189                         case 'r':
190                                 rpc_verbosity++;
191                                 break;
192                         default:
193                                 usage(argv[0]);
194                                 break;
195                 }
196         }
197
198         if ((progname = strrchr(argv[0], '/')))
199                 progname++;
200         else
201                 progname = argv[0];
202
203         initerr(progname, verbosity, fg);
204 #ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
205         authgss_set_debug_level(rpc_verbosity);
206 #else
207         if (rpc_verbosity > 0)
208                 printerr(0, "Warning: rpcsec_gss library does not "
209                             "support setting debug level\n");
210 #endif
211 #ifdef HAVE_NFS4_SET_DEBUG
212         nfs4_set_debug(idmap_verbosity, NULL);
213 #else
214         if (idmap_verbosity > 0)
215                 printerr(0, "Warning: your nfsidmap library does not "
216                             "support setting debug level\n");
217 #endif
218
219         if (gssd_check_mechs() != 0) {
220                 printerr(0, "ERROR: Problem with gssapi library\n");
221                 exit(1);
222         }
223
224         if (!fg)
225                 mydaemon(0, 0);
226
227         signal(SIGINT, sig_die);
228         signal(SIGTERM, sig_die);
229         signal(SIGHUP, sig_hup);
230
231         if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
232                 printerr(0, "unable to obtain root (machine) credentials\n");
233                 printerr(0, "do you have a keytab entry for "
234                             "nfs/<your.host>@<YOUR.REALM> in "
235                             "/etc/krb5.keytab?\n");
236                 exit(1);
237         }
238
239         if (!fg)
240                 release_parent();
241
242         gssd_run();
243         printerr(0, "gssd_run returned!\n");
244         abort();
245 }