nfs-ganesha 1.4
|
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 }