OpenDNSSEC-enforcer
1.3.8
|
00001 /* 00002 * $Id: daemon.c 6307 2012-05-04 09:36:03Z jerry $ 00003 * 00004 * Copyright (c) 2008-2009 Nominet UK. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00029 /* 00030 * daemon.c code needed to get a daemon up and running 00031 * 00032 * edit the DAEMONCONFIG and cmlParse function 00033 * in daemon_util.[c|h] to add options specific 00034 * to your app 00035 * 00036 * gcc -o daemon daemon_util.c daemon.c 00037 * 00038 * Most of this is based on stuff I have seen in NSD 00039 */ 00040 00041 #include "config.h" 00042 00043 #include <sys/types.h> 00044 #include <sys/param.h> 00045 #include <syslog.h> 00046 #include <stdarg.h> 00047 #include <errno.h> 00048 #include <unistd.h> 00049 #include <fcntl.h> 00050 #include <stdlib.h> 00051 #include <string.h> 00052 #include <signal.h> 00053 00054 #include "daemon.h" 00055 #include "daemon_util.h" 00056 #include "privdrop.h" 00057 00058 #include "ksm/ksm.h" 00059 #include "ksm/dbsmsg.h" 00060 #include "ksm/dbsdef.h" 00061 #include "ksm/kmemsg.h" 00062 #include "ksm/kmedef.h" 00063 #include "ksm/message.h" 00064 #include "ksm/string_util.h" 00065 00066 #ifndef MAXPATHLEN 00067 # define MAXPATHLEN 4096 00068 #endif 00069 00070 extern int server_init(DAEMONCONFIG *config); 00071 extern void server_main(DAEMONCONFIG *config); 00072 00073 DAEMONCONFIG config; 00074 00075 void 00076 sig_handler (int sig) 00077 { 00078 switch (sig) { 00079 case SIGCHLD: 00080 return; 00081 case SIGHUP: 00082 return; 00083 case SIGALRM: 00084 break; 00085 case SIGILL: 00086 break; 00087 case SIGUSR1: 00088 break; 00089 case SIGINT: 00090 config.term = 2; 00091 break; 00092 case SIGTERM: 00093 config.term = 1; 00094 break; 00095 default: 00096 break; 00097 } 00098 } 00099 00100 void 00101 exit_function(void) 00102 { 00103 unlink(config.pidfile); 00104 } 00105 00106 int 00107 main(int argc, char *argv[]){ 00108 int fd; 00109 struct sigaction action; 00110 const char* program; /* Temporary for program name */ 00111 00112 config.debug = false; 00113 config.once = false; 00114 00115 config.pidfile = NULL; 00116 config.program = NULL; 00117 config.host = NULL; 00118 config.port = NULL; 00119 config.user = (unsigned char *)calloc(MAX_USER_LENGTH, sizeof(char)); 00120 config.password = (unsigned char *)calloc(MAX_PASSWORD_LENGTH, sizeof(char)); 00121 config.schema = (unsigned char *)calloc(MAX_SCHEMA_LENGTH, sizeof(char)); 00122 config.DSSubmitCmd = (char *)calloc(MAXPATHLEN + 1024, sizeof(char)); 00123 00124 if (config.user == NULL || config.password == NULL || config.schema == NULL) { 00125 log_msg(&config, LOG_ERR, "Malloc for config struct failed"); 00126 exit(1); 00127 } 00128 config.term = 0; 00129 00130 /* Lets set up the logging first */ 00131 /* The program name is the last component of the program file name */ 00132 if ((program = strrchr(argv[0], '/'))) { /* EQUALS */ 00133 ++program; /* Point to character after last "/" */ 00134 } 00135 else { 00136 program = argv[0]; /* No slash, so use string given */ 00137 } 00138 config.program = program; 00139 config.log_user = DEFAULT_LOG_FACILITY; 00140 00141 log_init(config.log_user, config.program); 00142 00143 /* useful message */ 00144 log_msg(&config, LOG_INFO, "%s starting...", PACKAGE_NAME); 00145 00146 #ifdef ENFORCER_TIMESHIFT 00147 if (getenv("ENFORCER_TIMESHIFT")) { 00148 log_msg(&config, LOG_INFO, "Timeshift mode detected, running once only!"); 00149 fprintf(stderr, "WARNING: Timeshift mode detected, running once only!\n"); 00150 config.once = true; 00151 config.debug = true; 00152 } 00153 #endif /* ENFORCER_TIMESHIFT */ 00154 00155 /* Process command line */ 00156 cmdlParse(&config, &argc, argv); 00157 if(config.debug) log_msg(&config, LOG_INFO, "%s DEBUG ON.", PACKAGE_NAME); 00158 00159 /* If we dont debug then fork */ 00160 if(!config.debug){ 00161 /* Fork */ 00162 switch ((config.pid = fork())) { 00163 case 0: 00164 break; 00165 case -1: 00166 log_msg(&config, LOG_ERR, "fork failed: %s", strerror(errno)); 00167 unlink(config.pidfile); 00168 exit(1); 00169 default: 00170 fprintf(stdout, "OpenDNSSEC ods-enforcerd started (version %s), pid %d\n", PACKAGE_VERSION, (int) config.pid); 00171 log_msg(&config, LOG_INFO, "%s Parent exiting...", PACKAGE_NAME); 00172 exit(0); 00173 } 00174 00175 /* Detach ourselves... */ 00176 if (setsid() == -1) { 00177 log_msg(&config, LOG_ERR, "setsid() failed: %s", strerror(errno)); 00178 exit(1); 00179 } 00180 00181 if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { 00182 (void)dup2(fd, STDIN_FILENO); 00183 (void)dup2(fd, STDOUT_FILENO); 00184 (void)dup2(fd, STDERR_FILENO); 00185 if (fd > 2) 00186 (void)close(fd); 00187 } 00188 log_msg(&config, LOG_INFO, "%s forked OK...", PACKAGE_NAME); 00189 } else { 00190 log_msg(&config, LOG_INFO, "%s in debug mode - not forking...", PACKAGE_NAME); 00191 } 00192 00193 action.sa_handler = sig_handler; 00194 sigfillset(&action.sa_mask); 00195 action.sa_flags = 0; 00196 sigaction(SIGTERM, &action, NULL); 00197 sigaction(SIGHUP, &action, NULL); 00198 sigaction(SIGINT, &action, NULL); 00199 sigaction(SIGILL, &action, NULL); 00200 sigaction(SIGUSR1, &action, NULL); 00201 sigaction(SIGALRM, &action, NULL); 00202 sigaction(SIGCHLD, &action, NULL); 00203 action.sa_handler = SIG_IGN; 00204 sigaction(SIGPIPE, &action, NULL); 00205 00206 /* Get perms that we will be dropping to */ 00207 if (getPermsForDrop(&config) != 0) { 00208 exit(1); 00209 } 00210 00211 /* Run the server specific code. You need to provide this function somewhere 00212 this sets our pidfile */ 00213 if (server_init(&config) != 0) { 00214 exit(1); 00215 } 00216 00217 /* make the directory for the pidfile if required; do this before we drop 00218 privs */ 00219 if (createPidDir(&config) != 0) { 00220 exit(1); 00221 } 00222 00223 /* 00224 * Drop permissions. 00225 * This function exits if something goes wrong 00226 */ 00227 privdrop(config.username, config.groupname, NULL); 00228 00229 config.uid = geteuid(); 00230 config.gid = getegid(); 00231 config.pid = getpid(); 00232 00233 atexit(exit_function); 00234 00235 log_msg(&config, LOG_NOTICE, "%s started (version %s), pid %d", PACKAGE_NAME, PACKAGE_VERSION, 00236 (int) config.pid); 00237 00238 MsgInit(); 00239 MsgRegister(KME_MIN_VALUE, KME_MAX_VALUE, m_messages, ksm_log_msg); 00240 MsgRegister(DBS_MIN_VALUE, DBS_MAX_VALUE, d_messages, ksm_log_msg); 00241 00242 /* Do something. You need to provide this function somewhere */ 00243 server_main(&config); 00244 00245 /* Free stuff here (exit from sigs pass through) */ 00246 MsgRundown(); 00247 if (config.host) free(config.host); 00248 if (config.port) free(config.port); 00249 free(config.user); 00250 free(config.password); 00251 free(config.schema); 00252 free(config.DSSubmitCmd); 00253 00254 StrFree(config.username); 00255 StrFree(config.groupname); 00256 #if 0 00257 StrFree(config.chrootdir); 00258 #endif 00259 00260 exit(0); 00261 00262 } 00263