/* BS2000 requires a "special" version of fork() before a setuid() call */ pid_t os_fork(const char *user) { pid_t pid; char username[USER_LEN+1]; switch (os_forktype(0)) { case bs2_FORK: pid = fork(); break; case bs2_UFORK: apr_cpystrn(username, user, sizeof username); /* Make user name all upper case - for some versions of ufork() */ ap_str_toupper(username); pid = ufork(username); if (pid == -1 && errno == EPERM) { ap_log_error(APLOG_MARK, APLOG_EMERG, errno, ap_server_conf, APLOGNO(02181) "ufork: Possible mis-configuration " "for user %s - Aborting.", user); exit(1); } break; default: pid = 0; break; } return pid; }
/* It stores the account name for later use */ const char *os_set_account(pool *p, const char *account) { char account_temp[ACCT_LEN+1]; ap_cpystrn(account_temp, account, sizeof account_temp); /* Make account all upper case */ ap_str_toupper(account_temp); /* Pad to length 8 */ ap_pad(account_temp, sizeof account_temp, ' '); bs2000_account = ap_pstrdup(p, account_temp); return NULL; }
AP_DECLARE(int) ap_regname(const ap_regex_t *preg, apr_array_header_t *names, const char *prefix, int upper) { int namecount; int nameentrysize; int i; char *nametable; pcre_fullinfo((const pcre *)preg->re_pcre, NULL, PCRE_INFO_NAMECOUNT, &namecount); pcre_fullinfo((const pcre *)preg->re_pcre, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize); pcre_fullinfo((const pcre *)preg->re_pcre, NULL, PCRE_INFO_NAMETABLE, &nametable); for (i = 0; i < namecount; i++) { const char *offset = nametable + i * nameentrysize; int capture = ((offset[0] << 8) + offset[1]); while (names->nelts <= capture) { apr_array_push(names); } if (upper || prefix) { char *name = ((char **) names->elts)[capture] = prefix ? apr_pstrcat(names->pool, prefix, offset + 2, NULL) : apr_pstrdup(names->pool, offset + 2); if (upper) { ap_str_toupper(name); } } else { ((const char **)names->elts)[capture] = offset + 2; } } return namecount; }
/* This routine complements the setuid() call: it causes the BS2000 job * environment to be switched to the target user's user id. * That is important if CGI scripts try to execute native BS2000 commands. */ int os_init_job_environment(server_rec *server, const char *user_name, int one_process) { _rini_struct inittask; char username[USER_LEN+1]; bs2_ForkType type = os_forktype(); /* We can be sure that no change to uid==0 is possible because of * the checks in http_core.c:set_user() */ /* The _rini() function works only after a prior _rfork(). * In the case of one_process, it would fail. */ if (one_process) { type = forktype = bs2_noFORK; ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server, "The debug mode of Apache should only " "be started by an unprivileged user!"); return 0; } /* If no _rini() is required, then return quickly. */ if (type != bs2_RFORK_RINI && type != bs2_FORK_RINI) return 0; /* An Account is required for _rini() */ if (bs2000_account == NULL) { ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server, "No BS2000Account configured - cannot switch to User %s", user_name); exit(APEXIT_CHILDFATAL); } ap_cpystrn(username, user_name, sizeof username); /* Make user name all upper case */ ap_str_toupper(username); /* Pad to length 8 */ ap_pad(username, sizeof username, ' '); inittask.username = username; inittask.account = bs2000_account; inittask.processor_name = " "; /* Switch to the new logon user (setuid() and setgid() are done later) */ /* Only the super user can switch identities. */ if (_rini(&inittask) != 0) { ap_log_error(APLOG_MARK, APLOG_ALERT, server, "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"", inittask.username, inittask.account); exit(APEXIT_CHILDFATAL); } return 0; }