qubesd-query-fast.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/socket.h>
  5. #include <sys/un.h>
  6. #define QUBESD_SOCKET "/var/run/qubesd.sock"
  7. void write_wrapper(int fd, char *data, size_t len) {
  8. size_t written = 0;
  9. int ret;
  10. while (written < len) {
  11. ret = write(fd, data+written, len-written);
  12. if (ret == -1) {
  13. perror("write");
  14. exit(1);
  15. }
  16. written += ret;
  17. }
  18. }
  19. int main(int argc, char **argv) {
  20. char *source_domain = getenv("QREXEC_REMOTE_DOMAIN");
  21. char *target_domain = getenv("QREXEC_REQUESTED_TARGET");
  22. char *service_name = strrchr(argv[0], '/');
  23. int fd;
  24. char buf[4096];
  25. int read_ret;
  26. struct sockaddr_un qubesd_addr = {
  27. .sun_family = AF_UNIX,
  28. .sun_path = QUBESD_SOCKET,
  29. };
  30. if (service_name)
  31. service_name++;
  32. if (!source_domain || !target_domain || !service_name || argc > 2) {
  33. fprintf(stderr, "Usage: %s [service-argument]\n", argv[0]);
  34. fprintf(stderr, "\n");
  35. fprintf(stderr, "Expected environment variables:\n");
  36. fprintf(stderr, " - QREXEC_REMOTE_DOMAIN - source domain for the call\n");
  37. fprintf(stderr, " - QREXEC_REQUESTED_TARGET - target domain for the call\n");
  38. fprintf(stderr, "\n");
  39. fprintf(stderr, "Additionally, this program assumes being called with desired service name as argv[0] (use symlink)\n");
  40. return 1;
  41. }
  42. fd = socket(AF_UNIX, SOCK_STREAM, 0);
  43. if (fd == -1) {
  44. perror("socket");
  45. return 1;
  46. }
  47. if (connect(fd, (struct sockaddr *)&qubesd_addr, sizeof(qubesd_addr)) == -1) {
  48. perror("connect to qubesd");
  49. return 1;
  50. }
  51. // write parameters, including trailing zero as separator
  52. write_wrapper(fd, source_domain, strlen(source_domain) + 1);
  53. write_wrapper(fd, service_name, strlen(service_name) + 1);
  54. write_wrapper(fd, target_domain, strlen(target_domain) + 1);
  55. if (argc == 2)
  56. write_wrapper(fd, argv[1], strlen(argv[1]) + 1);
  57. else
  58. // empty argument
  59. write_wrapper(fd, "\0", 1);
  60. // now, read from stdin and write it to qubesd
  61. while ((read_ret = read(0, buf, sizeof(buf))) > 0)
  62. write_wrapper(fd, buf, read_ret);
  63. if (read_ret == -1) {
  64. perror("read from stdin");
  65. return 1;
  66. }
  67. // end of request, now let qubesd execute the action and return response
  68. shutdown(fd, SHUT_WR);
  69. // then, retrieve the response from qubesd and send it to stdout
  70. while ((read_ret = read(fd, buf, sizeof(buf))) > 0)
  71. write_wrapper(1, buf, read_ret);
  72. if (read_ret == -1) {
  73. perror("read from qubesd");
  74. return 1;
  75. }
  76. return 0;
  77. }