1 /* $NetBSD: main.c,v 1.7 2009/08/30 19:24:40 plunky Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: src/usr.sbin/bluetooth/sdpd/main.c,v 1.1 2004/01/20 20:48:26 emax Exp $ 30 */ 31 32 #include <sys/cdefs.h> 33 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc.\ 34 Copyright (c) 2006 Itronix, Inc.\ 35 Copyright (c) 2004 Maksim Yevmenkin m_evmenkin@yahoo.com.\ 36 All rights reserved."); 37 __RCSID("$NetBSD: main.c,v 1.7 2009/08/30 19:24:40 plunky Exp $"); 38 39 #include <errno.h> 40 #include <grp.h> 41 #include <pwd.h> 42 #include <signal.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "sdpd.h" 49 50 #define SDPD "sdpd" 51 52 static bool drop_root (char const *user, char const *group); 53 static void sighandler (int s); 54 static void usage (void); 55 56 static bool done; 57 58 /* 59 * Bluetooth Service Discovery Procotol (SDP) daemon 60 */ 61 62 int 63 main(int argc, char *argv[]) 64 { 65 server_t server; 66 char const *control = SDP_LOCAL_PATH; 67 char const *user = "_sdpd", *group = "_sdpd"; 68 char const *sgroup = NULL; 69 int opt; 70 bool detach = true; 71 struct sigaction sa; 72 73 while ((opt = getopt(argc, argv, "c:dG:g:hu:")) != -1) { 74 switch (opt) { 75 case 'c': /* control */ 76 control = optarg; 77 break; 78 79 case 'd': /* do not detach */ 80 detach = false; 81 break; 82 83 case 'G': /* super group */ 84 sgroup = optarg; 85 break; 86 87 case 'g': /* group */ 88 group = optarg; 89 break; 90 91 case 'u': /* user */ 92 user = optarg; 93 break; 94 95 case 'h': 96 default: 97 usage(); 98 /* NOT REACHED */ 99 } 100 } 101 102 log_open(SDPD, !detach); 103 104 /* Become daemon if required */ 105 if (detach && daemon(0, 0) < 0) { 106 log_crit("Could not become daemon. %s (%d)", 107 strerror(errno), errno); 108 109 exit(EXIT_FAILURE); 110 } 111 112 /* Set signal handlers */ 113 memset(&sa, 0, sizeof(sa)); 114 sa.sa_handler = sighandler; 115 116 if (sigaction(SIGTERM, &sa, NULL) < 0 117 || sigaction(SIGHUP, &sa, NULL) < 0 118 || sigaction(SIGINT, &sa, NULL) < 0) { 119 log_crit("Could not install signal handlers. %s (%d)", 120 strerror(errno), errno); 121 122 exit(EXIT_FAILURE); 123 } 124 125 sa.sa_handler = SIG_IGN; 126 if (sigaction(SIGPIPE, &sa, NULL) < 0) { 127 log_crit("Could not install signal handlers. %s (%d)", 128 strerror(errno), errno); 129 130 exit(EXIT_FAILURE); 131 } 132 133 /* Initialize server */ 134 if (!server_init(&server, control, sgroup)) 135 exit(EXIT_FAILURE); 136 137 if ((user != NULL || group != NULL) && !drop_root(user, group)) 138 exit(EXIT_FAILURE); 139 140 for (done = 0; !done; ) { 141 if (!server_do(&server)) 142 done++; 143 } 144 145 server_shutdown(&server); 146 log_close(); 147 148 exit(EXIT_SUCCESS); 149 } 150 151 /* 152 * Drop root 153 */ 154 155 static bool 156 drop_root(char const *user, char const *group) 157 { 158 int uid, gid; 159 char *ep; 160 161 if ((uid = getuid()) != 0) { 162 log_notice("Cannot set uid/gid. Not a superuser"); 163 return true; /* dont do anything unless root */ 164 } 165 166 gid = getgid(); 167 168 if (user != NULL) { 169 uid = strtol(user, &ep, 10); 170 if (*ep != '\0') { 171 struct passwd *pwd = getpwnam(user); 172 173 if (pwd == NULL) { 174 log_err("No passwd entry for user %s", user); 175 return false; 176 } 177 178 uid = pwd->pw_uid; 179 } 180 } 181 182 if (group != NULL) { 183 gid = strtol(group, &ep, 10); 184 if (*ep != '\0') { 185 struct group *grp = getgrnam(group); 186 187 if (grp == NULL) { 188 log_err("No group entry for group %s", group); 189 return false; 190 } 191 192 gid = grp->gr_gid; 193 } 194 } 195 196 if (setgid(gid) < 0) { 197 log_err("Could not setgid(%s). %s (%d)", group, 198 strerror(errno), errno); 199 200 return false; 201 } 202 203 if (setgroups(0, NULL) < 0) { 204 log_err("Could not setgroups(0). %s (%d)", 205 strerror(errno), errno); 206 207 return false; 208 } 209 210 if (setuid(uid) < 0) { 211 log_err("Could not setuid(%s). %s (%d)", user, 212 strerror(errno), errno); 213 214 return false; 215 } 216 217 return true; 218 } 219 220 /* 221 * Signal handler 222 */ 223 224 static void 225 sighandler(int s) 226 { 227 228 log_notice("Got signal %d. Total number of signals received %d", 229 s, ++done); 230 } 231 232 /* 233 * Display usage information and quit 234 */ 235 236 static void 237 usage(void) 238 { 239 240 fprintf(stderr, "Usage: %s [options]\n" 241 "Where options are:\n" 242 "\t-c specify control socket name (default %s)\n" 243 "\t-d do not detach (run in foreground)\n" 244 "\t-G grp allow privileges to group\n" 245 "\t-g grp specify group\n" 246 "\t-h display usage and exit\n" 247 "\t-u usr specify user\n" 248 "", SDPD, SDP_LOCAL_PATH); 249 250 exit(EXIT_FAILURE); 251 } 252