Hello,

As OpenCT is a security component, it best to use least privileged mode, and 
udev allows this now.
The attached patch allows users to run the ifdhandler as none root user.

The configuration file was modified, not the ifdhandler is a node in the 
following format:

#
# Path to ifdhandler
ifdhandler {
        program         = SBINDIR/ifdhandler;
#       user            = openctd;
#       groups = {
#               usb,
#       };
};

I believe this place is correct, but if people want to keep backward 
compatibility I guess
this can be splitted, and keep current ifdhandler key.

The openct-control running from init.d script or udev rule script will fork the 
ifdhandler using
the specified user and set the context to the specified groups. There may be 
more than one
group as there are more than one device type.

It also set the /var/run/openct/status owner to the specified user.

Please review.

Alon.

---

Index: src/tools/openct-control.c
===================================================================
--- src/tools/openct-control.c  (revision 1039)
+++ src/tools/openct-control.c  (working copy)
@@ -93,13 +93,19 @@
 
 static int mgr_init(int argc, char **argv)
 {
+       char *ifdhandler_user = NULL;
+       char *sval;
        int n;
 
        if (argc != 1)
                usage(1);
 
+       /* Get the ifdhandler user so we can set ownership */
+       if (ifd_conf_get_string("ifdhandler.user", &sval) >= 0)
+               ifdhandler_user = sval;
+
        /* Zap the status file */
-       ct_status_clear(OPENCT_MAX_READERS);
+       ct_status_clear(OPENCT_MAX_READERS, ifdhandler_user);
 
        /* Initialize IFD library */
        ifd_init();
Index: src/ifd/utils.c
===================================================================
--- src/ifd/utils.c     (revision 1039)
+++ src/ifd/utils.c     (working copy)
@@ -13,6 +13,9 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
 
 #ifndef __GNUC__
 void ifd_debug(int level, const char *fmt, ...)
@@ -86,6 +89,7 @@
        char *type, *device;
        int argc, n;
        pid_t pid;
+       char *user = NULL;
 
        ifd_debug(1, "driver=%s, devtype=%s, index=%d", driver, devtype, idx);
 
@@ -140,7 +144,50 @@
        n = getdtablesize();
        while (--n > 2)
                close(n);
+       
+       if ((n = ifd_conf_get_string_list("ifdhandler.groups", NULL, 0)) > 0) {
+               char **groups = (char **)calloc(n, sizeof(char *));
+               gid_t *gids = (gid_t *)calloc(n, sizeof(gid_t));
+               int j;
+               if (!groups || !gids) {
+                       ct_error("out of memory");
+                       exit(1);
+               }
+               n = ifd_conf_get_string_list("ifdhandler.groups", groups, n);
+               for (j = 0; j < n; j++) {
+                       struct group *g = getgrnam(groups[j]);
+                       if (g == NULL) {
+                               ct_error("failed to parse group %s", groups[j]);
+                               exit(1);
+                       }
+                       gids[j] = g->gr_gid;
+               }
+               if (setgroups(n-1, &gids[1]) == -1) {
+                       ct_error("failed set groups %m");
+                       exit(1);
+               }
+               if (setgid(gids[0]) == -1) {
+                       ct_error("failed setgid %d %m", gids[0]);
+                       exit(1);
+               }
+               free(groups);
+               free(gids);
+       }
 
+       if (ifd_conf_get_string("ifdhandler.user", &user) >= 0) {
+               struct passwd *p = getpwnam(user);
+
+               if (p == NULL) {
+                       ct_error("failed to parse user %s", user);
+                       exit(1);
+               }
+
+               if (setuid(p->pw_uid) == -1) {
+                       ct_error("failed to set*uid user %s %m", user);
+                       exit(1);
+               }
+       }
+
        execv(ct_config.ifdhandler, (char **)argv);
        ct_error("failed to execute %s: %m", ct_config.ifdhandler);
        exit(1);
Index: src/ifd/init.c
===================================================================
--- src/ifd/init.c      (revision 1039)
+++ src/ifd/init.c      (working copy)
@@ -61,7 +61,7 @@
        if (ifd_conf_get_integer("debug", &ival) >= 0 && ival > ct_config.debug)
                ct_config.debug = ival;
 
-       if (ifd_conf_get_string("ifdhandler", &sval) >= 0)
+       if (ifd_conf_get_string("ifdhandler.program", &sval) >= 0)
                ct_config.ifdhandler = sval;
 
        /* Register all driver information (use hotplug ids) */
Index: src/include/openct/openct.h
===================================================================
--- src/include/openct/openct.h (revision 1039)
+++ src/include/openct/openct.h (working copy)
@@ -91,7 +91,7 @@
                                unsigned short address,
                                const void *send_buf, size_t send_len);
 
-extern int             ct_status_clear(unsigned int);
+extern int             ct_status_clear(unsigned int, const char *);
 extern ct_info_t *     ct_status_alloc_slot(int *);
 extern int             ct_status_update(ct_info_t *);
 
Index: src/ct/status.c
===================================================================
--- src/ct/status.c     (revision 1039)
+++ src/ct/status.c     (working copy)
@@ -10,6 +10,8 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <pwd.h>
 #include <signal.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -61,9 +63,9 @@
        return addr;
 }
 
-int ct_status_clear(unsigned int count)
+int ct_status_clear(unsigned int count, const char *owner)
 {
-       int fd;
+       int fd = -1;
        char status_path[PATH_MAX];
 
        if (!ct_format_path(status_path, PATH_MAX, "status")) {
@@ -75,13 +77,31 @@
            || ftruncate(fd, count * sizeof(ct_info_t)) < 0
            || fchmod(fd, 0644) < 0) {
                ct_error("cannot create %s: %m", status_path);
-               unlink(status_path);
-               if (fd >= 0)
-                       close(fd);
-               return -1;
+               goto error;
        }
 
+       if (owner != NULL) {
+               struct passwd *p = getpwnam(owner);
+
+               if (p == NULL) {
+                       ct_error("cannot parse user %s", owner);
+                       goto error;
+               }
+
+               if (fchown(fd, p->pw_uid, -1) == -1) {
+                       ct_error("cannot chown %s to %s: %m", status_path, 
owner);
+                       goto error;
+               }
+       }
+
        return 0;
+
+error:
+
+       unlink(status_path);
+       if (fd >= 0)
+               close(fd);
+       return -1;
 }
 
 int ct_status(const ct_info_t ** result)
Index: etc/openct.conf.in
===================================================================
--- etc/openct.conf.in  (revision 1039)
+++ etc/openct.conf.in  (working copy)
@@ -3,9 +3,16 @@
 #
 # Enable hot plugging
 hotplug        = yes;
+
 #
 # Path to ifdhandler
-ifdhandler = SBINDIR/ifdhandler;
+ifdhandler {
+       program         = SBINDIR/ifdhandler;
+#      user            = openctd;
+#      groups = {
+#              usb,
+#      };
+};
 
 #
 # Configuration for ifdproxy (if you use it)
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to