|
@@ -920,61 +920,215 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- * success. On failure, log and return -1.
|
|
|
+
|
|
|
+ * success. Logs and return -1 on failure.
|
|
|
*/
|
|
|
int
|
|
|
-switch_id(const char *user, const char *group)
|
|
|
+log_credential_status()
|
|
|
+{
|
|
|
+#define CREDENTIAL_LOG_LEVEL LOG_INFO
|
|
|
+#ifndef MS_WINDOWS
|
|
|
+
|
|
|
+ uid_t ruid, euid, suid;
|
|
|
+
|
|
|
+ gid_t rgid, egid, sgid;
|
|
|
+
|
|
|
+ gid_t sup_gids[NGROUPS_MAX + 1];
|
|
|
+
|
|
|
+ int ngids;
|
|
|
+
|
|
|
+
|
|
|
+#ifdef HAVE_GETRESUID
|
|
|
+ if (getresuid(&ruid, &euid, &suid) != 0 ) {
|
|
|
+ log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
|
|
|
+ return -1;
|
|
|
+ } else {
|
|
|
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "UID is %u (real), %u (effective), %u (saved)", ruid, euid, suid);
|
|
|
+ }
|
|
|
+#else
|
|
|
+
|
|
|
+ ruid = getuid();
|
|
|
+ euid = geteuid();
|
|
|
+ (void)suid;
|
|
|
+
|
|
|
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "UID is %u (real), %u (effective), unknown (saved)", ruid, euid);
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+#ifdef HAVE_GETRESGID
|
|
|
+ if (getresgid(&rgid, &egid, &sgid) != 0 ) {
|
|
|
+ log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
|
|
|
+ return -1;
|
|
|
+ } else {
|
|
|
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "GID is %u (real), %u (effective), %u (saved)", rgid, egid, sgid);
|
|
|
+ }
|
|
|
+#else
|
|
|
+
|
|
|
+ rgid = getgid();
|
|
|
+ egid = getegid();
|
|
|
+ (void)sgid;
|
|
|
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "GID is %u (real), %u (effective), unknown (saved)", rgid, egid);
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+ if((ngids = getgroups(NGROUPS_MAX + 1, sup_gids)) < 0) {
|
|
|
+ log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s", strerror(errno));
|
|
|
+ return -1;
|
|
|
+ } else {
|
|
|
+ int i;
|
|
|
+ char *strgid;
|
|
|
+ char *s = NULL;
|
|
|
+ int formatting_error = 0;
|
|
|
+ smartlist_t *elts = smartlist_create();
|
|
|
+
|
|
|
+ for (i = 0; i<ngids; i++) {
|
|
|
+ strgid = tor_malloc(11);
|
|
|
+ if (tor_snprintf(strgid, 11, "%u", (unsigned)sup_gids[i]) == -1) {
|
|
|
+ log_warn(LD_GENERAL, "Error printing supplementary GIDs");
|
|
|
+ formatting_error = 1;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ smartlist_add(elts, strgid);
|
|
|
+ }
|
|
|
+
|
|
|
+ s = smartlist_join_strings(elts, " ", 0, NULL);
|
|
|
+
|
|
|
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Supplementary groups are: %s", s);
|
|
|
+
|
|
|
+ error:
|
|
|
+ tor_free(s);
|
|
|
+ SMARTLIST_FOREACH(elts, char *, cp,
|
|
|
+ {
|
|
|
+ tor_free(cp);
|
|
|
+ });
|
|
|
+ smartlist_free(elts);
|
|
|
+
|
|
|
+ if (formatting_error)
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ * primary group. Return 0 on success. On failure, log and return -1.
|
|
|
+ */
|
|
|
+int
|
|
|
+switch_id(const char *user)
|
|
|
{
|
|
|
#ifndef MS_WINDOWS
|
|
|
struct passwd *pw = NULL;
|
|
|
- struct group *gr = NULL;
|
|
|
+ uid_t old_uid;
|
|
|
+ gid_t old_gid;
|
|
|
+
|
|
|
+ tor_assert(user);
|
|
|
|
|
|
+
|
|
|
if (user) {
|
|
|
- pw = getpwnam(user);
|
|
|
- if (pw == NULL) {
|
|
|
- log_warn(LD_CONFIG,"User '%s' not found.", user);
|
|
|
+ if (log_credential_status()) {
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
+ log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Changing user and groups");
|
|
|
|
|
|
-
|
|
|
- if (group) {
|
|
|
- gr = getgrnam(group);
|
|
|
- if (gr == NULL) {
|
|
|
- log_warn(LD_CONFIG,"Group '%s' not found.", group);
|
|
|
+
|
|
|
+ old_uid = getuid();
|
|
|
+ old_gid = getgid();
|
|
|
+
|
|
|
+
|
|
|
+ if (user) {
|
|
|
+ pw = getpwnam(user);
|
|
|
+ if (pw == NULL) {
|
|
|
+ log_warn(LD_CONFIG, "Error setting configured user: "
|
|
|
+ "'%s' not found.", user);
|
|
|
return -1;
|
|
|
}
|
|
|
+ } else {
|
|
|
+
|
|
|
+ log_warn(LD_CONFIG, "Error setting configured user: No user supplied.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- if (setgid(gr->gr_gid) != 0) {
|
|
|
- log_warn(LD_GENERAL,"Error setting to configured GID: %s",
|
|
|
- strerror(errno));
|
|
|
+
|
|
|
+ if (setgroups(1, &pw->pw_gid)) {
|
|
|
+ log_warn(LD_GENERAL, "Error setting configured groups: %s",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (setegid(pw->pw_gid)) {
|
|
|
+ log_warn(LD_GENERAL, "Error setting configured egid: %s",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (setgid(pw->pw_gid)) {
|
|
|
+ log_warn(LD_GENERAL, "Error setting configured gid: %s",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (setuid(pw->pw_uid)) {
|
|
|
+ log_warn(LD_GENERAL, "Error setting configured uid: %s",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (seteuid(pw->pw_uid)){
|
|
|
+ log_warn(LD_GENERAL, "Error setting configured euid: %s",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (setgroups(1, &pw->pw_gid) || setegid(pw->pw_gid) ||
|
|
|
+ setgid(pw->pw_gid) || setuid(pw->pw_uid) || seteuid(pw->pw_uid)) {
|
|
|
+ setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) {
|
|
|
+ log_warn(LD_GENERAL, "Error setting configured UID/GID: %s",
|
|
|
+ strerror(errno));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ * we're here. */
|
|
|
+
|
|
|
+#if !defined(CYGWIN) && !defined(__CYGWIN__)
|
|
|
+
|
|
|
+ * restore root (E)(U|G)ID, and abort if the operation succeeds */
|
|
|
+
|
|
|
+
|
|
|
+ if (pw->pw_uid) {
|
|
|
+
|
|
|
+ if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) {
|
|
|
+ log_warn(LD_GENERAL, "Was able to restore group credentials");
|
|
|
return -1;
|
|
|
}
|
|
|
- } else if (user) {
|
|
|
- if (setgid(pw->pw_gid) != 0) {
|
|
|
- log_warn(LD_GENERAL,"Error setting to user GID: %s", strerror(errno));
|
|
|
+
|
|
|
+
|
|
|
+ if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) {
|
|
|
+ log_warn(LD_GENERAL, "Was able to restore user credentials");
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
-
|
|
|
- privileges */
|
|
|
+
|
|
|
if (user) {
|
|
|
- if (setuid(pw->pw_uid) != 0) {
|
|
|
- log_warn(LD_GENERAL,"Error setting UID: %s", strerror(errno));
|
|
|
+ if (log_credential_status()) {
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
+
|
|
|
#else
|
|
|
(void)user;
|
|
|
- (void)group;
|
|
|
#endif
|
|
|
|
|
|
log_warn(LD_CONFIG,
|
|
|
- "User or group specified, but switching users is not supported.");
|
|
|
+ "User specified but switching users is unsupported on your OS.");
|
|
|
return -1;
|
|
|
}
|
|
|
|