diff --git a/kcontrol/tdm/tdm-appear.cpp b/kcontrol/tdm/tdm-appear.cpp index cdd5f2fc9..990270123 100644 --- a/kcontrol/tdm/tdm-appear.cpp +++ b/kcontrol/tdm/tdm-appear.cpp @@ -21,7 +21,9 @@ #include #include - +#include +#include +#include #include #include @@ -47,11 +49,14 @@ #include "tdm-appear.h" #include "kbackedcombobox.h" +#include "config.h" + extern KSimpleConfig *config; +#define TSAK_LOCKFILE "/tmp/tdesocket-global/tsak.lock" TDMAppearanceWidget::TDMAppearanceWidget(TQWidget *parent, const char *name) - : TQWidget(parent, name) + : TQWidget(parent, name), sakwarning(0) { TQString wtstr; @@ -247,6 +252,13 @@ TDMAppearanceWidget::TDMAppearanceWidget(TQWidget *parent, const char *name) TQGridLayout *hbox2 = new TQGridLayout( group->layout(), 2, 2, KDialog::spacingHint() ); hbox2->setColStretch(1, 1); hbox2->addWidget(sakbox, 1, 0); + if (getuid() == 0 && config->checkConfigFilesWritable( true )) { + if (system(KDE_BINDIR "/tsak checkdeps") != 0) { + sakbox->setEnabled(false); + sakwarning = new TQLabel( i18n("Secure Attention Key support is not available on your system. Please check for the presence of evdev and uinput."), group ); + hbox2->addWidget(sakwarning, 2, 0); + } + } wtstr = i18n("Here you can enable or disable the Secure Attention Key [SAK] anti-spoofing measure."); TQWhatsThis::add( sakbox, wtstr ); @@ -465,6 +477,21 @@ void TDMAppearanceWidget::save() config->writeEntry("Language", langcombo->current()); config->writeEntry("UseSAK", sakbox->isChecked()); + + // Enable/disable tsak as needed + if (sakbox->isChecked()) { + system(KDE_BINDIR "/tsak"); + } + else { + // Get PID + TQFile file(TSAK_LOCKFILE); + if (file.open(IO_ReadOnly)) { + TQTextStream stream(&file); + unsigned long tsakpid = stream.readLine().toULong(); + file.close(); + kill(tsakpid, SIGTERM); + } + } } @@ -516,7 +543,12 @@ void TDMAppearanceWidget::load() langcombo->setCurrentItem(config->readEntry("Language", "C")); // See if the SAK is enabled - sakbox->setChecked(config->readBoolEntry("UseSAK", true)); + if (sakwarning) { + sakbox->setChecked(config->readBoolEntry("UseSAK", true)); + } + else { + sakbox->setChecked(false); + } } diff --git a/kcontrol/tdm/tdm-appear.h b/kcontrol/tdm/tdm-appear.h index 0d4047e10..8ae739c2f 100644 --- a/kcontrol/tdm/tdm-appear.h +++ b/kcontrol/tdm/tdm-appear.h @@ -91,6 +91,7 @@ private: KBackedComboBox *echocombo; KLanguageButton *langcombo; TQCheckBox *sakbox; + TQLabel *sakwarning; }; diff --git a/tsak/main.cpp b/tsak/main.cpp index f06fb9184..f0fe3b1a3 100644 --- a/tsak/main.cpp +++ b/tsak/main.cpp @@ -21,6 +21,7 @@ License along with tsak. If not, see http://www.gnu.org/licenses/. #include #include +#include #include #include #include @@ -38,6 +39,8 @@ License along with tsak. If not, see http://www.gnu.org/licenses/. #include #include +using namespace std; + #define FIFO_DIR "/tmp/tdesocket-global" #define FIFO_FILE_OUT "/tmp/tdesocket-global/tsak" #define FIFO_LOCKFILE_OUT "/tmp/tdesocket-global/tsak.lock" @@ -94,6 +97,38 @@ int bit_set(size_t i, const byte* a) return a[i/CHAR_BIT] & (1 << i%CHAR_BIT); } +/* exception handling */ +struct exit_exception { + int c; + exit_exception(int c):c(c) { } +}; + +/* signal handler */ +void signal_callback_handler(int signum) +{ + // Terminate program + throw exit_exception(signum); + exit(signum); +} + +/* termination handler */ +void tsak_friendly_termination() { + int i; + + // Close down all child processes + for (i=0; i -1) { + if (writepid) { + // Write my PID to the file + pid_t tsakpid = getpid(); + char pidstring[1024]; + sprintf(pidstring, "%d", tsakpid); + write(mPipe_lockfd_out, pidstring, strlen(pidstring)); + } // Set the exclusive file lock return setFileLock(mPipe_lockfd_out, true); } @@ -343,8 +385,8 @@ PipeHandler::~PipeHandler() { if (active) { tearDownPipe(); + tearDownLockingPipe(); } - tearDownLockingPipe(); } int main (int argc, char *argv[]) @@ -360,291 +402,319 @@ int main (int argc, char *argv[]) bool hide_event = false; bool established = false; bool testrun = false; + bool depcheck = false; int current_keyboard; bool can_proceed; // Ignore SIGPIPE signal(SIGPIPE, SIG_IGN); - for (i=0; i0) { - return 4; - } - sleep(1); - restart_tsak(); + // Create the output pipe + PipeHandler controlpipe; + if (depcheck == false) { + if (!setupPipe()) { + fprintf(stderr, "Another instance of this program is already running\n"); + return 8; } } - else { - fprintf(stderr, "Found %d keyboard(s)\n", keyboard_fd_num); - - can_proceed = true; - for (current_keyboard=0;current_keyboard0) { + return 4; + } + sleep(1); + restart_tsak(); } } + else { + fprintf(stderr, "Found %d keyboard(s)\n", keyboard_fd_num); - if (can_proceed == true) { + can_proceed = true; for (current_keyboard=0;current_keyboard0) { - child_pids[current_keyboard] = i; - continue; - } - setupLockingPipe(); + ioctl(keyboard_fds[current_keyboard], EVIOCGNAME(UINPUT_MAX_NAME_SIZE), devinfo.name); + strncat(devinfo.name, "+tsak", UINPUT_MAX_NAME_SIZE-1); + fprintf(stderr, "%s\n", devinfo.name); + ioctl(keyboard_fds[current_keyboard], EVIOCGID, &devinfo.id); + + copy_features(keyboard_fds[current_keyboard], devout[current_keyboard]); + if (write(devout[current_keyboard],&devinfo,sizeof(devinfo)) < 0) { + fprintf(stderr, "Unable to write to output device\n"); } - - established = true; - - if (testrun == true) { - return 0; + if (ioctl(devout[current_keyboard],UI_DEV_CREATE)<0) { + fprintf(stderr, "Unable to create input device with UI_DEV_CREATE\n"); + if (established) + sleep(1); + else + return 2; } + else { + fprintf(stderr, "Device created.\n"); + + if (established == false) { + int i=fork(); + if (i<0) return 9; // fork failed + if (i>0) { + child_pids[current_keyboard] = i; + continue; + } + setupLockingPipe(false); + } - while (1) { - if ((rd = read (keyboard_fds[current_keyboard], ev, size)) < size) { - fprintf(stderr, "Read failed.\n"); - break; + established = true; + + if (testrun == true) { + return 0; } - // Replicate LED events from the virtual keyboard to the physical keyboard - int rrd = read(devout[current_keyboard], &revev, size); - if (rrd >= size) { - if (revev.type == EV_LED) { - if (write(keyboard_fds[current_keyboard], &revev, sizeof(revev)) < 0) { - fprintf(stderr, "Unable to replicate LED event\n"); + while (1) { + if ((rd = read (keyboard_fds[current_keyboard], ev, size)) < size) { + fprintf(stderr, "Read failed.\n"); + break; + } + + // Replicate LED events from the virtual keyboard to the physical keyboard + int rrd = read(devout[current_keyboard], &revev, size); + if (rrd >= size) { + if (revev.type == EV_LED) { + if (write(keyboard_fds[current_keyboard], &revev, sizeof(revev)) < 0) { + fprintf(stderr, "Unable to replicate LED event\n"); + } } } - } - value = ev[0].value; + value = ev[0].value; - if (ev[0].value == 0 && ev[0].type == 1) { // Read the key release event - if (keycode[(ev[0].code)]) { - if (strcmp(keycode[(ev[0].code)], "") == 0) ctrl_down = false; - if (strcmp(keycode[(ev[0].code)], "") == 0) alt_down = false; + if (ev[0].value == 0 && ev[0].type == 1) { // Read the key release event + if (keycode[(ev[0].code)]) { + if (strcmp(keycode[(ev[0].code)], "") == 0) ctrl_down = false; + if (strcmp(keycode[(ev[0].code)], "") == 0) alt_down = false; + } } - } - if (ev[0].value == 1 && ev[0].type == 1) { // Read the key press event - if (keycode[(ev[0].code)]) { - if (strcmp(keycode[(ev[0].code)], "") == 0) ctrl_down = true; - if (strcmp(keycode[(ev[0].code)], "") == 0) alt_down = true; + if (ev[0].value == 1 && ev[0].type == 1) { // Read the key press event + if (keycode[(ev[0].code)]) { + if (strcmp(keycode[(ev[0].code)], "") == 0) ctrl_down = true; + if (strcmp(keycode[(ev[0].code)], "") == 0) alt_down = true; + } } - } - hide_event = false; - if (ev[0].value == 1 && ev[0].type == 1) { // Read the key press event - if (keycode[(ev[0].code)]) { - if (alt_down && ctrl_down && (strcmp(keycode[(ev[0].code)], "") == 0)) { - hide_event = true; + hide_event = false; + if (ev[0].value == 1 && ev[0].type == 1) { // Read the key press event + if (keycode[(ev[0].code)]) { + if (alt_down && ctrl_down && (strcmp(keycode[(ev[0].code)], "") == 0)) { + hide_event = true; + } } } - } - if ((hide_event == false) && (ev[0].type != EV_LED) && (ev[1].type != EV_LED)) { - // Pass the event on... - event = ev[0]; - if (write(devout[current_keyboard], &event, sizeof event) < 0) { - fprintf(stderr, "Unable to replicate keyboard event!\n"); + if ((hide_event == false) && (ev[0].type != EV_LED) && (ev[1].type != EV_LED)) { + // Pass the event on... + event = ev[0]; + if (write(devout[current_keyboard], &event, sizeof event) < 0) { + fprintf(stderr, "Unable to replicate keyboard event!\n"); + } + } + if (hide_event == true) { + // Let anyone listening to our interface know that an SAK keypress was received + broadcast_sak(); } - } - if (hide_event == true) { - // Let anyone listening to our interface know that an SAK keypress was received - broadcast_sak(); } } } } - } - // fork udev monitor process - int i=fork(); - if (i<0) { - return 10; // fork failed - } - if (i>0) { - // Terminate parent - controlpipe.active = false; - return 0; - } + // fork udev monitor process + int i=fork(); + if (i<0) { + return 10; // fork failed + } + if (i>0) { + // Terminate parent + controlpipe.active = false; + return 0; + } - // Prevent multiple process instances from starting - setupLockingPipe(); + // Prevent multiple process instances from starting + setupLockingPipe(true); - // Wait a little bit so that udev hotplug can stabilize before we start monitoring - sleep(1); + // Wait a little bit so that udev hotplug can stabilize before we start monitoring + sleep(1); - fprintf(stderr, "Hotplug monitoring process started\n"); + fprintf(stderr, "Hotplug monitoring process started\n"); - // Monitor for hotplugged keyboards - int j; - int hotplug_fd; - bool is_new_keyboard; - struct udev *udev; - struct udev_device *dev; - struct udev_monitor *mon; + // Monitor for hotplugged keyboards + int j; + int hotplug_fd; + bool is_new_keyboard; + struct udev *udev; + struct udev_device *dev; + struct udev_monitor *mon; - // Create the udev object - udev = udev_new(); - if (!udev) { - fprintf(stderr, "Cannot connect to udev interface\n"); - return 11; - } + // Create the udev object + udev = udev_new(); + if (!udev) { + fprintf(stderr, "Cannot connect to udev interface\n"); + return 11; + } + + // Set up a udev monitor to monitor input devices + mon = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL); + udev_monitor_enable_receiving(mon); + + while (1) { + // Watch for input from the monitoring process + dev = udev_monitor_receive_device(mon); + if (dev) { + // If a keyboard was removed we need to restart... + if (strcmp(udev_device_get_action(dev), "remove") == 0) { + udev_device_unref(dev); + udev_unref(udev); + restart_tsak(); + } - // Set up a udev monitor to monitor input devices - mon = udev_monitor_new_from_netlink(udev, "udev"); - udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL); - udev_monitor_enable_receiving(mon); - - while (1) { - // Watch for input from the monitoring process - dev = udev_monitor_receive_device(mon); - if (dev) { - // If a keyboard was removed we need to restart... - if (strcmp(udev_device_get_action(dev), "remove") == 0) { + is_new_keyboard = false; + snprintf(filename,sizeof(filename), "%s", udev_device_get_devnode(dev)); udev_device_unref(dev); - udev_unref(udev); - restart_tsak(); - } - is_new_keyboard = false; - snprintf(filename,sizeof(filename), "%s", udev_device_get_devnode(dev)); - udev_device_unref(dev); + // Print name of keyboard + hotplug_fd = open(filename, O_RDWR|O_SYNC); + ioctl(hotplug_fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask); - // Print name of keyboard - hotplug_fd = open(filename, O_RDWR|O_SYNC); - ioctl(hotplug_fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask); + /* We assume that anything that has an alphabetic key in the + QWERTYUIOP range in it is the main keyboard. */ + for (j = KEY_Q; j <= KEY_P; j++) { + if (TestBit(j, key_bitmask)) { + is_new_keyboard = true; + } + } + ioctl (hotplug_fd, EVIOCGNAME (sizeof (name)), name); + close(hotplug_fd); - /* We assume that anything that has an alphabetic key in the - QWERTYUIOP range in it is the main keyboard. */ - for (j = KEY_Q; j <= KEY_P; j++) { - if (TestBit(j, key_bitmask)) { - is_new_keyboard = true; + // Ensure that we do not detect our own tsak faked keyboards + if (str_ends_with(name, "+tsak") == 1) { + is_new_keyboard = false; } - } - ioctl (hotplug_fd, EVIOCGNAME (sizeof (name)), name); - close(hotplug_fd); - // Ensure that we do not detect our own tsak faked keyboards - if (str_ends_with(name, "+tsak") == 1) { - is_new_keyboard = false; + // If a keyboard was added we need to restart... + if (is_new_keyboard == true) { + fprintf(stderr, "Hotplugged new keyboard: (%s)\n", name); + udev_unref(udev); + restart_tsak(); + } } - - // If a keyboard was added we need to restart... - if (is_new_keyboard == true) { - fprintf(stderr, "Hotplugged new keyboard: (%s)\n", name); - udev_unref(udev); - restart_tsak(); + else { + fprintf(stderr, "No Device from receive_device(). A udev error has occurred; terminating hotplug monitoring process.\n"); + return 11; } } - else { - fprintf(stderr, "No Device from receive_device(). A udev error has occurred; terminating hotplug monitoring process.\n"); - return 11; - } - } - udev_unref(udev); + udev_unref(udev); - fprintf(stderr, "Hotplug monitoring process terminated\n"); + fprintf(stderr, "Hotplug monitoring process terminated\n"); + } } } } + catch(exit_exception& e) { + exit(e.c); + } return 6; }