1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
61 #include "http_config.h"
64 #include <sys/utsname.h>
69 static const char *bs2000_account = NULL;
72 bs2_unknown, /* not initialized yet. */
73 bs2_noFORK, /* no fork() because -X flag was specified */
74 bs2_FORK, /* only fork() because uid != 0 */
75 bs2_FORK_RINI, /* prior to A17, regular fork() and _rini() was used. */
76 bs2_RFORK_RINI, /* for A17, use of _rfork() and _rini() was required */
77 bs2_UFORK /* As of A18, the new ufork() is used. */
80 static bs2_ForkType forktype = bs2_unknown;
82 #if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
89 extern int _rini(_rini_struct *);
90 #endif /* !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) */
93 static void ap_pad(char *dest, size_t size, char ch)
95 int i = strlen(dest); /* Leave space for trailing '\0' */
100 dest[size-1] = '\0'; /* Guarantee for trailing '\0' */
103 static void ap_str_toupper(char *str)
106 *str = apr_toupper(*str);
111 /* Determine the method for forking off a child in such a way as to
112 * set both the POSIX and BS2000 user id's to the unprivileged user.
114 static bs2_ForkType os_forktype(void)
116 struct utsname os_version;
118 /* have we checked the OS version before? If yes return the previous
119 * result - the OS release isn't going to change suddenly!
121 if (forktype != bs2_unknown) {
125 /* If the user is unprivileged, use the normal fork() only. */
127 return forktype = bs2_FORK;
130 if (uname(&os_version) < 0)
132 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
133 "uname() failed - aborting.");
134 exit(APEXIT_CHILDFATAL);
138 * Old BS2000/OSD versions (before XPG4 SPEC1170) don't work with Apache.
139 * Anyway, simply return a fork().
141 if (strcmp(os_version.release, "01.0A") == 0 ||
142 strcmp(os_version.release, "02.0A") == 0 ||
143 strcmp(os_version.release, "02.1A") == 0)
145 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
146 "Error: unsupported OS version. "
147 "You may encounter problems.");
151 /* The following versions are special:
152 * OS versions before A17 needs regular fork() and _rini().
153 * A17 requires _rfork() and _rini(),
154 * and later versions need ufork().
156 else if (strcmp(os_version.release, "01.1A") == 0 ||
157 strcmp(os_version.release, "03.0A") == 0 ||
158 strcmp(os_version.release, "03.1A") == 0 ||
159 strcmp(os_version.release, "04.0A") == 0)
161 if (strcmp (os_version.version, "A18") >= 0)
162 forktype = bs2_UFORK;
164 else if (strcmp (os_version.version, "A17") < 0)
165 forktype = bs2_FORK_RINI;
168 forktype = bs2_RFORK_RINI;
171 /* All later OS versions will hopefully use ufork() only ;-) */
173 forktype = bs2_UFORK;
180 /* This routine is called by http_core for the BS2000Account directive */
181 /* It stores the account name for later use */
182 const char *os_set_account(apr_pool_t *p, const char *account)
184 char account_temp[ACCT_LEN+1];
186 apr_cpystrn(account_temp, account, sizeof account_temp);
188 /* Make account all upper case */
189 ap_str_toupper(account_temp);
191 /* Pad to length 8 */
192 ap_pad(account_temp, sizeof account_temp, ' ');
194 bs2000_account = apr_pstrdup(p, account_temp);
198 /* This routine complements the setuid() call: it causes the BS2000 job
199 * environment to be switched to the target user's user id.
200 * That is important if CGI scripts try to execute native BS2000 commands.
202 int os_init_job_environment(server_rec *server, const char *user_name, int one_process)
204 _rini_struct inittask;
205 char username[USER_LEN+1];
207 bs2_ForkType type = os_forktype();
209 /* We can be sure that no change to uid==0 is possible because of
210 * the checks in http_core.c:set_user()
213 /* The _rini() function works only after a prior _rfork().
214 * In the case of one_process, it would fail.
218 type = forktype = bs2_noFORK;
220 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, server,
221 "The debug mode of Apache should only "
222 "be started by an unprivileged user!");
226 /* If no _rini() is required, then return quickly. */
227 if (type != bs2_RFORK_RINI && type != bs2_FORK_RINI)
230 /* An Account is required for _rini() */
231 if (bs2000_account == NULL)
233 ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, server,
234 "No BS2000Account configured - cannot switch to User %s",
236 exit(APEXIT_CHILDFATAL);
239 apr_cpystrn(username, user_name, sizeof username);
241 /* Make user name all upper case */
242 ap_str_toupper(username);
244 /* Pad to length 8 */
245 ap_pad(username, sizeof username, ' ');
247 inittask.username = username;
248 inittask.account = bs2000_account;
249 inittask.processor_name = " ";
251 /* Switch to the new logon user (setuid() and setgid() are done later) */
252 /* Only the super user can switch identities. */
253 if (_rini(&inittask) != 0) {
255 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server,
256 "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"",
257 inittask.username, inittask.account);
259 exit(APEXIT_CHILDFATAL);
265 /* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */
266 pid_t os_fork(const char *user)
269 char username[USER_LEN+1];
271 switch (os_forktype()) {
282 apr_cpystrn(username, user, sizeof username);
284 /* Make user name all upper case - for some versions of ufork() */
285 ap_str_toupper(username);
287 pid = ufork(username);
288 if (pid == -1 && errno == EPERM) {
289 ap_log_error(APLOG_MARK, APLOG_EMERG, errno,
290 NULL, "ufork: Possible mis-configuration "
291 "for user %s - Aborting.", user);
304 #else /* _OSD_POSIX */
305 void bs2login_is_not_here()
308 #endif /* _OSD_POSIX */