Whamcloud - gitweb
LU-8901 misc: update Intel copyright messages for 2016
[fs/lustre-release.git] / lustre / utils / gss / 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  *
12  * All rights reserved, all wrongs reversed.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  *
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. Neither the name of the University nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
28  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
34  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 <fcntl.h>
47 #include <errno.h>
48
49
50 #include <unistd.h>
51 #include <err.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <signal.h>
56 #include <dirent.h>
57 #include "svcgssd.h"
58 #include "gss_util.h"
59 #include "err_util.h"
60 #include "lsupport.h"
61 #include "lustre_ver.h"
62
63 int null_enabled;
64 int krb_enabled;
65 int sk_enabled;
66
67 void
68 closeall(int min)
69 {
70         DIR *dir = opendir("/proc/self/fd");
71         if (dir != NULL) {
72                 int dfd = dirfd(dir);
73                 struct dirent *d;
74
75                 while ((d = readdir(dir)) != NULL) {
76                         char *endp;
77                         long n = strtol(d->d_name, &endp, 10);
78                         if (*endp != '\0' && n >= min && n != dfd)
79                                 (void) close(n);
80                 }
81                 closedir(dir);
82         } else {
83                 int fd = sysconf(_SC_OPEN_MAX);
84                 while (--fd >= min)
85                         (void) close(fd);
86         }
87 }
88
89 /*
90  * mydaemon creates a pipe between the partent and child
91  * process. The parent process will wait until the
92  * child dies or writes a '1' on the pipe signaling
93  * that it started successfully.
94  */
95 int pipefds[2] = { -1, -1};
96
97 static void
98 mydaemon(int nochdir, int noclose)
99 {
100         int pid, status, tempfd;
101
102         if (pipe(pipefds) < 0) {
103                 printerr(1, "mydaemon: pipe() failed: errno %d (%s)\n",
104                         errno, strerror(errno));
105                 exit(1);
106         }
107         if ((pid = fork ()) < 0) {
108                 printerr(1, "mydaemon: fork() failed: errno %d (%s)\n",
109                         errno, strerror(errno));
110                 exit(1);
111         }
112
113         if (pid != 0) {
114                 /*
115                  * Parent. Wait for status from child.
116                  */
117                 close(pipefds[1]);
118                 if (read(pipefds[0], &status, 1) != 1)
119                         exit(1);
120                 exit (0);
121         }
122         /* Child.       */
123         close(pipefds[0]);
124         setsid ();
125         if (nochdir == 0) {
126                 if (chdir ("/") == -1) {
127                         printerr(1, "mydaemon: chdir() failed: errno %d (%s)\n",
128                                 errno, strerror(errno));
129                         exit(1);
130                 }
131         }
132
133         while (pipefds[1] <= 2) {
134                 pipefds[1] = dup(pipefds[1]);
135                 if (pipefds[1] < 0) {
136                         printerr(1, "mydaemon: dup() failed: errno %d (%s)\n",
137                                 errno, strerror(errno));
138                         exit(1);
139                 }
140         }
141
142         if (noclose == 0) {
143                 tempfd = open("/dev/null", O_RDWR);
144                 dup2(tempfd, 0);
145                 dup2(tempfd, 1);
146                 dup2(tempfd, 2);
147                 closeall(3);
148         }
149
150         return;
151 }
152
153 static void
154 release_parent()
155 {
156         int status;
157         ssize_t sret __attribute__ ((unused));
158
159         if (pipefds[1] > 0) {
160                 sret = write(pipefds[1], &status, 1);
161                 close(pipefds[1]);
162                 pipefds[1] = -1;
163         }
164 }
165
166 void
167 sig_die(int signal)
168 {
169         /* destroy krb5 machine creds */
170         cleanup_mapping();
171         printerr(1, "exiting on signal %d\n", signal);
172         exit(1);
173 }
174
175 void
176 sig_hup(int signal)
177 {
178         /* don't exit on SIGHUP */
179         printerr(1, "Received SIGHUP... Ignoring.\n");
180         return;
181 }
182
183 static void
184 usage(FILE *fp, char *progname)
185 {
186         fprintf(fp, "usage: %s [ -fnvmogk ]\n",
187                 progname);
188         fprintf(stderr, "-f      - Run in foreground\n");
189         fprintf(stderr, "-n      - Don't establish kerberos credentials\n");
190         fprintf(stderr, "-v      - Verbosity\n");
191         fprintf(stderr, "-m      - Service MDS\n");
192         fprintf(stderr, "-o      - Service OSS\n");
193         fprintf(stderr, "-g      - Service MGS\n");
194         fprintf(stderr, "-k      - Enable kerberos support\n");
195 #ifdef HAVE_OPENSSL_SSK
196         fprintf(stderr, "-s      - Enable shared secret key support\n");
197 #endif
198         fprintf(stderr, "-z      - Enable gssnull support\n");
199
200         exit(fp == stderr);
201 }
202
203 int
204 main(int argc, char *argv[])
205 {
206         int get_creds = 1;
207         int fg = 0;
208         int verbosity = 0;
209         int opt;
210         int must_srv_mds = 0, must_srv_oss = 0, must_srv_mgs = 0;
211         char *progname;
212
213         while ((opt = getopt(argc, argv, "fnvmogksz")) != -1) {
214                 switch (opt) {
215                 case 'f':
216                         fg = 1;
217                         break;
218                 case 'n':
219                         get_creds = 0;
220                         break;
221                 case 'v':
222                         verbosity++;
223                         break;
224                 case 'm':
225                         get_creds = 1;
226                         must_srv_mds = 1;
227                         break;
228                 case 'o':
229                         get_creds = 1;
230                         must_srv_oss = 1;
231                         break;
232                 case 'g':
233                         get_creds = 1;
234                         must_srv_mgs = 1;
235                         break;
236                 case 'k':
237                         krb_enabled = 1;
238                         break;
239                 case 'h':
240                         usage(stdout, argv[0]);
241                         break;
242                 case 's':
243 #ifdef HAVE_OPENSSL_SSK
244                         sk_enabled = 1;
245 #else
246                         fprintf(stderr, "error: request for SSK but service "
247                                 "support not enabled\n");
248                         usage(stderr, argv[0]);
249 #endif
250                         break;
251                 case 'z':
252                         null_enabled = 1;
253                         break;
254                 default:
255                         usage(stderr, argv[0]);
256                         break;
257                 }
258         }
259
260         if ((progname = strrchr(argv[0], '/')))
261                 progname++;
262         else
263                 progname = argv[0];
264
265         if (!sk_enabled && !krb_enabled && !null_enabled) {
266 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
267                 fprintf(stderr, "warning: no -k, -s, or -z option given, "
268                         "assume -k for backward compatibility\n");
269                 krb_enabled = 1;
270 #else
271                 fprintf(stderr, "error: need one of -k, -s, or -z options\n");
272                 usage(stderr, argv[0]);
273
274 #endif
275         }
276         initerr(progname, verbosity, fg);
277
278         /* For kerberos use gss mechanisms but ignore for sk and null */
279         if (krb_enabled) {
280                 if (gssd_check_mechs()) {
281                         printerr(0, "ERROR: problem with gssapi library\n");
282                         exit(1);
283                 }
284                 if (gssd_get_local_realm()) {
285                         printerr(0, "ERROR: Can't get Local Kerberos realm\n");
286                         exit(1);
287                 }
288
289                 if (get_creds &&
290                     gssd_prepare_creds(must_srv_mgs, must_srv_mds,
291                                        must_srv_oss)) {
292                         printerr(0, "unable to obtain root (machine) "
293                                  "credentials\n");
294                         printerr(0, "do you have a keytab entry for "
295                                  "<lustre_xxs>/<your.host>@<YOUR.REALM> in "
296                                  "/etc/krb5.keytab?\n");
297                         exit(1);
298                 }
299         }
300
301         if (!fg)
302                 mydaemon(0, 0);
303
304         /*
305          * XXX: There is risk of memory leak for missing call
306          *      cleanup_mapping() for SIGKILL and SIGSTOP.
307          */
308         signal(SIGINT, sig_die);
309         signal(SIGTERM, sig_die);
310         signal(SIGHUP, sig_hup);
311
312         if (!fg)
313                 release_parent();
314
315         gssd_init_unique(GSSD_SVC);
316
317         svcgssd_run();
318         cleanup_mapping();
319         printerr(0, "gssd_run returned!\n");
320         abort();
321 }