3proxy/src/plugins/PamAuth/pamauth.c

144 lines
3.3 KiB
C

/* plugin for 3proxy with PAM auth only for *NIX (linux,*bsd)
Kirill Lopuchov <lopuchov@mail.ru>
Compile with: gcc -shared -o pamauth.so pamauth.c -lpam -DNOODBC
*/
#include "../../structures.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <security/pam_appl.h>
pthread_mutex_t pam_mutex;
static int already_loaded = 0;
static struct auth pamauth;
#ifdef USERCASE
static int usercaselow = 0;
#endif
static unsigned char *service=NULL;
static struct pluginlink * pl;
static char *password = NULL;
static int password_conversation ( int num_msg, const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
{
if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
{
return PAM_CONV_ERR;
}
if (!appdata_ptr) appdata_ptr = password;
if (!appdata_ptr)
{
return PAM_CONV_ERR;
}
*resp = calloc (num_msg, sizeof (struct pam_response));
if (!*resp)
{
return PAM_CONV_ERR;
}
(*resp)[0].resp = strdup ((char *) appdata_ptr);
(*resp)[0].resp_retcode = 0;
return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
}
#ifdef USERCASE
static void lower (char *string)
{
int length, i;
length = strlen(string);
for (i=0; i<length; i++)
{
string[i] = tolower(string[i]);
}
}
#endif
/* --------------------------------------------------------------------------*/
static int pamfunc(struct clientparam *param)
{
pam_handle_t *pamh = NULL;
int retval;
int rc=0;
struct pam_conv conv = {
&password_conversation,
NULL };
/* test proxy user auth ------------------------*/
if(!param->username || !param->password) return 4;
/*if(strlen(param->password)==0) return 4;*/
#ifdef USERCASE
if (usercaselow > 0)
{ lower(param->username); }
#endif
/*start process auth */
conv.appdata_ptr = (char *) param->password;
pthread_mutex_lock(&pam_mutex);
if (!pamh)
{
retval = pam_start ((char *)service, "3proxy@" , &conv, &pamh);
}
if (retval == PAM_SUCCESS)
retval = pam_set_item (pamh, PAM_USER, param->username);
/*fprintf(stderr,"pam_set_item1 rc=%d\n",retval);*/
if (retval == PAM_SUCCESS)
retval = pam_set_item (pamh, PAM_CONV, &conv);
/*fprintf(stderr,"pam_set_item2 rc=%d\n",retval); */
if (retval == PAM_SUCCESS)
retval = pam_authenticate (pamh, 0);
/*fprintf(stderr,"pam_authenticate rc=%d\n",retval);*/
if (retval == PAM_SUCCESS) { /*auth OK*/ rc=0; }
else { /*auth ERR*/ rc=5; }
if (pamh)
retval = pam_end (pamh, retval);
if (retval != PAM_SUCCESS)
{ pamh = NULL; }
pthread_mutex_unlock(&pam_mutex);
return rc;
}
/*------------------------------- MAIN --------------------------------------
start plugin init */
int start(struct pluginlink * pluginlink, int argc, unsigned char** argv)
{
if(argc < 2) return 1;
pl = pluginlink;
if(service) pl->myfree(service);
service=(unsigned char *)pl->mystrdup((char *)argv[1]);
if (already_loaded) { return (0); }
already_loaded = 1;
pthread_mutex_init(&pam_mutex, NULL);
pamauth.authenticate = pamfunc;
pamauth.authorize = pluginlink->checkACL;
pamauth.desc = "pam";
pamauth.next = pluginlink->authfuncs->next;
pluginlink->authfuncs->next = &pamauth;
return 0;
}