/******************************************************************** * 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 #ifndef VMS_SERVER # include #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 .