/* * ns-pam.c. A pam based basic authentication api for Netscape Enterprise SuiteSpot 3.5.1. * Author: Max Liccardo * */ /* ---------------------------------------------------- * * Parameters: * PAMService = pam service name. HAve a look in /etc/pam.conf * At the beginning of obj.conf: * Init fn=load-modules shlib=/path_of_your_web_server/config/ns-pam.so funcs=pamauth * Inside an object in obj.conf: * AuthTrans fn=pam-auth PAMService=www auth-type=basic * PathCheck fn=require-auth realm="REALM" auth-type=basic * */ /* ---------------------------------------------------------------- * * The following three are standard headers for SAFs. They're used to * get the data structures and prototypes needed to declare and use SAFs. */ #include #ifdef XP_WIN32 #define NSAPI_PUBLIC __declspec(dllexport) #else /* !XP_WIN32 */ #define NSAPI_PUBLIC #endif /* !XP_WIN32 */ #include #include #define DEFAULT_SERVICE "www" /* From Apache source code */ /* $Id: ns-pam.c,v 2.1 1999/12/03 15:20:11 max Exp max $ * ==================================================================== * 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 . * */ /* aaaack but it's fast and const should make it shared text page. */ static const int pr2six[256]={ 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,62,64,64,64,63,52,53,54,55,56,57,58,59,60,61,64,64, 64,64,64,64,64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,28, 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, 49,50,51,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64 }; /* modified Apache code */ int uudecode(char *bufcoded,char *bufplain) { /* bufout is created. Remember to free it! */ int nbytesdecoded; unsigned char *bufin; unsigned char *bufout; int nprbytes; /* Strip leading whitespace. */ while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++; /* Figure out how many characters are in the input buffer. * Allocate this many from the per-transaction pool for the result. */ bufin = (unsigned char *)bufcoded; while(pr2six[*(bufin++)] <= 63) ; nprbytes = (char *)bufin - bufcoded - 1; nbytesdecoded = ((nprbytes+3)/4) * 3; bufout = (unsigned char *)bufplain; bufin = (unsigned char *)bufcoded; while (nprbytes > 0) { *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); bufin += 4; nprbytes -= 4; } if(nprbytes & 03) { if(pr2six[bufin[-2]] > 63) nbytesdecoded -= 2; else nbytesdecoded -= 1; } bufplain[nbytesdecoded] = '\0'; return nbytesdecoded; } typedef struct{ char *user; char *pw; }WebVar; static int fconv(int num_msg, const struct pam_message **msg, struct pam_response **resp,void *appdata_ptr) { int i; WebVar *lpWebVar; if(appdata_ptr) { lpWebVar = appdata_ptr; } else{ return(PAM_CONV_ERR); } *resp = (struct pam_response *) calloc(num_msg,sizeof(struct pam_response)); for(i=0;imsg_style) { case PAM_PROMPT_ECHO_OFF: resp[i]->resp = strdup(lpWebVar->pw); break; case PAM_PROMPT_ECHO_ON: resp[i]->resp = strdup(lpWebVar->user); break; default: break; } resp[i]->resp_retcode = 0; } return(PAM_SUCCESS); } NSAPI_PUBLIC int pamauth(pblock *param, Session *sn, Request *rq) { int ret=REQ_NOACTION; int liDebug = 0; int liPAMretval; char *lpszPAMService; char *user = NULL; char *pw=NULL; pam_handle_t *pamh=NULL; struct pam_conv s_conv; WebVar s_WebVar; char *auth; char *auth_dec = NULL,*t; if(pblock_findval("debug",param)) { liDebug = 1; } if((lpszPAMService = pblock_findval("PAMService",param)) == NULL) { lpszPAMService = DEFAULT_SERVICE; } if(liDebug) log_error(LOG_INFORM,"pamauth",sn,rq," using %s as service",lpszPAMService); if((auth = pblock_findval("authorization",rq->headers)) != NULL) { /* * We are in basic authentication. */ /* Get user:pw */ if((t=strstr(auth,"Basic "))!=NULL) { if(t!=auth) auth=t; /* skip spaces */ /* auth_dec holds the decoded authentication info */ auth_dec = (char *) MALLOC( sizeof(char *)*sizeof(auth) ); uudecode(auth+6,auth_dec); if((strlen(auth_dec) < 1) || (auth_dec[0] == ':')) { FREE(auth_dec); FREE(auth); log_error(LOG_SECURITY,"pamauth",sn,rq," Malformed auth"); return (REQ_ABORTED); } if((t=strchr(auth_dec,':'))!=NULL) { t[0]='\0'; pw=t+1; } else pw=auth_dec+strlen(auth_dec); user=auth_dec; } else{ FREE(auth); log_error(LOG_SECURITY,"pamauth",sn,rq,"Non Basic autentication"); return (REQ_ABORTED); } } memset(&s_WebVar,'\0',sizeof(s_WebVar)); s_WebVar.user = user; s_WebVar.pw = pw; s_conv.conv = fconv; s_conv.appdata_ptr = (void *) &s_WebVar; /* * start PAM. */ liPAMretval = pam_start(lpszPAMService,user, &s_conv, &pamh); if (liPAMretval == PAM_SUCCESS) liPAMretval = pam_set_item(pamh,PAM_RHOST,pblock_findval("ip",sn->client)); if (liPAMretval == PAM_SUCCESS) liPAMretval = pam_authenticate(pamh,PAM_DISALLOW_NULL_AUTHTOK); /* is user really user? */ if (liPAMretval == PAM_SUCCESS) { param_free(pblock_remove("auth-type", rq->vars)); pblock_nvinsert("auth-type", "basic", rq->vars); param_free(pblock_remove("auth-user", rq->vars)); if(!user) pam_get_item(pamh,PAM_USER,&user); pblock_nvinsert("auth-user",user, rq->vars); if(liDebug) log_error(LOG_INFORM,"pamauth",sn,rq,"user %s authenticated",user); pam_setcred(pamh,PAM_DISALLOW_NULL_AUTHTOK); ret = REQ_PROCEED; } else{ ret = REQ_NOACTION; if(user) log_error(LOG_SECURITY, "pamauth",sn,rq, "%s. user %s not authenticated by service %s", pam_strerror(pamh,liPAMretval), user, lpszPAMService); } pam_end(pamh,liPAMretval); /* close Linux-PAM */ FREE(auth); FREE(auth_dec); return (ret); } /* E.O.F. $Header: /home/max/src/ns-api/pam-auth/RCS/ns-pam.c,v 2.1 1999/12/03 15:20:11 max Exp max $ */