Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #define _GNU_SOURCE
00032
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <unistd.h>
00036 #include <string.h>
00037 #include <syslog.h>
00038 #include <stdarg.h>
00039 #include <errno.h>
00040 #include <pwd.h>
00041 #include <grp.h>
00042 #include <ctype.h>
00043
00044 #include "config.h"
00045 #include "privdrop.h"
00046
00047
00048 int
00049 privdrop(const char *username, const char *groupname, const char *newroot)
00050 {
00051 int status;
00052
00053 struct passwd *pwd;
00054 struct group *grp;
00055
00056 uid_t uid, olduid;
00057 gid_t gid, oldgid;
00058
00059 long ngroups_max;
00060 gid_t *final_groups;
00061 int final_group_len = -1;
00062
00063
00064 uid = olduid = geteuid();
00065 gid = oldgid = getegid();
00066
00067
00068 if (username) {
00069
00070 if ((pwd = getpwnam(username)) == NULL) {
00071 syslog(LOG_ERR, "user '%s' does not exist. exiting...\n", username);
00072 exit(1);
00073 } else {
00074 uid = pwd->pw_uid;
00075 }
00076 endpwent();
00077 }
00078
00079
00080 if (groupname) {
00081
00082 if ((grp = getgrnam(groupname)) == NULL) {
00083 syslog(LOG_ERR, "group '%s' does not exist. exiting...\n", groupname);
00084 exit(1);
00085 } else {
00086 gid = grp->gr_gid;
00087 }
00088 endgrent();
00089 }
00090
00091
00092 if (newroot) {
00093 if (chroot(newroot) != 0 || chdir("/") != 0) {
00094 syslog(LOG_ERR, "chroot to '%s' failed. exiting...\n", newroot);
00095 exit(1);
00096 }
00097 }
00098
00099
00100 if (username != NULL && !olduid) {
00101 if (initgroups(username, gid) < 0) {
00102 syslog(LOG_ERR, "initgroups failed: %s: %.100s", username, strerror(errno));
00103 exit(1);
00104 }
00105
00106 ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
00107 final_groups = (gid_t *)malloc(ngroups_max *sizeof(gid_t));
00108 if (final_groups == NULL) {
00109 syslog(LOG_ERR, "Malloc for group struct failed");
00110 exit(1);
00111 }
00112
00113 final_group_len = getgroups(ngroups_max, final_groups);
00114
00115 if (!olduid) setgroups(final_group_len, final_groups);
00116
00117 free(final_groups);
00118 }
00119 else {
00120
00121 if (!olduid) setgroups(1, &(gid));
00122 }
00123
00124
00125 if (groupname) {
00126
00127 #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
00128 status = setresgid(gid, gid, gid);
00129 #elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID)
00130 status = setregid(gid, gid);
00131 #else
00132 status = setegid(gid);
00133 if (status != 0) {
00134 syslog(LOG_ERR, "unable to drop group privileges: %s (%lu). exiting...\n",
00135 groupname, (unsigned long) gid);
00136 exit(1);
00137 }
00138 status = setgid(gid);
00139 #endif
00140
00141 if (status != 0) {
00142 syslog(LOG_ERR, "unable to drop group privileges: %s (%lu). exiting...\n",
00143 groupname, (unsigned long) gid);
00144 exit(1);
00145 return -1;
00146 } else {
00147 syslog(LOG_ERR, "group set to: %s (%lu)\n", groupname, (unsigned long) gid);
00148 }
00149 }
00150
00151
00152 if (username) {
00153
00154 #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
00155 status = setresuid(uid, uid, uid);
00156 #elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
00157 status = setreuid(uid, uid);
00158 #else
00159
00160 # ifndef SETEUID_BREAKS_SETUID
00161 status = seteuid(uid);
00162 if (status != 0) {
00163 syslog(LOG_ERR, "unable to drop user privileges (seteuid): %s (%lu). exiting...\n",
00164 username, (unsigned long) uid);
00165 exit(1);
00166 }
00167 # endif
00168
00169 status = setuid(uid);
00170 #endif
00171
00172 if (status != 0) {
00173 syslog(LOG_ERR, "unable to drop user privileges: %s (%lu). exiting...\n",
00174 username, (unsigned long) uid);
00175 exit(1);
00176 return -1;
00177 } else {
00178 syslog(LOG_ERR, "user set to: %s (%lu)\n", username, (unsigned long) uid);
00179 }
00180 }
00181
00182 return 0;
00183 }