nfs-ganesha 1.4

svcgssd.c

Go to the documentation of this file.
00001 /*
00002   gssd.c
00003 
00004   Copyright (c) 2000 The Regents of the University of Michigan.
00005   All rights reserved.
00006 
00007   Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
00008   Copyright (c) 2002 Andy Adamson <andros@UMICH.EDU>.
00009   Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
00010   Copyright (c) 2002 J. Bruce Fields <bfields@UMICH.EDU>.
00011   All rights reserved, all wrongs reversed.
00012 
00013   Redistribution and use in source and binary forms, with or without
00014   modification, are permitted provided that the following conditions
00015   are met:
00016 
00017   1. Redistributions of source code must retain the above copyright
00018      notice, this list of conditions and the following disclaimer.
00019   2. Redistributions in binary form must reproduce the above copyright
00020      notice, this list of conditions and the following disclaimer in the
00021      documentation and/or other materials provided with the distribution.
00022   3. Neither the name of the University nor the names of its
00023      contributors may be used to endorse or promote products derived
00024      from this software without specific prior written permission.
00025 
00026   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00027   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00028   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00029   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00030   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00033   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 
00038 */
00039 
00040 #ifdef HAVE_CONFIG_H
00041 #include <config.h>
00042 #endif  /* HAVE_CONFIG_H */
00043 
00044 #include <sys/param.h>
00045 #include <sys/types.h>
00046 #include <sys/stat.h>
00047 #include <sys/socket.h>
00048 #include <rpc/rpc.h>
00049 #include <fcntl.h>
00050 #include <errno.h>
00051 
00052 
00053 #include <unistd.h>
00054 #include <err.h>
00055 #include <stdio.h>
00056 #include <stdlib.h>
00057 #include <string.h>
00058 #include <signal.h>
00059 #include <nfsidmap.h>
00060 #include "nfslib.h"
00061 #include "svcgssd.h"
00062 #include "gss_util.h"
00063 #include "err_util.h"
00064 
00065 /*
00066  * mydaemon creates a pipe between the partent and child
00067  * process. The parent process will wait until the
00068  * child dies or writes a '1' on the pipe signaling
00069  * that it started successfully.
00070  */
00071 int pipefds[2] = { -1, -1};
00072 
00073 static void
00074 mydaemon(int nochdir, int noclose)
00075 {
00076         int pid, status, tempfd;
00077 
00078         if (pipe(pipefds) < 0) {
00079                 printerr(1, "mydaemon: pipe() failed: errno %d (%s)\n",
00080                         errno, strerror(errno));
00081                 exit(1);
00082         }
00083         if ((pid = fork ()) < 0) {
00084                 printerr(1, "mydaemon: fork() failed: errno %d (%s)\n",
00085                         errno, strerror(errno));
00086                 exit(1);
00087         }
00088 
00089         if (pid != 0) {
00090                 /*
00091                  * Parent. Wait for status from child.
00092                  */
00093                 close(pipefds[1]);
00094                 if (read(pipefds[0], &status, 1) != 1)
00095                         exit(1);
00096                 exit (0);
00097         }
00098         /* Child.       */
00099         close(pipefds[0]);
00100         setsid ();
00101         if (nochdir == 0) {
00102                 if (chdir ("/") == -1) {
00103                         printerr(1, "mydaemon: chdir() failed: errno %d (%s)\n",
00104                                 errno, strerror(errno));
00105                         exit(1);
00106                 }
00107         }
00108 
00109         while (pipefds[1] <= 2) {
00110                 pipefds[1] = dup(pipefds[1]);
00111                 if (pipefds[1] < 0) {
00112                         printerr(1, "mydaemon: dup() failed: errno %d (%s)\n",
00113                                 errno, strerror(errno));
00114                         exit(1);
00115                 }
00116         }
00117 
00118         if (noclose == 0) {
00119                 tempfd = open("/dev/null", O_RDWR);
00120                 if (tempfd >= 0) {
00121                         dup2(tempfd, 0);
00122                         dup2(tempfd, 1);
00123                         dup2(tempfd, 2);
00124                         close(tempfd);
00125                 } else {
00126                         printerr(1, "mydaemon: can't open /dev/null: errno %d "
00127                                     "(%s)\n", errno, strerror(errno));
00128                         exit(1);
00129                 }
00130         }
00131 
00132         return;
00133 }
00134 
00135 static void
00136 release_parent(void)
00137 {
00138         int status;
00139 
00140         if (pipefds[1] > 0) {
00141                 if (write(pipefds[1], &status, 1) != 1) {
00142                         printerr(1, 
00143                                 "WARN: writing to parent pipe failed: errno %d (%s)\n",
00144                                 errno, strerror(errno));
00145                 }
00146                 close(pipefds[1]);
00147                 pipefds[1] = -1;
00148         }
00149 }
00150 
00151 void
00152 sig_die(int signal)
00153 {
00154         /* destroy krb5 machine creds */
00155         printerr(1, "exiting on signal %d\n", signal);
00156         exit(1);
00157 }
00158 
00159 void
00160 sig_hup(int signal)
00161 {
00162         /* don't exit on SIGHUP */
00163         printerr(1, "Received SIGHUP(%d)... Ignoring.\n", signal);
00164         return;
00165 }
00166 
00167 static void
00168 usage(char *progname)
00169 {
00170         fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i] [-p principal]\n",
00171                 progname);
00172         exit(1);
00173 }
00174 
00175 int
00176 main(int argc, char *argv[])
00177 {
00178         int get_creds = 1;
00179         int fg = 0;
00180         int verbosity = 0;
00181         int rpc_verbosity = 0;
00182         int idmap_verbosity = 0;
00183         int opt, status;
00184         extern char *optarg;
00185         char *progname;
00186         char *principal = NULL;
00187 
00188         while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
00189                 switch (opt) {
00190                         case 'f':
00191                                 fg = 1;
00192                                 break;
00193                         case 'i':
00194                                 idmap_verbosity++;
00195                                 break;
00196                         case 'n':
00197                                 get_creds = 0;
00198                                 break;
00199                         case 'v':
00200                                 verbosity++;
00201                                 break;
00202                         case 'r':
00203                                 rpc_verbosity++;
00204                                 break;
00205                         case 'p':
00206                                 principal = optarg;
00207                                 break;
00208                         default:
00209                                 usage(argv[0]);
00210                                 break;
00211                 }
00212         }
00213 
00214         if ((progname = strrchr(argv[0], '/')))
00215                 progname++;
00216         else
00217                 progname = argv[0];
00218 
00219         initerr(progname, verbosity, fg);
00220 #ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
00221         if (verbosity && rpc_verbosity == 0)
00222                 rpc_verbosity = verbosity;
00223         authgss_set_debug_level(rpc_verbosity);
00224 #else
00225         if (rpc_verbosity > 0)
00226                 printerr(0, "Warning: rpcsec_gss library does not "
00227                             "support setting debug level\n");
00228 #endif
00229 #ifdef HAVE_NFS4_SET_DEBUG
00230                 if (verbosity && idmap_verbosity == 0)
00231                         idmap_verbosity = verbosity;
00232         nfs4_set_debug(idmap_verbosity, NULL);
00233 #else
00234         if (idmap_verbosity > 0)
00235                 printerr(0, "Warning: your nfsidmap library does not "
00236                             "support setting debug level\n");
00237 #endif
00238 
00239         if (gssd_check_mechs() != 0) {
00240                 printerr(0, "ERROR: Problem with gssapi library\n");
00241                 exit(1);
00242         }
00243 
00244         if (!fg)
00245                 mydaemon(0, 0);
00246 
00247         signal(SIGINT, sig_die);
00248         signal(SIGTERM, sig_die);
00249         signal(SIGHUP, sig_hup);
00250 
00251         if (get_creds) {
00252                 if (principal)
00253                         status = gssd_acquire_cred(principal, 
00254                                 ((const gss_OID)GSS_C_NT_USER_NAME));
00255                 else
00256                         status = gssd_acquire_cred(GSSD_SERVICE_NAME, 
00257                                 (const gss_OID)GSS_C_NT_HOSTBASED_SERVICE);
00258                 if (status == FALSE) {
00259                         printerr(0, "unable to obtain root (machine) credentials\n");
00260                         printerr(0, "do you have a keytab entry for "
00261                                 "nfs/<your.host>@<YOUR.REALM> in "
00262                                 "/etc/krb5.keytab?\n");
00263                         exit(1);
00264                 }
00265         } else {
00266                 status = gssd_acquire_cred(NULL,
00267                         (const gss_OID)GSS_C_NT_HOSTBASED_SERVICE);
00268                 if (status == FALSE) {
00269                         printerr(0, "unable to obtain nameless credentials\n");
00270                         exit(1);
00271                 }
00272         }
00273 
00274         if (!fg)
00275                 release_parent();
00276 
00277         nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
00278         gssd_run();
00279         printerr(0, "gssd_run returned!\n");
00280         abort();
00281 }