/* ==================================================================== * Copyright (c) 1995 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see . * */ /* =================================================================== * mod_auth_ora8 version 2.0 - October, 30th 1999 * Copyright (c) 1999 Ben Reser * * Oracle8 Database Authentication Module for Apache * * I wrote this module because currently there is no module to do this. * You can do it with mod_perl and the DBI interfaces therein. However, * copiling in a copy of Perl seems like a bit of an overkill just for * a simple authentication routine such as this. * * This Module is largely based on the mod_auth_msql module and as a result * all of it's copyright appears below. I'm releasing this code under * the same licensing agreements as is set forth above in the orignal * Apache Group license. * * For the most recent information on this module please look at: * http://ben.reser.org/mod_auth_ora/ * * Credit is due to the following individuals for their work on the mod_auth_msql * prior to my adaptation: Rob McCool, Brian Behlendorf, rst, * and Dirk VanGulik * * Quick Compilation Instructions: * Make the followin modifcations to the Configuration File: * In EXTRA_CFLAGS add: -DORACLE_HOME=\"$(ORACLE_HOME)\" * Yes the \s and "s stay * In EXTRA_LFLAGS add: -L$(ORACLE_HOME)/lib * In EXTRA_LIBS add: -lclntsh -lnbeq8 -lnhost8 -ln8 -lncrypt8 -lnoss8 -lnidx8 -lnus8 -lnk58 -lnsslb8 -lnoname8 * In EXTRA_INCLUDES add: -I$(ORACLE_HOME)/rdbms/demo * Add a line that says: AddModule modules/extra/mod_auth_ora8.o * This can go just about anywhere but right around the other auth modules is a good idea. * Ensure that you have the ORACLE_HOME enviornment variable set properly! * Run the Configure script. * Run make * * No guarantee that this will work... I've only tested this personally on my machine, * however many of the decisions as far as where to grab things were matched with * DBD::Oracle of the Perl variety. So I'm hoping this will be somewhat universal. * FYI: My development platform was Solaris 2.7 Sparc, Oracle 8.1.5.0, Apache 1.3.6, * and gcc 2.8.1... All other platforms are at your own risk. * * Outline: * * This module allows access control using the commercial * Oracle8 database. * * An example table could be: * * create table user_records ( * user_id varchar2(32) primary key, * passwd varchar2(32), * grp varchar2(32) * ); * * The user_id can be as long as desired; however some of the * popular web browsers truncate, or stop the user from entering * names longer than 32 characters. Furthermore the 'crypt' function * on your platform might impose further limits. Also use of * the 'require users uid [uid..]' directive in the access.conf file, * where the user ids are separated by spaces can possibly prohibit the * use of spaces in your user-names. Also, not the MAX_FIELD_LEN define * somewhere below. * * To use the above, the following example could be in your access.conf * file. Also there is a more elaborate description afther this example. * * * * Auth_ORA8_SID ORCL * * The name of the database(SID) which contains *both* * the tables for group and user/passwords. Currently it * is not possible to have these split over two databases. * This will be set as the ORACLE_SID environment variable. * If you want to use a network connection (non local) to * the database you'll need to use Auth_ORA8_TWO_TASK (which * is explained below). * * Auth_ORA8uid_login wwwauth * Auth_ORA8pwd_login wwwauth_pass * * These two parameters set the userid and password that * is given to Oracle to get access to the database. * Read below for an important security note! * * Auth_ORA8pwd_table user_records * * Here the table which contain the uid/password combination * is specified. * * Auth_ORA8uid_field user_id * Auth_ORA8pwd_field passwd * * These two directive specify the field names in the 'user_record' * table. Currently the user_id field *MUST* be a primary key or * one must ensure that each user only occurs *once* in the table. * If a UID occurs twice access is denied by default. * * Auth_ORA8grp_table user_records * Auth_ORA8grp_field grp * * Optionaly one can also specify a table which contains the * user/group combinations. This can be the same table which * also contains the username/password combinations. However * if a user belongs to two or more groups, one will have to * use a differt table with multiple entries. * * Auth_ORA8_nopasswd off * Auth_ORA8_Authorative on * Auth_ORA8_EncryptedPasswords on * * These three optional fields (all set to the sensible defaults, * so you really do not have to enter them) are described in more * detail below. If you choose to set these to any other values than * the above be very sure you understand the security implications and * do verify that apache does what you exect it to do. * * AuthName example ORA8 realm * AuthType basic * * Normal apache/ncsa tokens for access control * * * order deny,allow * allow from all * * require valid-user * 'valid-user'; allow in any user which has a valid uid/passwd * pair in the above pwd_table. * or * require user smith jones * Limit access to users who have a valid uid/passwd pair in the * above pwd_table AND whose uid is 'smith' or 'jones'. Do note that * the uid's are separated by 'spaces' for historic (ncsa) reasons. * So allowing uids with spaces might cause problems. * * require group has_paid * Optionally also ensure that the uid has the value 'has_paid' in * the group field in the group table. * * * * End of the example * * - full description of all tokens: - * * Directives: * * Auth_ORA8_SID Name of the database(SID) in which the following * table(s) are contained. This is the equivelent of * the ORACLE_SID environment variable. If you're * not using SQLNET you probably just want to set this * as your local SID e.g. ORCL * * Auth_ORA8_TWO_TASK This is the same as the TWO_TASK environment variable * and can be set to allow access to remote databases * across a network. If you use this setting it *WILL* * override the Auth_ORA8_SID setting above. You should * consult the proper documentation if you want to use * this but here's an example: T:hostname:SID * * Auth_ORA8uid_login User name to log in to Oracle as. * Auth_ORA8pwd_login Password that is associated with the above user. * It is *STRONGLY* recommended that you create a seperate * user in Oracle for this purpose that only has read * access to the database. The reasonin behind this is * most configuration files are world readable on machines * and this would of course allow anyone who can read these * files an easy way in. You probably also should only * allow permission to read the tables that you're using * for authentication. * * Auth_ORA8pwd_table Contains at least the fields with the * username and the (encrypted) password. Each * uid should only occur once in this table and * for performance reasons should be a primary key. * Normally this table is compulsory, but it is * possible to use a fall-through to other methods * and use the ORA8 module for group control only; * see the Authorative directive below. * * Auth_ORA8grp_table Contains at least the fields with the * username and the groupname. A user which * is in multiple groups has therefore * multiple entries; this might be some per- * formance problems associated with this; and one * might consider to have separate tables for each * group (rather than all groups in one table) if * your directory structure allows for it. * One only needs to specify this table when doing * group control. * * Auth_ORA8uid_field Name of the field containing the username * Auth_ORA8pwd_field Fieldname for the passwords * Auth_ORA8grp_field Fieldname for the groupname * * Only the fields used need to be specified. When this * module is compiled with the BACKWARD_VITEK option the * uid and pwd field names default to 'user' and 'password'. * * * Auth_ORA8_nopasswd * skip password comparison if passwd field is * empty; i.e. allow 'any' password. This is off * by default; thus to ensure that an empty field * in the Oralce table does not allow people in by * default with a random password. * * Auth_ORA8_Authorative * default is 'on'. When set on, there is no * fall through to other authorization methods. So if a * user is not in the Oracle table (and perhaps * not in the right group) or has the password wrong, then * he or she is denied access. When this directive is set to * 'off' control is passed on to any other authorization * modules, such as the basic auth module wih the htpasswd * file and or the unix-(g)dbm modules. * The default is 'ON' to avoid nasty 'fall-through' sur- * prizes. Do be sure you know what you decide to switch * it off. * * Auth_ORA8_EncryptedPasswords * default is on. When set on, the values in the * pwd_field are assumed to be crypted using *your* * machines 'crypt' function; and the incoming password * is 'crypt'ed before comparison. When this function is * off, the comparison is done directly with the plaintext * entered password. (Yes; http-basic-auth does send the * password as plaintext over the wire :-( ). The default * is a sensible 'on', and I personally thing that it is * a *very-bad-idea* to change this. However a multi * vendor or international environment (which sometimes * leads to different crypts functions) might force you to. * * Release History * 1.00 - April 7th, 1998 - Ben Reser this was the Oracle7 version for Apache 1.2x * 2.00 - October 30th, 1999 - Ben Reser Oracle8 version for Apache 1.3x */ /* #define ORACLE_HOME "/usr/oracle8" */ /* * This should be set to the same thing as your ORACLE_HOME environment variable is * set to. It's commented out so that if people follow the installation instructions * above then everything should work for them. */ /* Max field value length limit; well above the limit of some browsers :-) */ #define MAX_FIELD_LEN (64) /* These are reasonable limits though certainly not the limits of Oracle. * Adjust these if you plan on using anything larger */ #define ORA8_FIELD_NAME_LEN (19) #define ORA8_TABLE_NAME_LEN (19) /* We only do the following two queries: * * - for the user/passwd combination * select PWDFIELD from PWDTABEL where USERFIELD='UID' * * - optionally for the user/group combination: * select GROUPFIELD from GROUPTABLE where USERFIELD='UID' and GROUPFIELD='GID' * * This leads to the following limits: (we are ignoring escaping a wee bit bit here * assuming not more than 24 escapes.) */ #define MAX_QUERY_LEN (32+24+MAX_FIELD_LEN*2+3*ORA8_FIELD_NAME_LEN+1*ORA8_TABLE_NAME_LEN) #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_protocol.h" #ifdef HAVE_CRYPT_H #include #endif #include #include #ifdef __STDCC__ #include #else #include #endif #include /* Oracle Params */ #define DEFER_PARSE 1 #define VERSION_8 2 typedef struct { char *auth_ora8_sid; char *auth_ora8_two_task; char *auth_ora8_uid_login; char *auth_ora8_pwd_login; char *auth_ora8_pwd_table; char *auth_ora8_grp_table; char *auth_ora8_pwd_field; char *auth_ora8_uname_field; char *auth_ora8_grp_field; int auth_ora8_nopasswd; int auth_ora8_authorative; int auth_ora8_encrypted; } ora8_auth_config_rec; void *create_ora8_auth_dir_config (pool *p, char *d) { ora8_auth_config_rec * sec= (ora8_auth_config_rec *) ap_pcalloc (p, sizeof(ora8_auth_config_rec)); /* just in case, to be nice... */ sec->auth_ora8_sid = NULL; sec->auth_ora8_two_task = NULL; sec->auth_ora8_pwd_table = NULL; sec->auth_ora8_grp_table = NULL; sec->auth_ora8_pwd_field = NULL; sec->auth_ora8_uname_field = NULL; sec->auth_ora8_grp_field = NULL; sec->auth_ora8_uid_login = NULL; sec->auth_ora8_pwd_login = NULL; sec->auth_ora8_authorative = 1; /* set some defaults, just in case... */ sec->auth_ora8_encrypted = 1; sec->auth_ora8_nopasswd = 0; return sec; } char *ora8_set_passwd_flag (cmd_parms *cmd, ora8_auth_config_rec *sec, int arg) { sec->auth_ora8_nopasswd=arg; return NULL; } char *ora8_set_authorative_flag (cmd_parms *cmd, ora8_auth_config_rec *sec, int arg) { sec->auth_ora8_authorative=arg; return NULL; } char *ora8_set_crypted_password_flag (cmd_parms *cmd, ora8_auth_config_rec *sec , int arg) { sec->auth_ora8_encrypted = arg; return NULL; } char *ora8_set_string_slot (cmd_parms *cmd, char *struct_ptr, char *arg) { int offset = (int)cmd->info; *(char **)(struct_ptr + offset) = ap_pstrdup (cmd->pool, arg); return NULL; } command_rec ora8_auth_cmds[] = { { "Auth_ORA8_SID", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_sid), OR_AUTHCFG, TAKE1, "Name of the Oracle8 database(SID) which contains the password (and possibly the group) tables. Use Auth_ORA8_two_task for Network(SQL*NET) connections" }, { "Auth_ORA8_TWO_TASK", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_two_task), OR_AUTHCFG, TAKE1, "SQL*NET V2 Name of the Oracle8 database which contains the password (and possibly the group) tables. See the tnsname.ora file to set the aliases for this." }, { "Auth_ORA8uid_login", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_uid_login), OR_AUTHCFG, TAKE1, "The User Name to Log Into Oracle8 As" }, { "Auth_ORA8pwd_login", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_pwd_login), OR_AUTHCFG, TAKE1, "The Password to Log Into Orace8 As" }, { "Auth_ORA8pwd_table", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_pwd_table), OR_AUTHCFG, TAKE1, "Name of the Oracle8 table containing the password/user-name combination" }, { "Auth_ORA8grp_table", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_grp_table), OR_AUTHCFG, TAKE1, "Name of the Oracle8 table containing the group-name/user-name combination; can be the same as the password-table." }, { "Auth_ORA8pwd_field", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_pwd_field), OR_AUTHCFG, TAKE1, "The name of the field in the Oracle8 password table" }, { "Auth_ORA8uid_field", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_uname_field), OR_AUTHCFG, TAKE1, "The name of the user-name field in the Oracle8 password (and possibly group) table(s)." }, { "Auth_ORA8grp_field", (void*)ora8_set_string_slot, (void*)XtOffsetOf(ora8_auth_config_rec, auth_ora8_grp_field), OR_AUTHCFG, TAKE1, "The name of the group field in the Oracle8 group table; must be set if you want to use groups." }, { "Auth_ORA8_nopasswd", (void*)ora8_set_passwd_flag, NULL, OR_AUTHCFG, FLAG, "Enable (on) or disable (off) empty password strings; in which case any user password is accepted." }, { "Auth_ORA8_Authorative", (void*)ora8_set_authorative_flag, NULL, OR_AUTHCFG, FLAG, "When 'on' the Oracle8 database is taken to be authorative and access control is not passed along to other db or access modules." }, { "Auth_ORA8_EncryptedPasswords", (void*)ora8_set_crypted_password_flag, NULL, OR_AUTHCFG, FLAG, "When 'on' the password in the password table are taken to be crypt()ed using your machines crypt() function." }, { NULL } }; module ora8_auth_module; /* boring little routine which escapes the ' and \ in the * SQL query. See the mSQL FAQ for more information :-) on * this very popular subject in the msql-mailing list. */ char *ora8_escape(char *out, char *in, char *ora8_errstr) { register int i=0,j=0; do { /* do we need to escape */ if ( (in[i] == '\'') || (in[i] == '\\')) { /* does this fit ? */ if (j >= (MAX_FIELD_LEN-1)) { sprintf(ora8_errstr,"Could not escape '%s', longer than %d",in,MAX_FIELD_LEN); return NULL; }; out[j++] = '\\'; /* insert that escaping slash for good measure */ }; /* Do things still fit ? */ if (j >= MAX_FIELD_LEN) return NULL; } while ( ( out[j++] = in[i++]) != '\0' ); return out; } /* get the password for uname=user, and copy it * into r. Assume that user is a string and stored * as such in the Oracle8 database */ char *do_ora8_query(request_rec *r, char *query, ora8_auth_config_rec *sec, int once , char *ora8_errstr) { Lda_Def lda; ub4 hda[HDA_SIZE/sizeof(ub4)]; Cda_Def cda1; text *result; ub2 resultl; sb2 result_ind; if (!(result=ap_palloc(r->pool,256))) { sprintf(ora8_errstr,"ORA8: Could not allocate memory for password"); return NULL; } memset(result,0,256); /* open if nessecary */ if (orlon(&lda,hda,(text*)sec->auth_ora8_uid_login,-1,(text*)sec->auth_ora8_pwd_login,-1,0)) { text msg[512]; oerhms(&lda, lda.rc, msg, (sword) sizeof msg); msg[strlen(msg) - 1] = 0; sprintf(ora8_errstr,"ORA8: Could not connect to Oracle8(%s) as %s : %s",(sec->auth_ora8_two_task) ? sec->auth_ora8_two_task : sec->auth_ora8_sid ,sec->auth_ora8_uid_login,msg); return NULL; } if (oopen(&cda1, &lda, (text *) 0, -1, -1, (text *) 0, -1)) { text msg[512]; oerhms(&lda, cda1.rc, msg, (sword) sizeof msg); msg[strlen(msg) - 1] = 0; sprintf(ora8_errstr,"ORA8: Could not get a cursor : %s",msg); return NULL; } /* run the query */ if (oparse(&cda1, query, (sb4) -1, DEFER_PARSE, (ub4) VERSION_8)) { text msg[512]; oerhms(&lda, cda1.rc, msg, (sword) sizeof msg); msg[strlen(msg) - 1] = 0; sprintf(ora8_errstr,"ORA8: Could not parse query : %s",msg); return NULL; } if (odefin(&cda1, 1, result, 256, (sword) STRING_TYPE, (sword) -1, (sb2 *) &result_ind, (text *) 0, -1, -1, (ub2 *) &resultl, (ub2 *) 0)) { text msg[512]; oerhms(&lda, cda1.rc, msg, (sword) sizeof msg); msg[strlen(msg) - 1] = 0; sprintf(ora8_errstr,"ORA8: Could not link query buffers : %s",msg); return NULL; } if (oexfet(&cda1, (ub4) 1, FALSE, FALSE)) { if (cda1.rc != NO_DATA_FOUND) { text msg[512]; oerhms(&lda, cda1.rc, msg, (sword) sizeof msg); msg[strlen(msg) - 1] = 0; sprintf(ora8_errstr,"ORA8: Query Execution Error : %s",msg); return NULL; } else { /* didn't find a matching user so return... the error message * will be picked up above */ return NULL; } } /* XXX: should complain if there are to many * matches. */ /* Check for NULL returns */ if (result_ind) { strcpy(result,"\0"); } oclose(&cda1); ologof(&lda); return result; } char *get_ora8_pw(request_rec *r, char *user, ora8_auth_config_rec *sec ,char *ora8_errstr) { char query[MAX_QUERY_LEN]; char esc_user[MAX_FIELD_LEN]; int err_esc = 0; /* do we have enough information to build a query */ if ((!sec->auth_ora8_sid) && (!sec->auth_ora8_two_task)) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8_SID or Auth_ORA8_TWO_TASK"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8_SID or Auth_ORA8_TWO_TASK"); } err_esc = 1; } if (!sec->auth_ora8_uid_login) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8uid_login"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8uid_login"); } err_esc = 1; } if (!sec->auth_ora8_pwd_login) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8pwd_login"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8pwd_login"); } err_esc = 1; } if (!sec->auth_ora8_pwd_table) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8pwd_table"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8pwd_table"); } err_esc = 1; } if (!sec->auth_ora8_uname_field) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8uid_field"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8uid_field"); } err_esc = 1; } if (!sec->auth_ora8_pwd_field) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8pwd_field"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8pwd_field"); } err_esc = 1; } if (err_esc) { char tempstr[MAX_STRING_LEN]; sprintf(tempstr,"ORA8: Missing parameters for password lookup: %s",ora8_errstr); strcpy(ora8_errstr,tempstr); return NULL; } if (!(ora8_escape(esc_user, user, ora8_errstr))) { sprintf(ora8_errstr, "ORA8: Could not cope/escape the '%s' user_id value; ",user); return NULL; }; sprintf(query,"select %s from %s where %s='%s'", sec->auth_ora8_pwd_field, sec->auth_ora8_pwd_table, sec->auth_ora8_uname_field, esc_user ); return do_ora8_query(r,query,sec,1,ora8_errstr); } char *get_ora8_grp(request_rec *r, char *group,char *user, ora8_auth_config_rec *sec, char *ora8_errstr) { char query[MAX_QUERY_LEN]; char esc_user[MAX_FIELD_LEN]; char esc_group[MAX_FIELD_LEN]; int err_esc = 0; /* do we have enough information to build a query */ if ((!sec->auth_ora8_sid) && (!sec->auth_ora8_two_task)) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8_SID or Auth_ORA8_TWO_TASK"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8_SID or Auth_ORA8_TWO_TASK"); } err_esc = 1; } if (!sec->auth_ora8_uid_login) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8uid_login"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8uid_login"); } err_esc = 1; } if (!sec->auth_ora8_pwd_login) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8pwd_login"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8pwd_login"); } err_esc = 1; } if ((!sec->auth_ora8_grp_table)) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8grp_table"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8grp_table"); } err_esc = 1; } if ((!sec->auth_ora8_uname_field)) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr,"Auth_ORA8uname_field"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8uname_field"); } err_esc = 1; } if ((!sec->auth_ora8_grp_field)) { if (err_esc) { sprintf(ora8_errstr,"%s, %s",ora8_errstr, "Auth_ORA8grp_field"); } else { sprintf(ora8_errstr,"%s","Auth_ORA8grp_field"); } err_esc = 1; } if (err_esc) { char tempstr[MAX_STRING_LEN]; sprintf(tempstr,"ORA8: Missing parameters for password lookup: %s",ora8_errstr); strcpy(ora8_errstr,tempstr); return NULL; } if (!(ora8_escape(esc_user, user,ora8_errstr))) { sprintf(ora8_errstr, "ORA8: Could not cope/escape the '%s' user_id value",user); return NULL; } if (!(ora8_escape(esc_group, group,ora8_errstr))) { sprintf(ora8_errstr, "ORA8: Could not cope/escape the '%s' group_id value",group); return NULL; } sprintf(query,"select %s from %s where %s='%s' and %s='%s'", sec->auth_ora8_grp_field, sec->auth_ora8_grp_table, sec->auth_ora8_uname_field,esc_user, sec->auth_ora8_grp_field, esc_group ); return do_ora8_query(r,query,sec,0,ora8_errstr); } int ora8_authenticate_basic_user (request_rec *r) { ora8_auth_config_rec *sec = (ora8_auth_config_rec *)ap_get_module_config (r->per_dir_config, &ora8_auth_module); char ora8_errstr[MAX_STRING_LEN]; conn_rec *c = r->connection; char *sent_pw, *real_pw; int res; char *ora_sid,*ora_home,*two_task; ora8_errstr[0]='\0'; if (sec->auth_ora8_sid) { ora_sid = (char *)ap_palloc(r->pool,15 + strlen(sec->auth_ora8_sid)); sprintf(ora_sid,"ORACLE_SID=%s",sec->auth_ora8_sid); putenv(ora_sid); } if (sec->auth_ora8_two_task) { two_task = (char *)ap_palloc(r->pool,15 + strlen(sec->auth_ora8_two_task)); sprintf(two_task,"TWO_TASK=%s",sec->auth_ora8_two_task); putenv(two_task); } ora_home = (char *)ap_palloc(r->pool,15 + strlen(ORACLE_HOME)); sprintf(ora_home,"ORACLE_HOME=%s",ORACLE_HOME); putenv(ora_home); if ((res = ap_get_basic_auth_pw (r, &sent_pw))) return res; /* if ORA8 *password* checking is configured in any way, i.e. then * handle it, if not decline and leave it to the next in line.. * We do not check on dbase, group, userid or host name, as it is * perfectly possible to only do group control with ORA8 and leave * user control to the next (dbm) guy in line. * We no longer check on the user field name; to avoid problems * with Backward VITEK. */ if (!sec->auth_ora8_pwd_table) return DECLINED; if(!(real_pw = get_ora8_pw(r, c->user, sec,ora8_errstr ))) { if ( ora8_errstr[0] ) { res = SERVER_ERROR; } else { if (sec->auth_ora8_authorative) { /* insist that the user is in the database */ sprintf(ora8_errstr,"ORA8: Password for user %s not found", c->user); ap_note_basic_auth_failure (r); res = AUTH_REQUIRED; } else { /* pass control on to the next authorization module. */ return DECLINED; }; /* if authorative */ }; /* if no error */ ap_log_reason (ora8_errstr, r->filename, r); return res; } /* allow no password, if the flag is set and the password * is empty. But be sure to log this. */ if ((sec->auth_ora8_nopasswd) && (!strlen(real_pw))) { /* sprintf(ora8_errstr,"ORA8: user %s: Empty/'any' password accepted",c->user); ap_log_reason (ora8_errstr, r->uri, r); */ return OK; }; /* if the flag is off however, keep that kind of stuff at * an arms length. */ if ((!strlen(real_pw)) || (!strlen(sent_pw))) { sprintf(ora8_errstr,"ORA8: user %s: Empty Password(s) Rejected",c->user); ap_log_reason (ora8_errstr, r->uri, r); ap_note_basic_auth_failure (r); return AUTH_REQUIRED; }; if(sec->auth_ora8_encrypted) { /* anyone know where the prototype for crypt is? * * PLEASE NOTE: * The crypt function (at least under FreeBSD 2.0.5) returns * a ptr to a *static* array (max 120 chars) and does *not* * modify the string pointed at by sent_pw ! */ sent_pw=(char *)crypt(sent_pw,real_pw); }; if (strcmp(real_pw,sent_pw)) { sprintf(ora8_errstr,"ORA8: user %s: password mismatch",c->user); ap_log_reason (ora8_errstr, r->uri, r); ap_note_basic_auth_failure (r); return AUTH_REQUIRED; } return OK; } /* Checking ID */ int ora8_check_auth (request_rec *r) { int user_result=DECLINED,group_result=DECLINED; char *ora_sid,*ora_home,*two_task; ora8_auth_config_rec *sec = (ora8_auth_config_rec *)ap_get_module_config (r->per_dir_config, &ora8_auth_module); char ora8_errstr[MAX_STRING_LEN]; char *user = r->connection->user; int m = r->method_number; array_header *reqs_arr = ap_requires (r); require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL; register int x; char *t, *w; ora8_errstr[0]='\0'; /* If we are not configured, ignore */ if (!sec->auth_ora8_pwd_table) return DECLINED; if (sec->auth_ora8_sid) { ora_sid = (char *)ap_palloc(r->pool,15 + strlen(sec->auth_ora8_sid)); sprintf(ora_sid,"ORACLE_SID=%s",sec->auth_ora8_sid); putenv(ora_sid); } if (sec->auth_ora8_two_task) { two_task = (char *)ap_palloc(r->pool,15 + strlen(sec->auth_ora8_two_task)); sprintf(two_task,"TWO_TASK=%s",sec->auth_ora8_two_task); putenv(two_task); } ora_home = (char *)ap_palloc(r->pool,15 + strlen(ORACLE_HOME)); sprintf(ora_home,"ORACLE_HOME=%s",ORACLE_HOME); putenv(ora_home); if (!reqs_arr) { if (sec->auth_ora8_authorative) { sprintf(ora8_errstr,"user %s denied, no access rules specified (ORA8-Authorative) ",user); ap_log_reason (ora8_errstr, r->uri, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; }; return DECLINED; }; for(x=0; (x < reqs_arr->nelts) ; x++) { if (! (reqs[x].method_mask & (1 << m))) continue; t = reqs[x].requirement; w = ap_getword(r->pool, (void*)&t, ' '); if ((user_result != OK) && (!strcmp(w,"user"))) { user_result=AUTH_REQUIRED; while(t[0]) { w = ap_getword_conf (r->pool,(void*) &t); if (!strcmp(user,w)) { user_result= OK; break; }; } if ((sec->auth_ora8_authorative) && ( user_result != OK)) { sprintf(ora8_errstr,"User %s not found (ORA8-Authorative)",user); ap_log_reason (ora8_errstr, r->uri, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; }; } if ( (group_result != OK) && (!strcmp(w,"group")) && (sec->auth_ora8_grp_table) && (sec->auth_ora8_grp_field) ) { /* look up the membership for each of the groups in the table */ group_result=AUTH_REQUIRED; while ( (t[0]) && (group_result != OK) && (!ora8_errstr[0]) ) { if (get_ora8_grp(r,ap_getword(r->pool,(void*) &t, ' '),user,sec,ora8_errstr)) { group_result= OK; break; }; }; if (ora8_errstr[0]) { ap_log_reason (ora8_errstr, r->filename, r); return SERVER_ERROR; }; if ( (sec->auth_ora8_authorative) && (group_result != OK) ) { sprintf(ora8_errstr,"user %s not in right groups (ORA8-Authorative) ",user); ap_log_reason (ora8_errstr, r->uri, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; }; }; if(!strcmp(w,"valid-user")) { user_result= OK; }; } /* Get serious if we are authorative, previous * returns are only if ORA8 yielded a correct result. * This really is not needed. */ if (((group_result == AUTH_REQUIRED) || (user_result == AUTH_REQUIRED)) && (sec->auth_ora8_authorative) ) { sprintf(ora8_errstr,"ORA8-Authorative: Access denied on %s %s rule(s) ", (group_result == AUTH_REQUIRED) ? "USER" : "", (user_result == AUTH_REQUIRED) ? "GROUP" : "" ); ap_log_reason (ora8_errstr, r->uri, r); return AUTH_REQUIRED; }; if ( (user_result == OK) || (group_result == OK)) return OK; return DECLINED; } module ora8_auth_module = { STANDARD_MODULE_STUFF, NULL, /* initializer */ create_ora8_auth_dir_config, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ ora8_auth_cmds, /* command table */ NULL, /* handlers */ NULL, /* filename translation */ ora8_authenticate_basic_user,/* check_user_id */ ora8_check_auth, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* pre-run fixups */ NULL /* logger */ };