1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "http_config.h"
22 #include <sys/utsname.h>
27 static const char *bs2000_account = NULL;
30 bs2_unknown, /* not initialized yet. */
31 bs2_noFORK, /* no fork() because -X flag was specified */
32 bs2_FORK, /* only fork() because uid != 0 */
33 bs2_FORK_RINI, /* prior to A17, regular fork() and _rini() was used. */
34 bs2_RFORK_RINI, /* for A17, use of _rfork() and _rini() was required */
35 bs2_UFORK /* As of A18, the new ufork() is used. */
38 static bs2_ForkType forktype = bs2_unknown;
40 #if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
47 extern int _rini(_rini_struct *);
48 #endif /* !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) */
51 static void ap_pad(char *dest, size_t size, char ch)
53 int i = strlen(dest); /* Leave space for trailing '\0' */
58 dest[size-1] = '\0'; /* Guarantee for trailing '\0' */
61 static void ap_str_toupper(char *str)
64 *str = apr_toupper(*str);
69 /* Determine the method for forking off a child in such a way as to
70 * set both the POSIX and BS2000 user id's to the unprivileged user.
72 static bs2_ForkType os_forktype(void)
74 struct utsname os_version;
76 /* have we checked the OS version before? If yes return the previous
77 * result - the OS release isn't going to change suddenly!
79 if (forktype != bs2_unknown) {
83 /* If the user is unprivileged, use the normal fork() only. */
85 return forktype = bs2_FORK;
88 if (uname(&os_version) < 0)
90 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
91 "uname() failed - aborting.");
92 exit(APEXIT_CHILDFATAL);
96 * Old BS2000/OSD versions (before XPG4 SPEC1170) don't work with Apache.
97 * Anyway, simply return a fork().
99 if (strcmp(os_version.release, "01.0A") == 0 ||
100 strcmp(os_version.release, "02.0A") == 0 ||
101 strcmp(os_version.release, "02.1A") == 0)
103 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
104 "Error: unsupported OS version. "
105 "You may encounter problems.");
109 /* The following versions are special:
110 * OS versions before A17 needs regular fork() and _rini().
111 * A17 requires _rfork() and _rini(),
112 * and later versions need ufork().
114 else if (strcmp(os_version.release, "01.1A") == 0 ||
115 strcmp(os_version.release, "03.0A") == 0 ||
116 strcmp(os_version.release, "03.1A") == 0 ||
117 strcmp(os_version.release, "04.0A") == 0)
119 if (strcmp (os_version.version, "A18") >= 0)
120 forktype = bs2_UFORK;
122 else if (strcmp (os_version.version, "A17") < 0)
123 forktype = bs2_FORK_RINI;
126 forktype = bs2_RFORK_RINI;
129 /* All later OS versions will hopefully use ufork() only ;-) */
131 forktype = bs2_UFORK;
138 /* This routine is called by http_core for the BS2000Account directive */
139 /* It stores the account name for later use */
140 const char *os_set_account(apr_pool_t *p, const char *account)
142 char account_temp[ACCT_LEN+1];
144 apr_cpystrn(account_temp, account, sizeof account_temp);
146 /* Make account all upper case */
147 ap_str_toupper(account_temp);
149 /* Pad to length 8 */
150 ap_pad(account_temp, sizeof account_temp, ' ');
152 bs2000_account = apr_pstrdup(p, account_temp);
156 /* This routine complements the setuid() call: it causes the BS2000 job
157 * environment to be switched to the target user's user id.
158 * That is important if CGI scripts try to execute native BS2000 commands.
160 int os_init_job_environment(server_rec *server, const char *user_name, int one_process)
162 _rini_struct inittask;
163 char username[USER_LEN+1];
165 bs2_ForkType type = os_forktype();
167 /* We can be sure that no change to uid==0 is possible because of
168 * the checks in http_core.c:set_user()
171 /* The _rini() function works only after a prior _rfork().
172 * In the case of one_process, it would fail.
176 type = forktype = bs2_noFORK;
178 ap_log_error(APLOG_MARK, APLOG_ERR, 0, server,
179 "The debug mode of Apache should only "
180 "be started by an unprivileged user!");
184 /* If no _rini() is required, then return quickly. */
185 if (type != bs2_RFORK_RINI && type != bs2_FORK_RINI)
188 /* An Account is required for _rini() */
189 if (bs2000_account == NULL)
191 ap_log_error(APLOG_MARK, APLOG_ALERT, 0, server,
192 "No BS2000Account configured - cannot switch to User %s",
194 exit(APEXIT_CHILDFATAL);
197 apr_cpystrn(username, user_name, sizeof username);
199 /* Make user name all upper case */
200 ap_str_toupper(username);
202 /* Pad to length 8 */
203 ap_pad(username, sizeof username, ' ');
205 inittask.username = username;
206 inittask.account = bs2000_account;
207 inittask.processor_name = " ";
209 /* Switch to the new logon user (setuid() and setgid() are done later) */
210 /* Only the super user can switch identities. */
211 if (_rini(&inittask) != 0) {
213 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server,
214 "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"",
215 inittask.username, inittask.account);
217 exit(APEXIT_CHILDFATAL);
223 /* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */
224 pid_t os_fork(const char *user)
227 char username[USER_LEN+1];
229 switch (os_forktype()) {
240 apr_cpystrn(username, user, sizeof username);
242 /* Make user name all upper case - for some versions of ufork() */
243 ap_str_toupper(username);
245 pid = ufork(username);
246 if (pid == -1 && errno == EPERM) {
247 ap_log_error(APLOG_MARK, APLOG_EMERG, errno,
248 NULL, "ufork: Possible mis-configuration "
249 "for user %s - Aborting.", user);
262 #else /* _OSD_POSIX */
263 void bs2login_is_not_here()
266 #endif /* _OSD_POSIX */