]> err.no Git - yubikey-server-c/commitdiff
Make this into a real daemon
authorTollef Fog Heen <tfheen@err.no>
Mon, 19 Oct 2009 14:20:24 +0000 (16:20 +0200)
committerTollef Fog Heen <tfheen@err.no>
Mon, 19 Oct 2009 14:20:24 +0000 (16:20 +0200)
Misc fixes to make it setuid/setgid properly, add some rudimentary
help, parsing of a config file and such

src/main.c

index 679d487bc2fc487a0ebd4c9c73f7d97b2fffa101..d21c60f0cc7796381ec71bfd27aca2159bd70440 100644 (file)
@@ -16,9 +16,9 @@
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#define PORT 8000
-
 #define _GNU_SOURCE
+
+#include <errno.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
-#include <microhttpd.h>
-#include <libpq-fe.h>
-#include <yubikey.h>
 #include <time.h>
-#include <gcrypt.h>
+#include <sys/types.h>
 #include <sys/select.h>
 #include <arpa/inet.h>
 #include <syslog.h>
+#include <pwd.h>
+#include <grp.h>
+#include <microhttpd.h>
+#include <libpq-fe.h>
+#include <yubikey.h>
+#include <gcrypt.h>
+
 #include "util.h"
 #include "config.h"
 
@@ -459,22 +463,126 @@ free_mem:
        return MHD_YES;
 }
 
-int main(int UNUSED(argc), char ** UNUSED(argv))
+void print_usage()
+{
+       printf("yubikeyd [-c conffile] [-V] [-f] [-h]\n");
+       printf("\n");
+       printf("-c conffile - use configuration file\n");
+       printf("-V - print version\n");
+       printf("-f - keep in foreground\n");
+       printf("-h - this help\n");
+       exit(0);
+}
+
+void print_version(void)
+{
+       printf("yubikeyd %s\n", VERSION);
+       exit(0);
+}
+
+struct ykc_config {
+       char *pidfile;
+       char *user;
+       int uid;
+       char *group;
+       int gid;
+       char *dbdef;
+       int port;
+};
+
+int parse_config(const char *file, struct ykc_config *c)
+{
+       FILE *f;
+       char line[4096];
+       char *key, *value;
+
+       f = fopen(file, "r");
+
+       while (fgets(line, sizeof(line), f) != NULL) {
+               if (line[0] == '#' || line[0] == '\n')
+                       continue;
+               if ((value = index(line, '\n')) != NULL) {
+                       *value = '\0';
+               }
+               if ((value = index(line, '=')) == NULL) {
+                       /* XXX complain */
+                       continue;
+               }
+               key = line;
+               *value = '\0';
+               value++;
+
+               if (strcmp(key, "pidfile") == 0) {
+                       c->pidfile = strdup(value);
+                       continue;
+               }
+               if (strcmp(key, "user") == 0) {
+                       struct passwd *p;
+                       p = getpwnam(value);
+                       c->user = strdup(value);
+                       c->uid = p->pw_uid;
+                       continue;
+               }
+               if (strcmp(key, "group") == 0) {
+                       struct group *g;
+                       g = getgrnam(value);
+                       c->group = strdup(value);
+                       c->gid = g->gr_gid;
+                       continue;
+               }
+               if (strcmp(key, "dbdef") == 0) {
+                       c->dbdef = strdup(value);
+                       continue;
+               }
+               if (strcmp(key, "port") == 0) {
+                       c->port = strtol(value, NULL, 0);
+                       continue;
+               }
+       }
+       return 0;
+}
+
+int main(int argc, char ** argv)
 {
        struct MHD_Daemon *d;
+       int opt;
+       const char *config;
+       int foreground = 0;
+       struct ykc_config conf;
+       FILE *pidfd;
+
+       while ((opt = getopt(argc, argv, "c:p:vfh")) != -1) {
+         switch (opt) {
+         case 'c':
+           config = optarg;
+           break;
+         case 'f':
+           foreground = 1;
+           break;
+         case 'V':
+           print_version();
+           break;
+         case 'h':
+         default:
+           print_usage();
+           break;
+         }
+       }
 
        openlog("yubikeyd", LOG_PID, LOG_AUTHPRIV);
        syslog(LOG_NOTICE, "yubikeyd version %s starting up", VERSION);
 
-       /* XXX connect args should go in config file */
-       db_conn = PQconnectdb("dbname=yubikey port=5433");
+       /* XXX return value */
+       parse_config(config, &conf);
+
+       db_conn = PQconnectdb(conf.dbdef);
        if (PQstatus(db_conn) != CONNECTION_OK) {
                syslog(LOG_ERR, "connection to database failed: %s",
                       PQerrorMessage(db_conn));
                exit(1);
        }
        d = MHD_start_daemon(MHD_USE_DEBUG,
-                            PORT,
+                            conf.port,
                             NULL, /* Access policy handler */
                             NULL, /* Data to access policy handler */
                             handle_request, /* default handler for all URIs */
@@ -482,8 +590,34 @@ int main(int UNUSED(argc), char ** UNUSED(argv))
                             MHD_OPTION_END);
        if (d == NULL) {
                syslog(LOG_ERR, "could not start daemon, unsure why\n");
+               perror("Error starting yubikeyd");
                exit(1);
        }
+
+       /*XXX return value */
+       if (setregid(conf.gid, conf.gid) < 0) {
+               perror("changing group id");
+               exit(1);
+       }
+       if (setreuid(conf.uid, conf.uid) < 0) {
+               perror("changing group id");
+               exit(1);
+       }
+
+       if (!foreground)
+               daemon(0, 0);
+
+       unlink(conf.pidfile); /* XXX ignore errors? */
+       pidfd = fopen(conf.pidfile, "wx");
+       if (! pidfd) {
+               perror("Error opening pid file");
+               syslog(LOG_ERR, "could not open pid file: %s\n",
+                      strerror(errno));
+               exit(1);
+       }
+       fprintf(pidfd, "%d\n", getpid());
+       fclose(pidfd);
+
        while (1) {
                fd_set rs, ws, es;
                int max_fd = 0;
@@ -517,4 +651,3 @@ int main(int UNUSED(argc), char ** UNUSED(argv))
        PQfinish(db_conn);
        return 0;
 }
-