Thu, 04 Oct 2012 20:30:05 +0200
Correct out of date build configuration, porting to Solaris 11 network
link infrastructure and new libpcap logic. This additionally allows for
device drivers in subdirectories of /dev. Correct packaged nmap
personalities and signatures to work out of the box. Finally, hack
arpd logic to properly close sockets and quit on TERM by repeating
signaling in the run command script. Sadly, all this fails to correct
the run time behaviour of honeyd which fails to bind to the IP layer.
michael@428 | 1 | /* |
michael@428 | 2 | ** openpkg.c -- OpenPKG Frontend |
michael@428 | 3 | ** Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/> |
michael@428 | 4 | ** |
michael@428 | 5 | ** This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
michael@428 | 6 | ** All rights reserved. Licenses which grant limited permission to use, |
michael@428 | 7 | ** copy, modify and distribute this software are available from the |
michael@428 | 8 | ** OpenPKG GmbH. |
michael@428 | 9 | ** |
michael@428 | 10 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
michael@428 | 11 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
michael@428 | 12 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
michael@428 | 13 | ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
michael@428 | 14 | ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@428 | 15 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@428 | 16 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
michael@428 | 17 | ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
michael@428 | 18 | ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
michael@428 | 19 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
michael@428 | 20 | ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
michael@428 | 21 | ** SUCH DAMAGE. |
michael@428 | 22 | */ |
michael@428 | 23 | |
michael@428 | 24 | /* program information */ |
michael@428 | 25 | #define LICENSE \ |
michael@428 | 26 | "Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/>\n" \ |
michael@428 | 27 | "\n" \ |
michael@428 | 28 | "This software is property of the OpenPKG GmbH, DE MUC HRB 160208.\n" \ |
michael@428 | 29 | "All rights reserved. Licenses which grant limited permission to use,\n" \ |
michael@428 | 30 | "copy, modify and distribute this software are available from the\n" \ |
michael@428 | 31 | "OpenPKG GmbH.\n" \ |
michael@428 | 32 | "\n" \ |
michael@428 | 33 | "THIS SOFTWARE IS PROVIDED \"AS IS\" AND ANY EXPRESSED OR IMPLIED\n" \ |
michael@428 | 34 | "WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n" \ |
michael@428 | 35 | "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n" \ |
michael@428 | 36 | "IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR\n" \ |
michael@428 | 37 | "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" \ |
michael@428 | 38 | "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" \ |
michael@428 | 39 | "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n" \ |
michael@428 | 40 | "USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n" \ |
michael@428 | 41 | "ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n" \ |
michael@428 | 42 | "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\n" \ |
michael@428 | 43 | "OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n" \ |
michael@428 | 44 | "SUCH DAMAGE.\n" |
michael@428 | 45 | |
michael@428 | 46 | /* system includes */ |
michael@428 | 47 | #include <stdio.h> |
michael@428 | 48 | #include <stdlib.h> |
michael@428 | 49 | #include <stdarg.h> |
michael@428 | 50 | #include <string.h> |
michael@428 | 51 | #include <sys/types.h> |
michael@428 | 52 | #include <sys/param.h> |
michael@428 | 53 | #include <sys/stat.h> |
michael@428 | 54 | #include <pwd.h> |
michael@428 | 55 | #include <grp.h> |
michael@428 | 56 | #include <unistd.h> |
michael@428 | 57 | #include <errno.h> |
michael@428 | 58 | |
michael@428 | 59 | /* sanity check compilation */ |
michael@428 | 60 | #ifndef OPENPKG_PREFIX |
michael@428 | 61 | #error OpenPKG instance prefix not defined |
michael@428 | 62 | #endif |
michael@428 | 63 | #ifndef OPENPKG_SUSR |
michael@428 | 64 | #error OpenPKG super user not defined |
michael@428 | 65 | #endif |
michael@428 | 66 | #ifndef OPENPKG_MUSR |
michael@428 | 67 | #error OpenPKG management user not defined |
michael@428 | 68 | #endif |
michael@428 | 69 | |
michael@428 | 70 | /* platform specifics */ |
michael@428 | 71 | #if defined(OPENPKG_PLATFORM_FREEBSD) || \ |
michael@428 | 72 | defined(OPENPKG_PLATFORM_NETBSD) || \ |
michael@428 | 73 | defined(OPENPKG_PLATFORM_OPENBSD) || \ |
michael@428 | 74 | defined(OPENPKG_PLATFORM_SUNOS) || \ |
michael@428 | 75 | defined(OPENPKG_PLATFORM_LINUX) || \ |
michael@428 | 76 | defined(OPENPKG_PLATFORM_DARWIN) || \ |
michael@428 | 77 | defined(OPENPKG_PLATFORM_AIX) || \ |
michael@428 | 78 | defined(OPENPKG_PLATFORM_IRIX) || \ |
michael@428 | 79 | defined(OPENPKG_PLATFORM_HPUX) |
michael@428 | 80 | #define HAVE_INITGROUPS |
michael@428 | 81 | #endif |
michael@428 | 82 | |
michael@428 | 83 | /* global debug enable flag */ |
michael@428 | 84 | static int debug_enable = 0; |
michael@428 | 85 | |
michael@428 | 86 | /* helper function: emulate (still less portable) setenv(3) via (more portable) putenv(3) */ |
michael@428 | 87 | static int my_setenv(const char *name, const char *value, int overwrite) |
michael@428 | 88 | { |
michael@428 | 89 | char *pair; |
michael@428 | 90 | |
michael@428 | 91 | if (overwrite == 0 && getenv(name) != NULL) |
michael@428 | 92 | return 0; |
michael@428 | 93 | if ((pair = malloc(strlen(name) + 1 + strlen(value) + 1)) == NULL) |
michael@428 | 94 | return -1; |
michael@428 | 95 | strcpy(pair, name); |
michael@428 | 96 | strcat(pair, "="); |
michael@428 | 97 | strcat(pair, value); |
michael@428 | 98 | putenv(pair); |
michael@428 | 99 | return 0; |
michael@428 | 100 | } |
michael@428 | 101 | |
michael@428 | 102 | /* helper function for printing a warning message */ |
michael@428 | 103 | static void warn(const char *fmt, ...) |
michael@428 | 104 | { |
michael@428 | 105 | va_list ap; |
michael@428 | 106 | |
michael@428 | 107 | va_start(ap, fmt); |
michael@428 | 108 | fprintf(stderr, "openpkg:WARNING: "); |
michael@428 | 109 | vfprintf(stderr, fmt, ap); |
michael@428 | 110 | fprintf(stderr, "\n"); |
michael@428 | 111 | va_end(ap); |
michael@428 | 112 | return; |
michael@428 | 113 | } |
michael@428 | 114 | |
michael@428 | 115 | /* helper function for printing a debug message */ |
michael@428 | 116 | static void debug(const char *fmt, ...) |
michael@428 | 117 | { |
michael@428 | 118 | va_list ap; |
michael@428 | 119 | |
michael@428 | 120 | va_start(ap, fmt); |
michael@428 | 121 | if (debug_enable) { |
michael@428 | 122 | fprintf(stderr, "openpkg:DEBUG: "); |
michael@428 | 123 | vfprintf(stderr, fmt, ap); |
michael@428 | 124 | fprintf(stderr, "\n"); |
michael@428 | 125 | } |
michael@428 | 126 | va_end(ap); |
michael@428 | 127 | return; |
michael@428 | 128 | } |
michael@428 | 129 | |
michael@428 | 130 | /* helper function for printing a fatal message and exit */ |
michael@428 | 131 | static void fatal(const char *fmt, ...) |
michael@428 | 132 | { |
michael@428 | 133 | va_list ap; |
michael@428 | 134 | |
michael@428 | 135 | va_start(ap, fmt); |
michael@428 | 136 | fprintf(stderr, "openpkg:ERROR: "); |
michael@428 | 137 | vfprintf(stderr, fmt, ap); |
michael@428 | 138 | fprintf(stderr, "\n"); |
michael@428 | 139 | va_end(ap); |
michael@428 | 140 | exit(1); |
michael@428 | 141 | return; |
michael@428 | 142 | } |
michael@428 | 143 | |
michael@428 | 144 | /* adjust process privileges */ |
michael@428 | 145 | static void adjust_privileges(uid_t uid, gid_t gid, int login) |
michael@428 | 146 | { |
michael@428 | 147 | struct passwd *pw; |
michael@428 | 148 | char cwd[MAXPATHLEN]; |
michael@428 | 149 | |
michael@428 | 150 | /* optionally emulate a more complete login */ |
michael@428 | 151 | if (login) { |
michael@428 | 152 | /* determine information about user id */ |
michael@428 | 153 | if ((pw = getpwuid(uid)) == NULL) |
michael@428 | 154 | fatal("unable to resolve user id \"%d\": %s", uid, strerror(errno)); |
michael@428 | 155 | |
michael@428 | 156 | /* reset some essential environment variables */ |
michael@428 | 157 | my_setenv("LOGNAME", pw->pw_name, 1); |
michael@428 | 158 | my_setenv("USER", pw->pw_name, 1); |
michael@428 | 159 | my_setenv("SHELL", pw->pw_shell, 1); |
michael@428 | 160 | my_setenv("HOME", pw->pw_dir, 1); |
michael@428 | 161 | |
michael@428 | 162 | #ifdef HAVE_INITGROUPS |
michael@428 | 163 | /* initialize complete group access list */ |
michael@428 | 164 | if (initgroups(pw->pw_name, pw->pw_gid) == -1) |
michael@428 | 165 | fatal("failed to initialize access group list via initgroups(3): %s", strerror(errno)); |
michael@428 | 166 | #endif |
michael@428 | 167 | } |
michael@428 | 168 | |
michael@428 | 169 | /* switch to group id (first) */ |
michael@428 | 170 | if (setgid(gid) == -1) |
michael@428 | 171 | fatal("failed to set group id via setgid(2): %s", strerror(errno)); |
michael@428 | 172 | |
michael@428 | 173 | /* switch to user id (second) */ |
michael@428 | 174 | if (setuid(uid) == -1) |
michael@428 | 175 | fatal("failed to set user id via setuid(2): %s", strerror(errno)); |
michael@428 | 176 | |
michael@428 | 177 | /* in case the current working directory is NO LONGER accessible, |
michael@428 | 178 | try to switch to the home directory of the target identity to |
michael@428 | 179 | prevent failures in subsequently called programs (e.g. GNU bash) */ |
michael@428 | 180 | if (login) { |
michael@428 | 181 | if (getcwd(cwd, sizeof(cwd)) == NULL) { |
michael@428 | 182 | warn("current working directory is no longer accessible -- switching to \"%s\"", pw->pw_dir); |
michael@428 | 183 | if (chdir(pw->pw_dir) == -1) |
michael@428 | 184 | fatal("unable to chdir(2) to \"%s\": %s", pw->pw_dir, strerror(errno)); |
michael@428 | 185 | } |
michael@428 | 186 | } |
michael@428 | 187 | |
michael@428 | 188 | return; |
michael@428 | 189 | } |
michael@428 | 190 | |
michael@428 | 191 | /* check whether caller is an explictly configured management user */ |
michael@428 | 192 | static int check_whether_is_manager(uid_t my_uid, gid_t my_gid, uid_t m_uid, gid_t m_gid) |
michael@428 | 193 | { |
michael@428 | 194 | char buf[1024]; |
michael@428 | 195 | char *username; |
michael@428 | 196 | char *groupname; |
michael@428 | 197 | char *filename; |
michael@428 | 198 | struct stat sb; |
michael@428 | 199 | char *cp; |
michael@428 | 200 | FILE *fp; |
michael@428 | 201 | struct passwd *pw; |
michael@428 | 202 | struct group *gr; |
michael@428 | 203 | int i; |
michael@428 | 204 | int ok_uid; |
michael@428 | 205 | int ok_gid; |
michael@428 | 206 | int is_manager; |
michael@428 | 207 | |
michael@428 | 208 | is_manager = 0; |
michael@428 | 209 | |
michael@428 | 210 | /* path to the managers configuration file */ |
michael@428 | 211 | filename = OPENPKG_PREFIX "/etc/openpkg/managers"; |
michael@428 | 212 | |
michael@428 | 213 | /* check permissions of file */ |
michael@428 | 214 | if (stat(filename, &sb) == -1) { |
michael@428 | 215 | warn("unable to determine information about configuration" |
michael@428 | 216 | " file \"%s\": %s -- ignoring file", filename, strerror(errno)); |
michael@428 | 217 | return 0; |
michael@428 | 218 | } |
michael@428 | 219 | if (sb.st_uid != m_uid) { |
michael@428 | 220 | warn("invalid owner user id %d (expected %d) on configuration" |
michael@428 | 221 | " file \"%s\" -- ignoring file", sb.st_uid, m_uid, filename); |
michael@428 | 222 | return 0; |
michael@428 | 223 | } |
michael@428 | 224 | if (sb.st_gid != m_gid) { |
michael@428 | 225 | warn("invalid owner group id %d (expected %d) on configuration" |
michael@428 | 226 | " file \"%s\" -- ignoring file", sb.st_gid, m_gid, filename); |
michael@428 | 227 | return 0; |
michael@428 | 228 | } |
michael@428 | 229 | if (sb.st_mode != (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH)) { |
michael@428 | 230 | warn("invalid permissions on configuration" |
michael@428 | 231 | " file \"%s\" -- ignoring file", filename); |
michael@428 | 232 | return 0; |
michael@428 | 233 | } |
michael@428 | 234 | |
michael@428 | 235 | /* parse configuration file */ |
michael@428 | 236 | if ((fp = fopen(filename, "r")) == NULL) { |
michael@428 | 237 | warn("unable to open configuration file \"%s\": %s -- ignoring file", filename, strerror(errno)); |
michael@428 | 238 | return 0; |
michael@428 | 239 | } |
michael@428 | 240 | while ((cp = fgets(buf, sizeof(buf), fp)) != NULL) { |
michael@428 | 241 | /* parse entry as "<username>[:<groupname>]" where both |
michael@428 | 242 | <username> and <groupname> can be set and default to "*" |
michael@428 | 243 | to indicate an arbitrary user or group */ |
michael@428 | 244 | if ((i = strlen(buf)) == 0) { |
michael@428 | 245 | warn("unexpected empty buffer during parsing of configuration file \"%\"", filename); |
michael@428 | 246 | break; |
michael@428 | 247 | } |
michael@428 | 248 | if (i >= sizeof(buf)) { |
michael@428 | 249 | warn("unexpected buffer overflow during parsing of configuration file \"%\"", filename); |
michael@428 | 250 | break; |
michael@428 | 251 | } |
michael@428 | 252 | if (buf[i-1] != '\r' && buf[i-1] != '\n') { |
michael@428 | 253 | warn("unexpected non-newline-terminated line found during parsing of configuration file \"%\"", filename); |
michael@428 | 254 | break; |
michael@428 | 255 | } |
michael@428 | 256 | username = buf + strspn(buf, " \t"); |
michael@428 | 257 | cp = username + strcspn(username, " \t#\r\n"); |
michael@428 | 258 | *cp = '\0'; |
michael@428 | 259 | if (username[0] == '#' || username[0] == '\r' || username[0] == '\n' || username[0] == '\0') |
michael@428 | 260 | continue; |
michael@428 | 261 | groupname = "*"; |
michael@428 | 262 | if ((cp = strchr(username, ':')) != NULL) { |
michael@428 | 263 | *cp++ = '\0'; |
michael@428 | 264 | groupname = cp; |
michael@428 | 265 | } |
michael@428 | 266 | debug("parsing result: username=\"%s\" groupname=\"%s\"", username, groupname); |
michael@428 | 267 | |
michael@428 | 268 | /* check whether UID is ok */ |
michael@428 | 269 | ok_uid = 0; |
michael@428 | 270 | if (strcmp(username, "*") == 0) |
michael@428 | 271 | ok_uid = 1; |
michael@428 | 272 | else { |
michael@428 | 273 | if ((pw = getpwnam(username)) == NULL) { |
michael@428 | 274 | warn("invalid username \"%s\" in \"%s\"", username, filename); |
michael@428 | 275 | continue; |
michael@428 | 276 | } |
michael@428 | 277 | if (pw->pw_uid == my_uid) |
michael@428 | 278 | ok_uid = 1; |
michael@428 | 279 | } |
michael@428 | 280 | |
michael@428 | 281 | /* check whether GID is ok */ |
michael@428 | 282 | ok_gid = 0; |
michael@428 | 283 | if (strcmp(groupname, "*") == 0) |
michael@428 | 284 | ok_gid = 1; |
michael@428 | 285 | else { |
michael@428 | 286 | if ((gr = getgrnam(groupname)) == NULL) { |
michael@428 | 287 | warn("invalid groupname \"%s\" in \"%s\"", groupname, filename); |
michael@428 | 288 | continue; |
michael@428 | 289 | } |
michael@428 | 290 | if (gr->gr_gid == my_gid) |
michael@428 | 291 | ok_gid = 1; |
michael@428 | 292 | } |
michael@428 | 293 | |
michael@428 | 294 | /* if both UID and GID are ok, user is manager */ |
michael@428 | 295 | debug("matching: username ok = %s, groupname ok = %s", ok_uid ? "yes" : "no", ok_gid ? "yes" : "no"); |
michael@428 | 296 | if (ok_uid && ok_gid) { |
michael@428 | 297 | is_manager = 1; |
michael@428 | 298 | break; |
michael@428 | 299 | } |
michael@428 | 300 | } |
michael@428 | 301 | fclose(fp); |
michael@428 | 302 | return is_manager; |
michael@428 | 303 | } |
michael@428 | 304 | |
michael@428 | 305 | /* check whether command requires super-user privileges */ |
michael@428 | 306 | static int check_whether_require_superuser(int argc, char *argv[]) |
michael@428 | 307 | { |
michael@428 | 308 | int require_superuser; |
michael@428 | 309 | int i, j; |
michael@428 | 310 | |
michael@428 | 311 | require_superuser = 0; |
michael@428 | 312 | if (argc > 1 && strcmp(argv[1], "rpm") == 0) { |
michael@428 | 313 | for (i = 2; i < argc; i++) { |
michael@428 | 314 | if (strcmp(argv[i], "--") == 0) |
michael@428 | 315 | break; |
michael@428 | 316 | else if ( strcmp(argv[i], "--erase") == 0 |
michael@428 | 317 | || strcmp(argv[i], "--freshen") == 0 |
michael@428 | 318 | || strcmp(argv[i], "--install") == 0 |
michael@428 | 319 | || strcmp(argv[i], "--upgrade") == 0 |
michael@428 | 320 | || strcmp(argv[i], "--import") == 0 |
michael@428 | 321 | || strcmp(argv[i], "--initdb") == 0 |
michael@428 | 322 | || strcmp(argv[i], "--rebuilddb") == 0 |
michael@428 | 323 | || strcmp(argv[i], "--db-build") == 0 |
michael@428 | 324 | || strcmp(argv[i], "--db-rebuild") == 0 |
michael@428 | 325 | || strcmp(argv[i], "--db-cleanup") == 0 |
michael@428 | 326 | || strcmp(argv[i], "--db-fixate") == 0 |
michael@428 | 327 | || strcmp(argv[i], "--setperms") == 0 |
michael@428 | 328 | || strcmp(argv[i], "--setugids") == 0) { |
michael@428 | 329 | require_superuser = 1; |
michael@428 | 330 | break; |
michael@428 | 331 | } |
michael@428 | 332 | else if ( argv[i][0] == '-' |
michael@428 | 333 | && argv[i][1] != '-' |
michael@428 | 334 | && argv[i][1] != 'b' |
michael@428 | 335 | && argv[i][1] != 't' |
michael@428 | 336 | ) { |
michael@428 | 337 | for (j = 1; argv[i][j] != '\0'; j++) { |
michael@428 | 338 | if ( ( argv[i][j] == 'q' |
michael@428 | 339 | || argv[i][j] == 'K') |
michael@428 | 340 | && argv[i][j+1] != '\0') { |
michael@428 | 341 | j++; |
michael@428 | 342 | continue; |
michael@428 | 343 | } |
michael@428 | 344 | else if ( argv[i][j] == 'i' |
michael@428 | 345 | || argv[i][j] == 'U' |
michael@428 | 346 | || argv[i][j] == 'F' |
michael@428 | 347 | || argv[i][j] == 'V' |
michael@428 | 348 | || argv[i][j] == 'e') { |
michael@428 | 349 | require_superuser = 1; |
michael@428 | 350 | break; |
michael@428 | 351 | } |
michael@428 | 352 | } |
michael@428 | 353 | if (require_superuser) |
michael@428 | 354 | break; |
michael@428 | 355 | } |
michael@428 | 356 | } |
michael@428 | 357 | } |
michael@428 | 358 | else if (argc > 1 && strcmp(argv[1], "rc") == 0) { |
michael@428 | 359 | require_superuser = 1; |
michael@428 | 360 | for (i = 2; i < argc; i++) { |
michael@428 | 361 | if (strcmp(argv[i], "--") == 0) |
michael@428 | 362 | break; |
michael@428 | 363 | else if ( strcmp(argv[i], "-p") == 0 |
michael@428 | 364 | || strcmp(argv[i], "--print") == 0 |
michael@428 | 365 | || strcmp(argv[i], "-e") == 0 |
michael@428 | 366 | || strcmp(argv[i], "--eval") == 0 |
michael@428 | 367 | || strcmp(argv[i], "-q") == 0 |
michael@428 | 368 | || strcmp(argv[i], "--query") == 0 |
michael@428 | 369 | || strcmp(argv[i], "-c") == 0 |
michael@428 | 370 | || strcmp(argv[i], "--config") == 0) { |
michael@428 | 371 | require_superuser = 0; |
michael@428 | 372 | break; |
michael@428 | 373 | } |
michael@428 | 374 | } |
michael@428 | 375 | } |
michael@428 | 376 | return require_superuser; |
michael@428 | 377 | } |
michael@428 | 378 | |
michael@428 | 379 | /* main program */ |
michael@428 | 380 | int main(int argc, char **argv, char **envp) |
michael@428 | 381 | { |
michael@428 | 382 | int keep_original_privileges; |
michael@428 | 383 | int is_manager; |
michael@428 | 384 | int require_superuser; |
michael@428 | 385 | uid_t my_uid, my_euid; |
michael@428 | 386 | gid_t my_gid, my_egid; |
michael@428 | 387 | uid_t m_uid; |
michael@428 | 388 | gid_t m_gid; |
michael@428 | 389 | uid_t s_uid; |
michael@428 | 390 | gid_t s_gid; |
michael@428 | 391 | struct passwd *pw; |
michael@428 | 392 | struct group *gr; |
michael@428 | 393 | int dry_run; |
michael@428 | 394 | int license; |
michael@428 | 395 | |
michael@428 | 396 | /* parse command line options */ |
michael@428 | 397 | license = 0; |
michael@428 | 398 | dry_run = 0; |
michael@428 | 399 | keep_original_privileges = 0; |
michael@428 | 400 | if (argc <= 0) |
michael@428 | 401 | abort(); |
michael@428 | 402 | argv++; argc--; |
michael@428 | 403 | while (argc > 0) { |
michael@428 | 404 | if (argv[0][0] != '-') |
michael@428 | 405 | break; |
michael@428 | 406 | else if (strcmp(argv[0], "--") == 0) { |
michael@428 | 407 | argv++; argc--; |
michael@428 | 408 | break; |
michael@428 | 409 | } |
michael@428 | 410 | else if (strcmp(argv[0], "--license") == 0) { |
michael@428 | 411 | license = 1; |
michael@428 | 412 | argv++; argc--; |
michael@428 | 413 | continue; |
michael@428 | 414 | } |
michael@428 | 415 | else if (strcmp(argv[0], "--debug") == 0) { |
michael@428 | 416 | debug_enable = 1; |
michael@428 | 417 | argv++; argc--; |
michael@428 | 418 | continue; |
michael@428 | 419 | } |
michael@428 | 420 | else if (strcmp(argv[0], "--dry-run") == 0) { |
michael@428 | 421 | dry_run = 1; |
michael@428 | 422 | argv++; argc--; |
michael@428 | 423 | continue; |
michael@428 | 424 | } |
michael@428 | 425 | else if (strcmp(argv[0], "--keep-privileges") == 0) { |
michael@428 | 426 | keep_original_privileges = 1; |
michael@428 | 427 | argv++; argc--; |
michael@428 | 428 | continue; |
michael@428 | 429 | } |
michael@428 | 430 | break; |
michael@428 | 431 | } |
michael@428 | 432 | argv--; argc++; |
michael@428 | 433 | |
michael@428 | 434 | /* display stand-alone license information */ |
michael@428 | 435 | if (license) { |
michael@428 | 436 | fprintf(stdout, "%s", LICENSE); |
michael@428 | 437 | exit(0); |
michael@428 | 438 | } |
michael@428 | 439 | |
michael@428 | 440 | /* determine our current real and effective user/group ids */ |
michael@428 | 441 | my_uid = getuid(); |
michael@428 | 442 | my_gid = getgid(); |
michael@428 | 443 | my_euid = geteuid(); |
michael@428 | 444 | my_egid = getegid(); |
michael@428 | 445 | if ((pw = getpwuid(my_uid)) == NULL) |
michael@428 | 446 | fatal("unable to resolve current user id %d: %s", my_uid, strerror(errno)); |
michael@428 | 447 | if ((gr = getgrgid(my_gid)) == NULL) |
michael@428 | 448 | fatal("unable to resolve current group id %d: %s", my_gid, strerror(errno)); |
michael@428 | 449 | debug("current-user: usr=%s uid=%d euid=%d grp=%s gid=%d egid=%d", |
michael@428 | 450 | pw->pw_name, my_uid, my_euid, gr->gr_name, my_gid, my_egid); |
michael@428 | 451 | |
michael@428 | 452 | /* determine super user/group id */ |
michael@428 | 453 | if ((pw = getpwnam(OPENPKG_SUSR)) == NULL) |
michael@428 | 454 | fatal("unable to resolve OpenPKG superuser username \"%s\": %s", OPENPKG_SUSR, strerror(errno)); |
michael@428 | 455 | s_uid = pw->pw_uid; |
michael@428 | 456 | s_gid = pw->pw_gid; |
michael@428 | 457 | debug("super-user: s_usr=%s s_uid=%d s_gid=%d", OPENPKG_SUSR, s_uid, s_gid); |
michael@428 | 458 | |
michael@428 | 459 | /* determine management user/group id */ |
michael@428 | 460 | if ((pw = getpwnam(OPENPKG_MUSR)) == NULL) |
michael@428 | 461 | fatal("unable to resolve OpenPKG management username \"%s\": %s", OPENPKG_MUSR, strerror(errno)); |
michael@428 | 462 | m_uid = pw->pw_uid; |
michael@428 | 463 | m_gid = pw->pw_gid; |
michael@428 | 464 | debug("management-user: m_grp=%s m_uid=%d m_gid=%d", OPENPKG_MUSR, m_uid, m_gid); |
michael@428 | 465 | |
michael@428 | 466 | /* determine whether caller is explicitly configured as a management user */ |
michael@428 | 467 | is_manager = 0; |
michael@428 | 468 | if (!keep_original_privileges) |
michael@428 | 469 | is_manager = check_whether_is_manager(my_uid, my_gid, m_uid, m_gid); |
michael@428 | 470 | debug("current user is manager: %s", is_manager ? "yes" : "no"); |
michael@428 | 471 | |
michael@428 | 472 | /* determine whether command requires super-user privileges */ |
michael@428 | 473 | require_superuser = check_whether_require_superuser(argc, argv); |
michael@428 | 474 | debug("current command requires super user privileges: %s", require_superuser ? "yes" : "no"); |
michael@428 | 475 | |
michael@428 | 476 | /* adjust privileges according to determined information */ |
michael@428 | 477 | if (!keep_original_privileges && require_superuser && is_manager && my_euid == 0) { |
michael@428 | 478 | /* increase privileges to super user */ |
michael@428 | 479 | debug("increase privileges to super user"); |
michael@428 | 480 | adjust_privileges(s_uid, s_gid, 1); |
michael@428 | 481 | } |
michael@428 | 482 | else if (!keep_original_privileges && !require_superuser && is_manager && my_euid == 0) { |
michael@428 | 483 | /* decrease privileges to management user */ |
michael@428 | 484 | debug("decrease privileges to management user"); |
michael@428 | 485 | adjust_privileges(m_uid, m_gid, 1); |
michael@428 | 486 | } |
michael@428 | 487 | else /* keep_original_privileges || !is_manager */ { |
michael@428 | 488 | /* drop effective privileges for current user*/ |
michael@428 | 489 | debug("drop effective privileges for current user"); |
michael@428 | 490 | adjust_privileges(my_uid, my_gid, 0); |
michael@428 | 491 | } |
michael@428 | 492 | |
michael@428 | 493 | /* pass-through control to real Execution Frontend (shell script) */ |
michael@428 | 494 | argv[0] = OPENPKG_PREFIX "/lib/openpkg/openpkg"; |
michael@428 | 495 | debug("execute \"%s\"", argv[0]); |
michael@428 | 496 | if (!dry_run) { |
michael@428 | 497 | if (execve(argv[0], argv, envp) == -1) |
michael@428 | 498 | fatal("failed to execute \"%s\": %s", argv[0], strerror(errno)); |
michael@428 | 499 | /* NOT REACHED */ |
michael@428 | 500 | fatal("INTERNAL ERROR"); |
michael@428 | 501 | } |
michael@428 | 502 | return 0; |
michael@428 | 503 | } |
michael@428 | 504 |