/********************************************************************
* wilkinson
* 3.13VMS
* 1995/09/25 14:22
* gopher_root1:[gopher.g2.vms2_13.gopherd]AUTH.c,v
*
* Paul Lindner, University of Minnesota DCS.
*
* Copyright 1991, 92, 93, 94 by the Regents of the University of Minnesota
* see the file "Copyright" in the distribution for conditions of use.
*********************************************************************
* MODULE: AUTH.c
* Routines to verify authentication
*********************************************************************
* Revision History:
* AUTH.c,v
* Revision 3.13VMS 1995/09/25 14:23 wilkinson
* Consolodate VMS/Unix source code for server as well as client
*
* Revision 3.13 1995/02/06 21:25:13 lindner
* Better stdio include
*
* Revision 3.12 1995/02/02 17:13:52 lindner
* Fix memory leaks
*
* Revision 3.11 1994/12/31 07:45:22 lindner
* Remove Item is protected note
*
* Revision 3.10 1994/12/15 17:32:21 lindner
* Fix for A/UX and undefined FILE*, AIX uses compat fgetpwent routines now
*
* Revision 3.9 1994/12/12 18:19:07 lindner
* Fix aix hack
*
* Revision 3.8 1994/12/12 17:41:08 lindner
* Hack around AIX
*
* Revision 3.7 1994/12/12 16:58:47 lindner
* Use fgetpwent() instead of setpwfile()
*
* Revision 3.6 1994/12/10 06:12:13 lindner
* Add support for a custom passwd file just for the gopher server
*
* Revision 3.5 1994/10/13 05:17:46 lindner
* Compiler complaint fixes
*
* Revision 3.4 1994/07/22 22:27:20 lindner
* NO_AUTHENTICATION mods
*
* Revision 3.3 1994/07/21 15:45:34 lindner
* Fix for systems without unistd.h
*
* Revision 3.2 1994/07/03 21:18:11 lindner
* Add initgroup() call
*
* Revision 3.1 1994/06/29 05:34:19 lindner
* New authentication routines
*
*
*********************************************************************/
#ifndef NO_AUTHENTICATION
#include "AUTH.h"
#include "compatible.h"
#include "Malloc.h"
#include "fileio.h" /* For running scripts */
#include "String.h" /* strchr and friends */
#include "Debug.h"
#include <stdio.h>
#ifndef VMS_SERVER
# include <pwd.h>
#endif
AUTH*
AUTHnew()
{
AUTH* temp;
temp = (AUTH*) malloc(sizeof(AUTH));
temp->type = AUTH_UNINITED;
temp->name = STRnew();
temp->scriptname = STRnew();
temp->authfcn = NULL;
temp->authfcnask = NULL;
return(temp);
}
void
AUTHdestroy(auth)
AUTH *auth;
{
STRdestroy(auth->name);
STRdestroy(auth->scriptname);
free(auth);
}
void
AUTHinit(auth)
AUTH *auth;
{
STRinit(auth->name);
STRinit(auth->scriptname);
auth->authfcn = NULL;
auth->authfcnask = NULL;
auth->type = AUTH_UNINITED;
}
AUTH*
AUTHcpy(dest, orig)
AUTH *dest, *orig;
{
STRcpy(dest->name, orig->name);
STRcpy(dest->scriptname, orig->scriptname);
dest->authfcn = orig->authfcn;
dest->authfcnask = orig->authfcnask;
dest->type = orig->type;
return(dest);
}
/*
* A very generic ASK block
*/
char**
AUTHgenericAsk(directory, defuser, defpw)
char *directory;
char *defuser;
char *defpw;
{
static char **Askstorage = NULL;
Debug("Trying to do the generic ask block for %s\n", directory);
if (Askstorage == NULL) {
Askstorage = (char**)malloc(sizeof(char*)*5);
Askstorage[0] = (char*) malloc(sizeof(char) * 80);
Askstorage[1] = (char*) malloc(sizeof(char) * 80);
Askstorage[2] = (char*) malloc(sizeof(char) * 80);
Askstorage[3] = NULL;
}
if (defuser == NULL)
defuser = "";
if (defpw == NULL)
defpw = "";
/* if (directory == NULL)
strcpy(Askstorage[0], "Note: This item is protected");
else
sprintf(Askstorage[0], "Note: The item %s is protected", directory);
*/
sprintf(Askstorage[1], "Ask: Your User Name:\t%s", defuser);
sprintf(Askstorage[2], "AskP: Your Password:\t%s", defpw);
return(Askstorage);
}
/*
* Check to see if 'password' is the users password.
*/
static AUTHresult
AUTHunix_checkuser(pw, password)
#ifndef VMS_SERVER
struct passwd *pw;
#else
void *pw;
#endif
char *password;
{
#ifndef VMS_SERVER
char salt[3];
char *encodedpw;
strncpy(salt, pw->pw_passwd, 2);
encodedpw = (char*) crypt(password, salt);
if (strcmp(encodedpw, pw->pw_passwd) == 0) {
if (getuid() == 0) {
initgroups(pw->pw_name, pw->pw_gid);
setuid(pw->pw_uid);
setgid(pw->pw_gid);
}
return(AUTHRES_OK);
}
return(AUTHRES_BADPW);
#else
return(AUTHRES_SYSERR);
#endif /*vms*/
}
/*
* Use a password file in the etc/passwd in the gopher-data directory
* to authenticate users.
*/
AUTHresult
AUTHunixfile(auth, username, password, hostname, hostip)
AUTH *auth;
char *username, *password, *hostname, *hostip;
{
#if !defined(VMS_SERVER)
FILE *ourpasswd;
struct passwd *pw;
Debug("Trying to authenticate %s\n", username);
/*** This may or may not work.. (doesn't on sunos 4.1.3) ***/
ourpasswd = fopen("etc/passwd", "r");
if (ourpasswd == NULL) {
Debugmsg("Couldn't open etc/passwd\n");
return(AUTHRES_SYSERR);
}
if (fgetpwent(ourpasswd) == NULL) {
Debugmsg("fgetpwent failed...");
return(AUTHRES_SYSERR);
}
fseek(ourpasswd, 0L,SEEK_SET);
/** Mimic getpwnam, sigh why isn't setpwfile() everywhere....**/
while ((pw = fgetpwent(ourpasswd)) != NULL) {
if (strcmp(pw->pw_name, username) == 0)
return(AUTHunix_checkuser(pw, password));
}
return(AUTHRES_NOUSER);
#else
return(AUTHRES_SYSERR);
#endif /*vms*/
}
/*
* Do the unix style /etc/passwd authentication...
*/
AUTHresult
AUTHunix(auth, username, password, hostname, hostip)
AUTH *auth;
char *username, *password, *hostname, *hostip;
{
#ifndef VMS_SERVER
struct passwd *pw;
pw = getpwnam(username);
if (pw == NULL)
return(AUTHRES_NOUSER);
return(AUTHunix_checkuser(pw, password));
#else
return(AUTHRES_SYSERR);
#endif /*VMS*/
}
AUTHresult
AUTHvalidate(auth, username, password, hostname, hostip)
AUTH *auth;
char *username, *password, *hostname, *hostip;
{
int result;
char *envstr;
switch (AUTHgetType(auth)) {
case AUTH_SCRIPT:
/*
* Need to set environment variables here...
* note envstr must be malloced.
*/
envstr = (char*) malloc(sizeof(char) * (16+strlen(username)));
sprintf(envstr, "GOPHER_USER=%s", username);
putenv(envstr);
envstr = (char*) malloc(sizeof(char) * (16+strlen(password)));
sprintf(envstr, "GOPHER_PW=%s", password);
putenv(envstr);
envstr = (char*) malloc(sizeof(char) * (16+strlen(hostname)));
sprintf(envstr, "GOPHER_HOST=%s", hostname);
putenv(envstr);
envstr = (char*) malloc(sizeof(char) * (16+strlen(hostip)));
sprintf(envstr, "GOPHER_IP=%s", hostip);
putenv(envstr);
result = FIOsystem(AUTHgetScriptName(auth));
switch (result) {
case 0:
return(AUTHRES_OK);
case 1:
return(AUTHRES_BADPW);
case 2:
return(AUTHRES_EXPIRED);
case 3:
return(AUTHRES_NOUSER);
default:
return(AUTHRES_BADPW);
}
break;
case AUTH_INTERNAL:
return(auth->authfcn(auth, username, password, hostname, hostip));
case AUTH_UNINITED:
return(AUTHRES_BADPW);
}
return(AUTHRES_OK);
}
/*************************************************************************
* AUTH array routines (AUTHA)
*/
AUTHarray*
AUTHAnew(size)
int size;
{
AUTHarray *aa;
AUTH *auth;
aa = DAnew((size),AUTHnew,AUTHinit,AUTHdestroy,AUTHcpy);
auth = AUTHnew();
if (auth == NULL)
return(NULL);
/** Always supply some defaults... **/
AUTHsetType(auth, AUTH_INTERNAL);
AUTHsetName(auth, "unix");
AUTHsetFcn(auth, AUTHunix);
AUTHsetAskFcn(auth, AUTHgenericAsk);
AUTHApush(aa, auth);
AUTHsetType(auth, AUTH_INTERNAL);
AUTHsetName(auth, "unixfile");
AUTHsetFcn(auth, AUTHunixfile);
AUTHsetAskFcn(auth, AUTHgenericAsk);
AUTHApush(aa, auth);
AUTHdestroy(auth);
return(aa);
}
/*
* Process a gopherd.conf style line and add it to the array
* really only for scripts.
*/
boolean
AUTHAprocessLine(autharr, inputline)
AUTHarray *autharr;
char *inputline;
{
AUTH *auth;
char *cp;
auth = AUTHnew();
if (auth == NULL)
return(FALSE);
cp = strchr(inputline, ' ');
*cp = '\0';
cp++;
AUTHsetType(auth, AUTH_SCRIPT);
AUTHsetScriptName(auth, cp);
AUTHsetName(auth,inputline);
AUTHsetAskFcn(auth, AUTHgenericAsk);
AUTHApush(autharr, auth);
AUTHdestroy(auth);
return(TRUE);
}
/*
* Find the authentication method, and pass the information to the
* routine that handles it.
*/
AUTHresult
AUTHAvalidate(autha, type, username, password, hostname, hostip)
AUTHarray *autha;
char *type;
char *username, *password, *hostname, *hostip;
{
int i;
AUTH *auth;
if (type == NULL)
return(AUTHRES_BADPW);
for (i=0; i < AUTHAgetTop(autha); i++) {
auth = AUTHAgetEntry(autha, i);
if (strcasecmp(type, AUTHgetName(auth)) == 0) {
return(AUTHvalidate(auth,username,password,hostname,hostip));
}
}
/** Shouldn't get to here.. **/
return(AUTHRES_BADPW);
}
/*
* Find an AUTH item in the autha array
*/
AUTH*
AUTHAlocate(autha, type)
AUTHarray *autha;
char *type;
{
int i;
AUTH *auth;
if (type == NULL)
return(NULL);
for (i=0; i < AUTHAgetTop(autha); i++) {
auth = AUTHAgetEntry(autha, i);
if (strcasecmp(type, AUTHgetName(auth)) == 0) {
return(auth);
}
}
/** Shouldn't get to here.. **/
return(NULL);
}
/*********************************************************************
* AUTHITEMS array
*/
#include "Regex.h"
AUTHITEMS *
AUTHITEMSnew(size)
int size;
{
AUTHITEMS *ai;
ai = (AUTHITEMS*) malloc(sizeof(AUTHITEMS));
if (ai != NULL) {
ai->regexps = STAnew(size);
ai->authtypes = STAnew(size);
}
return(ai);
}
void
AUTHITEMSdestroy(ai)
AUTHITEMS *ai;
{
if (ai == NULL)
return;
STAdestroy(ai->regexps);
STAdestroy(ai->authtypes);
}
void
AUTHITEMSpush(ai, regexp, authtype)
AUTHITEMS *ai;
char *regexp;
char *authtype;
{
String *str;
if (ai == NULL)
return;
str = STRnew();
if (str == NULL)
return;
STRset(str, regexp);
STApush(ai->regexps, str);
STRset(str, authtype);
STApush(ai->authtypes, str);
STRdestroy(str);
}
/*
* Find a match for the item in the regular expressions
*
* returns NULL if no match found..
*/
char *
AUTHITEMSfindType(ai, fname)
AUTHITEMS *ai;
char *fname;
{
int i;
char *rexp;
if (ai == NULL)
return(NULL);
for (i=0; i < STAgetTop(ai->regexps); i++) {
rexp = STAgetText(ai->regexps, i);
if (re_comp(rexp))
return(NULL);
if (re_exec(fname) == 1) {
/* We have a match */
return(STAgetText(ai->authtypes, i));
}
}
return(NULL); /* No match found.. */
}
/*
* Find the auth item required..
*/
AUTH*
AUTHITEMSfindAUTH(ai, aa, fname)
AUTHITEMS *ai;
AUTHarray *aa;
char *fname;
{
int i;
char *rexp;
if (ai == NULL)
return(NULL);
for (i=0; i < STAgetTop(ai->regexps); i++) {
rexp = STAgetText(ai->regexps, i);
Debug("Trying %s\n", rexp);
if (re_comp(rexp))
return(NULL);
if (re_exec(fname) == 1) {
/* We have a match */
return(AUTHAlocate(aa, STAgetText(ai->authtypes, i)));
}
}
return(NULL); /* No match found.. */
}
/*
* Process a gopherd.conf style line and put it into the arrays.
*/
boolean
AUTHITEMSprocessLine(ai, inputline)
AUTHITEMS *ai;
char *inputline;
{
char *cp;
cp = strchr(inputline, ' ');
if (cp == NULL)
return(FALSE);
*cp = '\0';
AUTHITEMSpush(ai, cp+1, inputline);
return(TRUE);
}
#endif