You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
3.1 KiB

  1. --- a/src/bin/pg_ctl/pg_ctl.c
  2. +++ b/src/bin/pg_ctl/pg_ctl.c
  3. @@ -88,6 +88,7 @@ static char *event_source = NULL;
  4. static char *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */
  5. static char *register_username = NULL;
  6. static char *register_password = NULL;
  7. +static char *username = "";
  8. static char *argv0 = NULL;
  9. static bool allow_core_files = false;
  10. static time_t start_time;
  11. @@ -1930,6 +1931,9 @@ do_help(void)
  12. #endif
  13. printf(_(" -s, --silent only print errors, no informational messages\n"));
  14. printf(_(" -t, --timeout=SECS seconds to wait when using -w option\n"));
  15. +#if !defined(WIN32) && !defined(__CYGWIN__)
  16. + printf(_(" -U, --username=NAME user name of account PostgreSQL server is running as\n"));
  17. +#endif
  18. printf(_(" -V, --version output version information, then exit\n"));
  19. printf(_(" -w wait until operation completes\n"));
  20. printf(_(" -W do not wait until operation completes\n"));
  21. @@ -2126,6 +2130,7 @@ main(int argc, char **argv)
  22. {"pgdata", required_argument, NULL, 'D'},
  23. {"silent", no_argument, NULL, 's'},
  24. {"timeout", required_argument, NULL, 't'},
  25. + {"username", required_argument, NULL, 'U'},
  26. {"core-files", no_argument, NULL, 'c'},
  27. {NULL, 0, NULL, 0}
  28. };
  29. @@ -2166,20 +2171,6 @@ main(int argc, char **argv)
  30. }
  31. }
  32. - /*
  33. - * Disallow running as root, to forestall any possible security holes.
  34. - */
  35. -#ifndef WIN32
  36. - if (geteuid() == 0)
  37. - {
  38. - write_stderr(_("%s: cannot be run as root\n"
  39. - "Please log in (using, e.g., \"su\") as the "
  40. - "(unprivileged) user that will\n"
  41. - "own the server process.\n"),
  42. - progname);
  43. - exit(1);
  44. - }
  45. -#endif
  46. env_wait = getenv("PGCTLTIMEOUT");
  47. if (env_wait != NULL)
  48. @@ -2265,11 +2256,15 @@ main(int argc, char **argv)
  49. wait_seconds_arg = true;
  50. break;
  51. case 'U':
  52. +#if defined(WIN32) || defined(__CYGWIN__)
  53. if (strchr(optarg, '\\'))
  54. register_username = pg_strdup(optarg);
  55. else
  56. /* Prepend .\ for local accounts */
  57. register_username = psprintf(".\\%s", optarg);
  58. +#else
  59. + username = pg_strdup(optarg);
  60. +#endif
  61. break;
  62. case 'w':
  63. do_wait = true;
  64. @@ -2351,6 +2346,41 @@ main(int argc, char **argv)
  65. exit(1);
  66. }
  67. + /*
  68. + * Disallow running as root, to forestall any possible security holes.
  69. + */
  70. +#if !defined(WIN32) && !defined(__CYGWIN__)
  71. + if (geteuid() == 0)
  72. + {
  73. + struct passwd *p;
  74. + if (!username || !strlen(username)) {
  75. + fprintf(stderr,
  76. + _("%s: when run as root, username needs to be provided\n"),
  77. + progname);
  78. + exit(1);
  79. + }
  80. + p = getpwnam(username);
  81. + if (!p) {
  82. + fprintf(stderr,
  83. + _("%s: invalid username: %s\n"),
  84. + progname, username);
  85. + exit(1);
  86. + }
  87. + if (!p->pw_uid) {
  88. + fprintf(stderr,
  89. + _("%s: user needs to be non-root\n"),
  90. + progname);
  91. + exit(1);
  92. + }
  93. + if (setgid(p->pw_gid) || setuid(p->pw_uid)) {
  94. + fprintf(stderr,
  95. + _("%s: failed to set user id %d: %d (%s)\n"),
  96. + progname, p->pw_uid, errno, strerror(errno));
  97. + exit(1);
  98. + }
  99. + }
  100. +#endif
  101. +
  102. /* Note we put any -D switch into the env var above */
  103. pg_config = getenv("PGDATA");
  104. if (pg_config)