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