qfile-unpacker.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #define _GNU_SOURCE
  2. #include <ioall.h>
  3. #include <grp.h>
  4. #include <unistd.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <pwd.h>
  8. #include <sys/stat.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <sys/fsuid.h>
  12. #include <gui-fatal.h>
  13. #include <errno.h>
  14. #include "filecopy.h"
  15. #define INCOMING_DIR_ROOT "/home/user/incoming"
  16. int prepare_creds_return_uid(char *username)
  17. {
  18. struct passwd *pwd;
  19. pwd = getpwnam(username);
  20. if (!pwd) {
  21. perror("getpwnam");
  22. exit(1);
  23. }
  24. setenv("HOME", pwd->pw_dir, 1);
  25. setenv("USER", username, 1);
  26. setgid(pwd->pw_gid);
  27. initgroups(username, pwd->pw_gid);
  28. setfsuid(pwd->pw_uid);
  29. return pwd->pw_uid;
  30. }
  31. void wait_for_child(int statusfd)
  32. {
  33. int status;
  34. if (read(statusfd, &status, sizeof status)!=sizeof status)
  35. gui_fatal("File copy error: Internal error reading status from unpacker");
  36. errno = status;
  37. switch (status) {
  38. case LEGAL_EOF: break;
  39. case 0: gui_fatal("File copy: Connection terminated unexpectedly"); break;
  40. case EINVAL: gui_fatal("File copy: Corrupted data from packer"); break;
  41. case EEXIST: gui_fatal("File copy: not overwriting existing file. Clean ~/incoming, and retry copy"); break;
  42. default: gui_fatal("File copy");
  43. }
  44. }
  45. extern void do_unpack(int);
  46. int main(int argc, char ** argv)
  47. {
  48. char *incoming_dir;
  49. int pipefds[2];
  50. int uid;
  51. pipe(pipefds);
  52. uid = prepare_creds_return_uid("user");
  53. mkdir(INCOMING_DIR_ROOT, 0700);
  54. asprintf(&incoming_dir, "%s/from-%s", INCOMING_DIR_ROOT, argv[1]);
  55. mkdir(incoming_dir, 0700);
  56. if (chdir(incoming_dir))
  57. gui_fatal("Error chdir to %s", incoming_dir);
  58. switch (fork()) {
  59. case -1:
  60. perror("fork");
  61. exit(1);
  62. case 0:
  63. if (chroot(incoming_dir)) //impossible
  64. gui_fatal("Error chroot to %s", incoming_dir);
  65. setuid(uid);
  66. close(pipefds[0]);
  67. do_unpack(pipefds[1]);
  68. exit(0);
  69. default:;
  70. }
  71. setuid(uid);
  72. close(pipefds[1]);
  73. wait_for_child(pipefds[0]);
  74. return 0;
  75. }