]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/gssd/svcgssd.c
mountd: Fix memcmp result comparison error for uuid match.
[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                 if (tempfd >= 0) {
121                         dup2(tempfd, 0);
122                         dup2(tempfd, 1);
123                         dup2(tempfd, 2);
124                         close(tempfd);
125                 } else {
126                         printerr(1, "mydaemon: can't open /dev/null: errno %d "
127                                     "(%s)\n", errno, strerror(errno));
128                         exit(1);
129                 }
130         }
131
132         return;
133 }
134
135 static void
136 release_parent(void)
137 {
138         int status;
139
140         if (pipefds[1] > 0) {
141                 if (write(pipefds[1], &status, 1) != 1) {
142                         printerr(1, 
143                                 "WARN: writing to parent pipe failed: errno %d (%s)\n",
144                                 errno, strerror(errno));
145                 }
146                 close(pipefds[1]);
147                 pipefds[1] = -1;
148         }
149 }
150
151 void
152 sig_die(int signal)
153 {
154         /* destroy krb5 machine creds */
155         printerr(1, "exiting on signal %d\n", signal);
156         exit(1);
157 }
158
159 void
160 sig_hup(int signal)
161 {
162         /* don't exit on SIGHUP */
163         printerr(1, "Received SIGHUP... Ignoring.\n");
164         return;
165 }
166
167 static void
168 usage(char *progname)
169 {
170         fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n",
171                 progname);
172         exit(1);
173 }
174
175 int
176 main(int argc, char *argv[])
177 {
178         int get_creds = 1;
179         int fg = 0;
180         int verbosity = 0;
181         int rpc_verbosity = 0;
182         int idmap_verbosity = 0;
183         int opt;
184         extern char *optarg;
185         char *progname;
186
187         while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
188                 switch (opt) {
189                         case 'f':
190                                 fg = 1;
191                                 break;
192                         case 'i':
193                                 idmap_verbosity++;
194                                 break;
195                         case 'n':
196                                 get_creds = 0;
197                                 break;
198                         case 'v':
199                                 verbosity++;
200                                 break;
201                         case 'r':
202                                 rpc_verbosity++;
203                                 break;
204                         default:
205                                 usage(argv[0]);
206                                 break;
207                 }
208         }
209
210         if ((progname = strrchr(argv[0], '/')))
211                 progname++;
212         else
213                 progname = argv[0];
214
215         initerr(progname, verbosity, fg);
216 #ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
217         if (verbosity && rpc_verbosity == 0)
218                 rpc_verbosity = verbosity;
219         authgss_set_debug_level(rpc_verbosity);
220 #else
221         if (rpc_verbosity > 0)
222                 printerr(0, "Warning: rpcsec_gss library does not "
223                             "support setting debug level\n");
224 #endif
225 #ifdef HAVE_NFS4_SET_DEBUG
226                 if (verbosity && idmap_verbosity == 0)
227                         idmap_verbosity = verbosity;
228         nfs4_set_debug(idmap_verbosity, NULL);
229 #else
230         if (idmap_verbosity > 0)
231                 printerr(0, "Warning: your nfsidmap library does not "
232                             "support setting debug level\n");
233 #endif
234
235         if (gssd_check_mechs() != 0) {
236                 printerr(0, "ERROR: Problem with gssapi library\n");
237                 exit(1);
238         }
239
240         if (!fg)
241                 mydaemon(0, 0);
242
243         signal(SIGINT, sig_die);
244         signal(SIGTERM, sig_die);
245         signal(SIGHUP, sig_hup);
246
247         if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
248                 printerr(0, "unable to obtain root (machine) credentials\n");
249                 printerr(0, "do you have a keytab entry for "
250                             "nfs/<your.host>@<YOUR.REALM> in "
251                             "/etc/krb5.keytab?\n");
252                 exit(1);
253         }
254
255         if (!fg)
256                 release_parent();
257
258         gssd_run();
259         printerr(0, "gssd_run returned!\n");
260         abort();
261 }