martin 99/01/28 10:27:21
Modified: src CHANGES src/main http_main.c src/os/bs2000 bs2login.c Log: BS2000 only: Adapt to the new ufork() system call interface which will make subtasking easier on the OSD/POSIX mainframe environment. Revision Changes Path 1.1227 +4 -0 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.1226 retrieving revision 1.1227 diff -u -r1.1226 -r1.1227 --- CHANGES 1999/01/28 09:24:56 1.1226 +++ CHANGES 1999/01/28 18:27:17 1.1227 @@ -1,5 +1,9 @@ Changes with Apache 1.3.5 + *) BS2000: Adapt to the new ufork() system call interface which will + make subtasking easier on the OSD/POSIX mainframe environment. + [Martin Kraemer] + *) Add a compatibility define for escape_uri() -> ap_escape_uri() to ap_compat.h. [David White <[EMAIL PROTECTED]>] PR#3725 1.420 +1 -1 apache-1.3/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_main.c,v retrieving revision 1.419 retrieving revision 1.420 diff -u -r1.419 -r1.420 --- http_main.c 1999/01/08 08:48:46 1.419 +++ http_main.c 1999/01/28 18:27:19 1.420 @@ -3935,7 +3935,7 @@ if ((pid = fork()) == -1) { #else /*_OSD_POSIX*/ /* BS2000 requires a "special" version of fork() before a setuid() call */ - if ((pid = os_fork()) == -1) { + if ((pid = os_fork(ap_user_name)) == -1) { #endif /*_OSD_POSIX*/ ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process"); 1.9 +115 -72 apache-1.3/src/os/bs2000/bs2login.c Index: bs2login.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/os/bs2000/bs2login.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- bs2login.c 1999/01/01 19:05:27 1.8 +++ bs2login.c 1999/01/28 18:27:21 1.9 @@ -66,6 +66,17 @@ #define USER_LEN 8 static const char *bs2000_account = NULL; +typedef enum +{ + bs2_unknown, /* not initialized yet. */ + bs2_noFORK, /* no fork() because -X flag was specified */ + bs2_FORK, /* only fork() because uid != 0 */ + bs2_FORK_RINI, /* prior to A17, regular fork() and _rini() was used. */ + bs2_RFORK_RINI, /* for A17, use of _rfork() and _rini() was required */ + bs2_UFORK /* As of A18, the new ufork() is used. */ +} bs2_ForkType; + +static bs2_ForkType forktype = bs2_unknown; static void ap_pad(char *dest, size_t size, char ch) @@ -86,6 +97,75 @@ } } +/* Determine the method for forking off a child in such a way as to + * set both the POSIX and BS2000 user id's to the unprivileged user. + */ +static bs2_ForkType os_forktype(void) +{ + struct utsname os_version; + + /* have we checked the OS version before? If yes return the previous + * result - the OS release isn't going to change suddenly! + */ + if (forktype != bs2_unknown) { + return forktype; + } + + /* If the user is unprivileged, use the normal fork() only. */ + if (getuid() != 0) { + return forktype = bs2_FORK; + } + + if (uname(&os_version) < 0) + { + ap_log_error(APLOG_MARK, APLOG_ALERT, NULL, + "uname() failed - aborting."); + exit(APEXIT_CHILDFATAL); + } + + /* + * Old BS2000/OSD versions (before XPG4 SPEC1170) don't work with Apache. + * Anyway, simply return a fork(). + */ + if (strcmp(os_version.release, "01.0A") == 0 || + strcmp(os_version.release, "02.0A") == 0 || + strcmp(os_version.release, "02.1A") == 0) + { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL, + "Error: unsupported OS version. " + "You may encounter problems."); + forktype = bs2_FORK; + } + + /* The following versions are special: + * OS versions before A17 needs regular fork() and _rini(). + * A17 requires _rfork() and _rini(), + * and later versions need ufork(). + */ + else if (strcmp(os_version.release, "01.1A") == 0 || + strcmp(os_version.release, "03.0A") == 0 || + strcmp(os_version.release, "03.1A") == 0 || + strcmp(os_version.release, "04.0A") == 0) + { + if (strcmp (os_version.version, "A18") >= 0) + forktype = bs2_UFORK; + + else if (strcmp (os_version.version, "A17") < 0) + forktype = bs2_FORK_RINI; + + else + forktype = bs2_RFORK_RINI; + } + + /* All later OS versions will hopefully use ufork() only ;-) */ + else + forktype = bs2_UFORK; + + return forktype; +} + + + /* This routine is called by http_core for the BS2000Account directive */ /* It stores the account name for later use */ const char *os_set_account(pool *p, const char *account) @@ -113,6 +193,7 @@ _rini_struct inittask; char username[USER_LEN+1]; int save_errno; + 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() @@ -121,6 +202,20 @@ /* 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) { @@ -130,16 +225,6 @@ exit(APEXIT_CHILDFATAL); } - /* The one_process test is placed _behind_ the BS2000Account test - * because we never want the user to forget configuring an account. - */ - if (one_process) { - 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; - } - ap_cpystrn(username, user_name, sizeof username); /* Make user name all upper case */ @@ -153,34 +238,13 @@ inittask.processor_name = " "; /* Switch to the new logon user (setuid() and setgid() are done later) */ - /* Only the super use can switch identities. */ + /* Only the super user can switch identities. */ if (_rini(&inittask) != 0) { - save_errno = errno; ap_log_error(APLOG_MARK, APLOG_ALERT, server, "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"", inittask.username, inittask.account); - if (save_errno == EAGAIN) { - /* This funny error code does NOT mean that the operation should - * be retried. Instead it means that authentication failed - * because of possibly incompatible `JOBCLASS'es between - * the calling (SYSROOT) and the target non-privileged user id. - * Help the administrator by logging a hint. - */ - char *curr_user, curr_uid[L_cuserid]; - - if ((curr_user = cuserid(curr_uid)) == NULL) { - /* This *SHOULD* not occur. But if it does, deal with it. */ - ap_snprintf(curr_uid, sizeof curr_uid, "#%u", getuid()); - curr_user = curr_uid; - } - - ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server, - "_rini: Hint: Possible reason: JOBCLASS of user %s " - "not compatible with that of user %s ?", - curr_user, inittask.username); - } exit(APEXIT_CHILDFATAL); } @@ -188,51 +252,30 @@ } /* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */ -/* Additionally, there's an OS release dependency here :-((( */ -/* I'm sorry, but there was no other way to make it work. -Martin */ -pid_t os_fork(void) +pid_t os_fork(const char *user) { - struct utsname os_version; + pid_t pid; - /* - * When we run as a normal user (and bypass setuid() and _rini()), - * we use the regular fork(). - */ - if (getuid() != 0) { - return fork(); - } + switch (os_forktype()) { + case bs2_FORK: + case bs2_FORK_RINI: + pid = fork(); + break; - if (uname(&os_version) >= 0) - { - /* - * Old versions (before XPG4 SPEC1170) don't work with Apache - * and they require a fork(), not a _rfork() - */ - if (strcmp(os_version.release, "01.0A") == 0 || - strcmp(os_version.release, "02.0A") == 0 || - strcmp(os_version.release, "02.1A") == 0) - { - return fork(); - } - - /* The following versions are special: - * OS versions before A17 work with regular fork() only, - * later versions with _rfork() only. - */ - if (strcmp(os_version.release, "01.1A") == 0 || - strcmp(os_version.release, "03.0A") == 0 || - strcmp(os_version.release, "03.1A") == 0 || - strcmp(os_version.release, "04.0A") == 0) - { - return (strcmp (os_version.version, "A17") < 0) - ? fork() : _rfork(); - } + case bs2_RFORK_RINI: + pid = _rfork(); + break; + + case bs2_UFORK: + pid = ufork(user); + break; + + default: + pid = 0; + break; } - /* All later OS versions will require _rfork() - * to prepare for authorization with _rini() - */ - return _rfork(); + return pid; } #else /* _OSD_POSIX */