int main(int argc, char **argv, char **envp) { enum BadCode bad = NotBad; int i, j; char *a, *e; #ifdef USE_PAM pam_handle_t *pamh = NULL; struct passwd *pw; int retval; pw = getpwuid(getuid()); if (pw == NULL) { bad = InternalError; } if (!bad) { retval = pam_start("xserver", pw->pw_name, &conv, &pamh); if (retval != PAM_SUCCESS) bad = PamFailed; } if (!bad) { retval = pam_authenticate(pamh, 0); if (retval != PAM_SUCCESS) { pam_end(pamh, retval); bad = PamAuthFailed; } } if (!bad) { retval = pam_acct_mgmt(pamh, 0); if (retval != PAM_SUCCESS) { pam_end(pamh, retval); bad = PamAuthFailed; } } /* this is not a session, so do not do session management */ if (!bad) pam_end(pamh, PAM_SUCCESS); #endif /* USE_PAM */ #if CHECK_EUID if (!bad && geteuid() == 0 && getuid() != geteuid()) { #else if (!bad) { #endif /* Check each argv[] */ for (i = 1; i < argc; i++) { /* Check for known bad arguments */ #if REJECT_CONFIG if (strcmp(argv[i], "-config") == 0) { bad = UnsafeArg; break; } #endif #if REJECT_XKBDIR if (strcmp(argv[i], "-xkbdir") == 0) { bad = UnsafeArg; break; } #endif if (strlen(argv[i]) > MAX_ARG_LENGTH) { bad = ArgTooLong; break; } a = argv[i]; while (*a) { if (checkPrintable(*a) == 0) { bad = UnprintableArg; break; } a++; } if (bad) break; } /* Check each envp[] */ if (!bad) for (i = 0; envp[i]; i++) { /* Check for bad environment variables and values */ #if REMOVE_ENV_LD while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) { for (j = i; envp[j]; j++) { envp[j] = envp[j+1]; } } #endif if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) { #if REMOVE_LONG_ENV for (j = i; envp[j]; j++) { envp[j] = envp[j+1]; } i--; #else char *eq; int len; eq = strchr(envp[i], '='); if (!eq) continue; len = eq - envp[i]; e = malloc(len + 1); if (!e) { bad = InternalError; break; } strncpy(e, envp[i], len); e[len] = 0; if (len >= 4 && (strcmp(e + len - 4, "PATH") == 0 || strcmp(e, "TERMCAP") == 0)) { if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) { bad = EnvTooLong; break; } else { free(e); } } else { bad = EnvTooLong; break; } #endif } } } switch (bad) { case NotBad: argv[0] = XSERVER_PATH; execve(XSERVER_PATH, argv, envp); fprintf(stderr, "execve failed for %s (errno %d)\n", XSERVER_PATH, errno); break; case UnsafeArg: fprintf(stderr, "Command line argument number %d is unsafe\n", i); fprintf(stderr, ARGMSG); break; case ArgTooLong: fprintf(stderr, "Command line argument number %d is too long\n", i); fprintf(stderr, ARGMSG); break; case UnprintableArg: fprintf(stderr, "Command line argument number %d contains unprintable" " characters\n", i); fprintf(stderr, ARGMSG); break; case EnvTooLong: fprintf(stderr, "Environment variable `%s' is too long\n", e); fprintf(stderr, ENVMSG); break; case InternalError: fprintf(stderr, "Internal Error\n"); break; #ifdef USE_PAM case PamFailed: fprintf(stderr, "Authentication System Failure, " "missing or mangled PAM configuration file or module?\n"); break; case PamAuthFailed: fprintf(stderr, "Authentication failed - cannot start X server.\nPerhaps you do not have console ownership?"); break; #endif default: fprintf(stderr, "Unknown error\n"); fprintf(stderr, ARGMSG); fprintf(stderr, ENVMSG); break; } exit(1); }
int main(int cArgs, char **apszArgs) { int rc = RTR3InitExe(cArgs, &apszArgs, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); enum { OPTION_FORMAT = 1, OPTION_COMMAND, OPTION_ARGUMENTS, OPTION_DESCRIPTION, OPTION_SERVICE_NAME, OPTION_ONE_SHOT, OPTION_STOP_COMMAND, OPTION_STOP_ARGUMENTS, OPTION_STATUS_COMMAND, OPTION_STATUS_ARGUMENTS }; static const RTGETOPTDEF s_aOptions[] = { { "--format", OPTION_FORMAT, RTGETOPT_REQ_STRING }, { "--command", OPTION_COMMAND, RTGETOPT_REQ_STRING }, { "--arguments", OPTION_ARGUMENTS, RTGETOPT_REQ_STRING }, { "--description", OPTION_DESCRIPTION, RTGETOPT_REQ_STRING }, { "--service-name", OPTION_SERVICE_NAME, RTGETOPT_REQ_STRING }, { "--one-shot", OPTION_ONE_SHOT, RTGETOPT_REQ_NOTHING }, { "--stop-command", OPTION_STOP_COMMAND, RTGETOPT_REQ_STRING }, { "--stop-arguments", OPTION_STOP_ARGUMENTS, RTGETOPT_REQ_STRING }, { "--status-command", OPTION_STATUS_COMMAND, RTGETOPT_REQ_STRING }, { "--status-arguments", OPTION_STATUS_ARGUMENTS, RTGETOPT_REQ_STRING } }; int ch; struct SERVICEPARAMETERS Parameters = { FORMAT_NONE }; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, cArgs, apszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 'h': showUsage(apszArgs[0]); return RTEXITCODE_SUCCESS; break; case 'V': showLogo(); return RTEXITCODE_SUCCESS; break; case OPTION_FORMAT: if (errorIfSet("--format", Parameters.enmFormat != FORMAT_NONE)) return(RTEXITCODE_SYNTAX); Parameters.enmFormat = getFormat("--format", ValueUnion.psz); if (Parameters.enmFormat == FORMAT_NONE) return(RTEXITCODE_SYNTAX); break; case OPTION_COMMAND: if (errorIfSet("--command", Parameters.pcszCommand)) return(RTEXITCODE_SYNTAX); Parameters.pcszCommand = ValueUnion.psz; if (!checkAbsoluteFilePath("--command", Parameters.pcszCommand)) return(RTEXITCODE_SYNTAX); break; case OPTION_ARGUMENTS: if (errorIfSet("--arguments", Parameters.pcszArguments)) return(RTEXITCODE_SYNTAX); /* Quoting will be checked while writing out the string. */ Parameters.pcszArguments = ValueUnion.psz; break; case OPTION_DESCRIPTION: if (errorIfSet("--description", Parameters.pcszDescription)) return(RTEXITCODE_SYNTAX); Parameters.pcszDescription = ValueUnion.psz; if (!checkPrintable("--description", Parameters.pcszDescription)) return(RTEXITCODE_SYNTAX); break; case OPTION_SERVICE_NAME: if (errorIfSet("--service-name", Parameters.pcszServiceName)) return(RTEXITCODE_SYNTAX); Parameters.pcszServiceName = ValueUnion.psz; if (!checkGraphic("--service-name", Parameters.pcszServiceName)) return(RTEXITCODE_SYNTAX); break; case OPTION_ONE_SHOT: Parameters.fOneShot = true; break; case OPTION_STOP_COMMAND: if (errorIfSet("--stop-command", Parameters.pcszStopCommand)) return(RTEXITCODE_SYNTAX); Parameters.pcszStopCommand = ValueUnion.psz; if (!checkAbsoluteFilePath("--stop-command", Parameters.pcszStopCommand)) return(RTEXITCODE_SYNTAX); break; case OPTION_STOP_ARGUMENTS: if (errorIfSet("--stop-arguments", Parameters.pcszStopArguments)) return(RTEXITCODE_SYNTAX); /* Quoting will be checked while writing out the string. */ Parameters.pcszStopArguments = ValueUnion.psz; break; case OPTION_STATUS_COMMAND: if (errorIfSet("--status-command", Parameters.pcszStatusCommand)) return(RTEXITCODE_SYNTAX); Parameters.pcszStatusCommand = ValueUnion.psz; if (!checkAbsoluteFilePath("--status-command", Parameters.pcszStatusCommand)) return(RTEXITCODE_SYNTAX); break; case OPTION_STATUS_ARGUMENTS: if (errorIfSet("--status-arguments", Parameters.pcszStatusArguments)) return(RTEXITCODE_SYNTAX); /* Quoting will be checked while writing out the string. */ Parameters.pcszStatusArguments = ValueUnion.psz; break; default: return RTGetOptPrintError(ch, &ValueUnion); } } if (Parameters.enmFormat == FORMAT_NONE) { RTStrmPrintf(g_pStdErr, "--format must be specified.\n"); return(RTEXITCODE_SYNTAX); } if (Parameters.pcszArguments && !Parameters.pcszCommand) { RTStrmPrintf(g_pStdErr, "--arguments requires --command to be specified.\n"); return(RTEXITCODE_SYNTAX); } if (Parameters.pcszStopArguments && !Parameters.pcszStopCommand) { RTStrmPrintf(g_pStdErr, "--stop-arguments requires --stop-command to be specified.\n"); return(RTEXITCODE_SYNTAX); } if (Parameters.pcszStatusArguments && !Parameters.pcszStatusCommand) { RTStrmPrintf(g_pStdErr, "--status-arguments requires --status-command to be specified.\n"); return(RTEXITCODE_SYNTAX); } return createServiceFile(&Parameters) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }