major source structure and module name changes

This commit is contained in:
soochoi
2006-06-07 16:34:19 +00:00
parent 5c75241b4b
commit 1fa6f07e83
651 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
#######################################################################
#
# Copyright (C) 2006 Novell, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: Juan Carlos Luciani <jluciani@novell.com>
#
#######################################################################
SUBDIRS = $(TARGET_OS)
DIST_SUBDIRS = linux
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@@ -0,0 +1,80 @@
/***********************************************************************
*
* README for pam_casaauthtok
*
***********************************************************************/
INTRODUCTION
pam_casaauthtok is a PAM authentication module which can be configured
to validate credentials consisting of CASA Authentication Tokens.
CONFIGURATION
To use pam_casaauthtok as a PAM authentication module for your service,
add the following line to the service's PAM configuration file:
auth required pam_casaauthtok.so
pam_casaauthtok supports the following input parameters:
U - This parameter tells pam_casaauthtok that it must verify that
the username is set to "CasaPrincipal". If the parameter is not
specified then pam_casaauthtok does not check the username.
CLIENT PROGRAMMING NOTES
Clients must specify the same service name when requesting Authentication
Tokens from the CASA Client as the service name specified by the server
when opening a PAM handle.
SERVER PROGRAMMING NOTES
Server applications validating credentials containing CASA Authentication
tokens can obtain the following information about the authenticated identity:
username - This is obtained by querying PAM using the pam_get_item() call with
the item type set to PAM_USER. This can also be obtained by querying PAM
using the pam_getenv() call with the variable name set to "IdentityId". The
username is the user's unique id within the authentication realm. When the
authentication realm is an LDAP database, the username consists of the user's fdn.
Note that PAM applications using pam_casaauthtok need to set username to
"CasaPrincipal" when opening a PAM handle and then the variable is updated by
pam_casaauthtok during the authentication process with the identity information
of the authenticated entity.
Name of the source of identity data (Authentication Realm) - This is obtained
by querying PAM using the pam_getenv() call with the variable name set to
"IdentityDataSourceName".
URL to the source of identity data - This is obtained
by querying PAM using the pam_getenv() call with the variable name set to
"IdentityDataSourceUrl".
Attributes of the authenticated identity - The attributes are set as environment
variables associated with the PAM handle. The environment variable names match
the names of the attributes. The attributes associated with the authenticated
identity and expressed as environment variables are configured at the time that
the service is enabled for CASA Authentication.
EXAMPLE SERVER APPLICATION
See test/test.c for an example application using PAM to authenticate credentials
consisting of CASA Authentication Tokens.
SECURITY CONSIDERATIONS
CASA Authenticatication Tokens when compromised can be used to either impersonate
a user or to obtain identity information about the user. Because of this it is
important that the tokens be secured by applications making use of them. It is
recommended that the tokens be transmitted using SSL.

View File

@@ -0,0 +1,13 @@
/***********************************************************************
*
* TODO for pam_casaauthtok
*
***********************************************************************/
INTRODUCTION
This file contains a list of the items still outstanding for pam_casaauthtok.
OUTSTANDING ITEMS
None.

View File

@@ -0,0 +1,110 @@
#######################################################################
#
# Copyright (C) 2006 Novell, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: Juan Carlos Luciani <jluciani@novell.com>
#
#######################################################################
if DEBUG
TARGET_CFG = Debug
CFLAGS += -v -w
else
TARGET_CFG = Release
endif
SUBDIRS =
DIST_SUBDIRS =
CASAROOT = ../../../..
CASALIBDIR = $(CASAROOT)/$(LIB)
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
PLATFORMINDEPENDENTSOURCEDIR = ..
PLATFORMDEPENDENTSOURCEDIR = .
MODULE_NAME = pam_casaauthtok
MODULE_EXT = so
CFILES = ../pam_authtoken.c
CSFILES_CSC :=
INCLUDES = -I. -I$(CASAROOT)/include
RESOURCES =
DEFINES = -Wno-format-extra-args -fno-strict-aliasing
CFLAGS += $(INCLUDES) $(DEFINES)
LIBS = -lpthread -lpam -lcasa_s_authtoken
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(CASALIBDIR)/$(TARGET_CFG) -Xlinker -rpath -Xlinker /opt/novell/CASA/lib
OBJDIR = ./$(TARGET_CFG)/$(LIB)
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o))
EXTRA_DIST = $(CFILES)
CUR_DIR := $(shell pwd)
all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
#
# Pattern based rules.
#
vpath %.c $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR)
vpath %.cpp $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR)
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: %.cpp
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS)
@echo [======== Linking $@ ========]
$(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(CASALIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(CASALIBDIR) ] || mkdir -p $(CASALIBDIR)
[ -d $(CASALIBDIR)/$(TARGET_CFG) ] || mkdir -p $(CASALIBDIR)/$(TARGET_CFG)
install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
$(mkinstalldirs) $(DESTDIR)$(libdir)
$(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/
uninstall-local:
cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
rmdir $(DESTDIR)$(libdir)
#installcheck-local: install
# $(mkinstalldirs) $(DESTDIR)$(libdir)
# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir)
# cd $(DESTDIR)$(libdir); $(MONO)
clean-local:
#cd $(TARGET_CFG); rm -rf *.dbg *.exe *.dll *.o *.so; cd ..; rmdir $(OBJDIR)
rm -rf $(TARGET_CFG)
distclean-local:
maintainer-clean-local:
rm -f Makefile.in

View File

@@ -0,0 +1,649 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
#define _GNU_SOURCE
#include <stdarg.h>
#include <syslog.h>
#include <stdbool.h>
#ifndef LINUX
#include <security/pam_appl.h>
#endif
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_PASSWORD
#define PAM_SM_SESSION
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <casa_s_authtoken.h>
//
// Environment variables set by module
//
static char CasaIdentityIdEnvVar[] = "IdentityId= ";
static char CasaIdentitySourceNameEnvVar[] = "IdentityDataSourceName= ";
static char CasaIdentitySourceUrlEnvVar[] = "IdentityDataSourceUrl= ";
/* ************************************************************************
* LogError()
*
* Logs error to syslog.
*
* L2
* ************************************************************************/
static void
LogError(char *pFormatStr, ... )
{
va_list args;
openlog("pam_casaauthtok", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER);
va_start(args, pFormatStr);
vsyslog(LOG_USER | LOG_INFO, pFormatStr, args);
va_end(args);
closelog();
}
/* ************************************************************************
* pam_sm_authenticate()
*
* Service provider implementation for pam_authenticate().
*
* This is a PAM authentication management function.
*
* We are going to validate the credentials using the CASA Authentication
* Token Credential APIs.
*
* L2
* ************************************************************************/
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int retStatus = PAM_SUCCESS;
bool performUsernameCheck = false;
int i;
char *pServicename = NULL;
char *pAuthToken = NULL;
// Determine if we are supposed to perform the username check
// based on the arguments specified.
for (i = 0; i < argc; i++)
{
if (*(argv[i]) == 'U')
{
// The arguments indicate that we should check the username
performUsernameCheck = true;
// No need to keep going through the arguments
break;
}
}
// Get the servicename.
if (pam_get_item(pamh, PAM_SERVICE, (void*) &pServicename) == PAM_SUCCESS
&& pServicename != NULL)
{
// We got the service name, now check if it is necessary to perform
// the username check.
if (performUsernameCheck)
{
char *pUsername;
struct pam_response *responses = NULL;
// Obtain the username so that it can be checked.
// .
// Note that we are not calling pam_get_user() because we
// assume that the service has set it before calling PAM_Authenticate.
if (pam_get_item(pamh, PAM_USER, (void*) &pUsername) == PAM_SUCCESS
&& pUsername != NULL)
{
// Check if the username matches the name that we are expecting
if (strcmp(pUsername, "CasaPrincipal") != 0)
{
LogError("Un-expected username, %s", pUsername);
retStatus = PAM_USER_UNKNOWN;
}
}
else
{
struct pam_conv *pConv;
// The username has not been set, try to obtain it from the
// application through the use of the conversation function.
if (pam_get_item(pamh, PAM_CONV, (void*) &pConv) == PAM_SUCCESS)
{
struct pam_message msg;
struct pam_message *messages = &msg;
// Obtained the conversation structure, now query the conversation
// function for the username.
msg.msg_style = PAM_PROMPT_ECHO_ON;
if (pConv->conv(1,
(const struct pam_message **) &messages,
&responses,
pConv->appdata_ptr) == PAM_SUCCESS)
{
// Check if we have a successful response
if (responses[0].resp_retcode == PAM_SUCCESS
&& responses[0].resp)
{
// Check if the username matches the name that we are expecting
if (strcmp(responses[0].resp, "CasaPrincipal") != 0)
{
LogError("Un-expected username, %s", responses[0].resp);
retStatus = PAM_USER_UNKNOWN;
}
}
else
{
LogError("Username not returned");
retStatus = PAM_CRED_INSUFFICIENT;
}
}
else
{
LogError("Conversation function error");
retStatus = PAM_AUTH_ERR;
}
}
else
{
LogError("Unable to obtain conversation structure");
retStatus = PAM_AUTH_ERR;
}
}
// Free conversation function response buffers if necessary
if (responses)
{
if (responses[0].resp)
free(responses[0].resp);
free(responses);
}
}
// Proceed with the authentication token check if we have not encountered any
// problems.
if (retStatus == PAM_SUCCESS)
{
struct pam_response *responses = NULL;
// Now obtain the authentication token.
if (pam_get_item(pamh, PAM_AUTHTOK, (void*) &pAuthToken) != PAM_SUCCESS
|| pAuthToken == NULL)
{
struct pam_conv *pConv;
// The authentication token has not been set, try to obtain it from the
// application through the use of the conversation function.
if (pam_get_item(pamh, PAM_CONV, (void*) &pConv) == PAM_SUCCESS)
{
struct pam_message msg;
struct pam_message *messages = &msg;
// Obtained the conversation structure, now query the conversation
// function for the authentication token.
msg.msg_style = PAM_PROMPT_ECHO_OFF;
if (pConv->conv(1,
(const struct pam_message **) &messages,
&responses,
pConv->appdata_ptr) == PAM_SUCCESS)
{
// Check if we have a successful response
if (responses[0].resp_retcode == PAM_SUCCESS
&& responses[0].resp)
{
// Set the authentication token with PAM
if (pam_set_item(pamh, PAM_AUTHTOK, responses[0].resp) == PAM_SUCCESS)
{
// Use the buffer returned by the caller as the authentication token
pAuthToken = responses[0].resp;
}
else
{
LogError("Unable to set the authentication token");
}
}
else
{
LogError("Token not returned");
}
}
else
{
LogError("Conversation function error");
}
}
else
{
LogError("Unable to obtain conversation structure");
}
}
// Check if we succeeded at obtaining the authentication token
if (pAuthToken)
{
CasaStatus casaStatus;
PrincipalIf *pPrincipalIf;
// Validate the token
casaStatus = ValidateAuthToken(pServicename,
pAuthToken,
strlen(pAuthToken),
&pPrincipalIf);
if (CASA_SUCCESS(casaStatus))
{
int buffLen;
// Assume success
retStatus = PAM_SUCCESS;
// Associate necessary environment variables with the PAM Handle
buffLen = 0;
casaStatus = pPrincipalIf->getIdentityId(pPrincipalIf,
NULL,
&buffLen);
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
{
char *pBuff;
// Allocate buffer to contain the Identity Id Environment Variable
pBuff = malloc(sizeof(CasaIdentityIdEnvVar) + buffLen);
if (pBuff)
{
// Start constructing the environment variable
memcpy(pBuff, CasaIdentityIdEnvVar, sizeof(CasaIdentityIdEnvVar) - 1);
// Read the value into our buffer
if (CASA_SUCCESS(pPrincipalIf->getIdentityId(pPrincipalIf,
pBuff + sizeof(CasaIdentityIdEnvVar) - 1,
&buffLen)))
{
// Now set the environment variable
if (pam_putenv(pamh, pBuff) != PAM_SUCCESS)
{
LogError("Unable to set identity id environment variable");
retStatus = PAM_SYSTEM_ERR;
}
// Also set the identity id as the username
if (pam_set_item(pamh, PAM_USER, pBuff + sizeof(CasaIdentityIdEnvVar) - 1) != PAM_SUCCESS)
{
LogError("Error setting the username");
}
}
else
{
LogError("Unable to obtain identity id");
retStatus = PAM_SYSTEM_ERR;
}
// Free allocated buffer
free(pBuff);
}
else
{
LogError("Buffer allocation failure");
retStatus = PAM_BUF_ERR;
}
}
else
{
LogError("Un-expected error obtaining identity id, %08X", casaStatus);
retStatus = PAM_SYSTEM_ERR;
}
if (retStatus == PAM_SUCCESS)
{
buffLen = 0;
casaStatus = pPrincipalIf->getSourceName(pPrincipalIf,
NULL,
&buffLen);
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
{
char *pBuff;
// Allocate buffer to contain the Identity Source Name Environment Variable
pBuff = malloc(sizeof(CasaIdentitySourceNameEnvVar) + buffLen);
if (pBuff)
{
// Start constructing the environment variable
memcpy(pBuff, CasaIdentitySourceNameEnvVar, sizeof(CasaIdentitySourceNameEnvVar) - 1);
// Read the value into our buffer
if (CASA_SUCCESS(pPrincipalIf->getSourceName(pPrincipalIf,
pBuff + sizeof(CasaIdentitySourceNameEnvVar) - 1,
&buffLen)))
{
// Now set the environment variable
if (pam_putenv(pamh, pBuff) != PAM_SUCCESS)
{
LogError("Unable to set identity source name environment variable");
retStatus = PAM_SYSTEM_ERR;
}
}
else
{
LogError("Unable to obtain identity source name");
retStatus = PAM_SYSTEM_ERR;
}
// Free allocated buffer
free(pBuff);
}
else
{
LogError("Buffer allocation failure");
retStatus = PAM_BUF_ERR;
}
}
else
{
LogError("Un-expected error obtaining identity source name, %08X", casaStatus);
retStatus = PAM_SYSTEM_ERR;
}
}
if (retStatus == PAM_SUCCESS)
{
buffLen = 0;
casaStatus = pPrincipalIf->getSourceUrl(pPrincipalIf,
NULL,
&buffLen);
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
{
char *pBuff;
// Allocate buffer to contain the Identity Source Url Environment Variable
pBuff = malloc(sizeof(CasaIdentitySourceUrlEnvVar) + buffLen);
if (pBuff)
{
// Start constructing the environment variable
memcpy(pBuff, CasaIdentitySourceUrlEnvVar, sizeof(CasaIdentitySourceUrlEnvVar) - 1);
// Read the value into our buffer
if (CASA_SUCCESS(pPrincipalIf->getSourceUrl(pPrincipalIf,
pBuff + sizeof(CasaIdentitySourceUrlEnvVar) - 1,
&buffLen)))
{
// Now set the environment variable
if (pam_putenv(pamh, pBuff) != PAM_SUCCESS)
{
LogError("Unable to set identity source url environment variable");
retStatus = PAM_SYSTEM_ERR;
}
}
else
{
LogError("Unable to obtain identity source url");
retStatus = PAM_SYSTEM_ERR;
}
// Free allocated buffer
free(pBuff);
}
else
{
LogError("Buffer allocation failure");
retStatus = PAM_BUF_ERR;
}
}
else
{
LogError("Un-expected error obtaining identity source url, %08X", casaStatus);
retStatus = PAM_SYSTEM_ERR;
}
}
if (retStatus == PAM_SUCCESS)
{
char *pBuff;
int enumHandle = 0;
int buff2Len;
while (retStatus == PAM_SUCCESS)
{
// Get attribute lengths
buffLen = buff2Len = 0;
casaStatus = pPrincipalIf->attributeEnumerate(pPrincipalIf,
&enumHandle,
NULL,
&buffLen,
NULL,
&buff2Len);
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
{
// Allocate buffer to contain the Identity attribute Environment Variable
pBuff = malloc(buffLen + 2 + buff2Len);
if (pBuff)
{
// Read the attribute into our buffer
if (CASA_SUCCESS(pPrincipalIf->attributeEnumerate(pPrincipalIf,
&enumHandle,
pBuff,
&buffLen,
pBuff + buffLen + 1, // This includes the NULL terminator
&buff2Len)))
{
// Finish constructing the environment variable string
*(pBuff + buffLen - 1) = '=';
*(pBuff + buffLen) = ' ';
// Now set the environment variable
if (pam_putenv(pamh, pBuff) != PAM_SUCCESS)
{
LogError("Unable to set identity attribute environment variable");
retStatus = PAM_SYSTEM_ERR;
}
}
else
{
LogError("Unable to obtain identity attribute");
retStatus = PAM_SYSTEM_ERR;
}
// Free allocated buffer
free(pBuff);
}
else
{
LogError("Buffer allocation failure");
retStatus = PAM_BUF_ERR;
}
}
else
{
// Check if we are done going through the attributes
if (CasaStatusCode(casaStatus) == CASA_STATUS_NO_MORE_ENTRIES)
{
// Done
break;
}
else
{
LogError("Un-expected error during attribute enumeration, %08X", casaStatus);
retStatus = PAM_SYSTEM_ERR;
}
}
}
}
// Release the principal interface instance
pPrincipalIf->releaseReference(pPrincipalIf);
}
else
{
LogError("Service %s failed to authenticate with status = %08X", pServicename, casaStatus);
retStatus = PAM_AUTH_ERR;
}
}
else
{
LogError("Unable to obtain authentication token");
retStatus = PAM_CRED_INSUFFICIENT;
}
// Free conversation function response buffers if necessary
if (responses)
{
if (responses[0].resp)
free(responses[0].resp);
free(responses);
}
}
}
else
{
LogError("Unable to obtain servicename");
retStatus = PAM_SYSTEM_ERR;
}
return retStatus;
}
/* ************************************************************************
* pam_sm_setcred()
*
* Service provider implementation for pam_setcred().
*
* This is a PAM authentication management function.
*
* This function is here just for completedness and to protect against
* PAM misconfiguration.
*
* ************************************************************************/
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return PAM_SUCCESS;
}
/* ************************************************************************
* pam_sm_acct_mgmt()
*
* Service provider implementation for pam_acct_mgmt().
*
* This is a PAM account management function.
*
* This function is here just for completedness and to protect against
* PAM misconfiguration.
*
* ************************************************************************/
PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return PAM_SUCCESS;
}
/* ************************************************************************
* pam_sm_chauthtok()
*
* Service provider implementation for pam_chauthtok().
*
* This is a PAM password management function.
*
* This function is here just for completedness and to protect against
* PAM misconfiguration.
*
* ************************************************************************/
PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return PAM_SUCCESS;
}
/* ************************************************************************
* pam_sm_open_session()
*
* Service provider implementation for pam_open_session().
*
* This is a PAM session management function.
*
* This function is here just for completedness and to protect against
* PAM misconfiguration.
*
* ************************************************************************/
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return PAM_SUCCESS;
}
/* ************************************************************************
* pam_sm_close_session()
*
* Service provider implementation for pam_close_session().
*
* This is a PAM session management function.
*
* This function is here just for completedness and to protect against
* PAM misconfiguration.
*
* ************************************************************************/
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return PAM_SUCCESS;
}
/* static module data */
#ifdef PAM_STATIC
struct pam_module _pam_casa_authtoken_modstruct = {
"pam_casa_authtoken",
pam_sm_authenticate,
pam_sm_setcred,
pam_sm_acct_mgmt,
pam_sm_chauthtok,
pam_sm_open_session,
pam_sm_close_session
};
#endif

View File

@@ -0,0 +1,32 @@
/***********************************************************************
*
* README for pamTest
*
***********************************************************************/
INTRODUCTION
pamTest is a PAM application which tests using CASA authentication tokens
for authentication.
CONFIGURATION
Place a copy of file testservice in the /etc/pam.d folder.
BUILDING APPLICATION
Execute script: make.sh.
RUNNING APPLICATION
Execute the following command: ./pamTest -s testService

View File

@@ -0,0 +1,2 @@
#!/bin/bash
gcc -o pamTest test.c -g -I"../../.." -I"../../../../include" -DN_PLAT_UNIX -L"../../../lib/Release" -lpam

View File

@@ -0,0 +1,520 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <getopt.h>
#include <errno.h>
#include <security/pam_appl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
//===[ Type definitions ]==================================================
typedef struct _AppUserData
{
char *pUserName;
char *pAuthToken;
} AppUserData, *PAppUserData;
//
// DbgTrace macro define
//
#define DbgTrace(LEVEL, X, Y) { \
if (LEVEL == 0) \
printf(X, Y); \
else if (DebugLevel >= LEVEL) \
printf(X, Y); \
}
//
// Socket Mapping definitions
//
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define LINGER struct linger
#define SOCKADDR_IN struct sockaddr_in
#define closesocket close
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Usage string
char usage[] = "\nPamTest: usage: -s serviceName [-D DebugLevel]\n";
// Debug Level
int DebugLevel = 3;
char *pServiceName = NULL;
//++=======================================================================
int
Converse(int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
int retStatus = PAM_SUCCESS;
int replies = 0;
struct pam_response *reply = NULL;
AppUserData *pAppUserData = (PAppUserData) appdata_ptr;
// Initialize output parameters
*resp = NULL;
// Check input parameters
if (num_msg <= 0 || appdata_ptr == NULL)
return PAM_CONV_ERR;
// Allocate enough space for the replies
reply = malloc(sizeof(struct pam_response) * num_msg);
if (!reply)
return PAM_CONV_ERR;
// Zero the reply buffer
memset(reply, 0, sizeof(struct pam_response) * num_msg);
for (replies = 0;
replies < num_msg && retStatus == PAM_SUCCESS;
replies++)
{
switch (msg[replies]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
// The caller wants the username
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = malloc(strlen(pAppUserData->pUserName) + 1);
if (reply[replies].resp)
strcpy(reply[replies].resp, pAppUserData->pUserName);
else
{
DbgTrace(0, "Converse- Buffer allocation failure\n", 0);
retStatus = PAM_CONV_ERR;
}
break;
case PAM_PROMPT_ECHO_OFF:
// The caller wants the authentication token
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = malloc(strlen(pAppUserData->pAuthToken) + 1);
if (reply[replies].resp)
{
strcpy(reply[replies].resp, pAppUserData->pAuthToken);
}
else
{
DbgTrace(0, "Converse- Buffer allocation failure\n", 0);
retStatus = PAM_CONV_ERR;
}
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
// Just return success
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = NULL;
break;
default:
// Un-expected
retStatus = PAM_CONV_ERR;
}
}
// Proceed based on the status
if (retStatus == PAM_SUCCESS)
{
*resp = reply;
}
else
{
// Free buffers allocated for the reply
for (replies = 0;
replies < num_msg && retStatus == PAM_SUCCESS;
replies++)
{
if (reply[replies].resp != NULL)
free(reply[replies].resp);
}
free(reply);
}
return retStatus;
}
//++=======================================================================
int
ReadLineIntoBuffer(int connSock, char *pBuffer)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
int i = 0;
char c;
int bytesReceived = 0;
DbgTrace(2, "ReadLineIntoBuffer- Start\n", 0);
// Receive the line
while ((bytesReceived = recv(connSock, &c, 1, 0)) == 1)
{
if (c == '\n')
break;
else
{
pBuffer[i] = c;
i ++;
}
}
// Check for a socket error
if (bytesReceived == 0)
{
DbgTrace(0, "ReadLineIntoBuffer- Socket error\n", 0);
}
DbgTrace(2, "ReadLineIntoBuffer- End, lineLength = %d\n", i);
return i;
}
//++=======================================================================
void
ProcessConnection(int connSock)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
char userName[] = "CasaPrincipal";
char token[4096] = {0};
char helloString[100] = {0};
AppUserData appUserData = {userName, token};
struct pam_conv conv = {Converse, &appUserData};
pam_handle_t *pamh;
int pam_status;
DbgTrace(1, "ProcessConnection- Start\n", 0);
// We have received a connection
printf("\n\nConnection received\n");
// Receive the token
if (ReadLineIntoBuffer(connSock, token) == 0)
{
DbgTrace(0, "ProcessConnection- Error receiving token\n", 0);
goto exit;
}
//printf("Token received = %s\n", token);
// We obtained authentication token credentials to authenticate
// to the service, now verify the credentials using PAM_Authenticate.
//
// Open a PAM Handle
pam_status = pam_start(pServiceName, userName, &conv, &pamh);
if (pam_status == PAM_SUCCESS)
{
// Now authenticate the user
pam_status = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK);
if (pam_status == PAM_SUCCESS)
{
char **pam_envlist;
char **pam_env;
char *pUsername;
DbgTrace(1, "ProcessConnection- pam_authenticate success\n", 0);
printf("Authentication succeeded\n");
printf("The DUDE is cool\n");
// Get the identity information about the DUDE
// Notice that the username may have been updated during the authentication process
if (pam_get_item(pamh, PAM_USER, (void*) &pUsername) == PAM_SUCCESS
&& pUsername != NULL)
{
printf("The username of the authenticated identity is %s\n", pUsername);
}
else
{
DbgTrace(0, "ProcessConnection- pam_get_item did not return the username\n", 0);
}
// Show identity information obtained during the authentication process and maintained
// as PAM environment variables.
pam_envlist = pam_getenvlist(pamh);
if (pam_envlist != NULL)
{
// Display the environment variables and free the memory associated
// with them.
for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env)
{
printf("%s\n", *pam_env);
free(*pam_env);
}
free(pam_envlist);
}
else
{
DbgTrace(0, "ProcessConnection- pam_getenvlist did not return any data\n", 0);
}
}
else
{
DbgTrace(0, "ProcessConnection- pam_authenticate failure, error = %s\n", pam_strerror(pamh, pam_status));
printf("The DUDE is a fake\n");
}
// Close the PAM Handle
pam_end(pamh, pam_status | PAM_DATA_SILENT);
}
else
{
DbgTrace(0, "ProcessConnection- pam_start failure, status = %08X\n", pam_status);
}
exit:
DbgTrace(1, "ProcessConnection- End\n", 0);
}
//++=======================================================================
void
ExecuteTests(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
int connSock;
int listenSock;
struct sockaddr_in localAddr = {0};
struct sockaddr_in boundAddr = {0};
struct sockaddr_in remoteAddr = {0};
struct linger linger_opt = {1, 15};
int on = 1;
socklen_t addrLen = sizeof(struct sockaddr_in);
DbgTrace(1, "ExecuteTests- Start\n", 0);
// Open listen socket
listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSock != INVALID_SOCKET)
{
// Setup the local address structure
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// Set the SO_REUSEADDR option on the socket to avoid
// problems in case of a re-start.
setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
// Bind socket
if (!bind(listenSock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in)))
{
// Display the local address information
if (getsockname(listenSock,
(struct sockaddr*) &boundAddr,
&addrLen) != SOCKET_ERROR)
{
printf("Listen port = %d\n", boundAddr.sin_port);
// Now start linstening for connections
if (listen(listenSock, SOMAXCONN) != SOCKET_ERROR)
{
// Loop accepting connections
while (1)
{
addrLen = sizeof(remoteAddr);
connSock = accept(listenSock,
(struct sockaddr*) &remoteAddr,
&addrLen);
if (connSock != INVALID_SOCKET)
{
ProcessConnection(connSock);
// Close the connection socket
closesocket(connSock);
}
else
{
DbgTrace(0, "ExecuteTests- - Accept failed, error = %08X\n", errno);
break;
}
}
}
else
{
DbgTrace(0, "ExecuteTests- Unable to start listening, error = %d", errno);
}
}
else
{
DbgTrace(0, "ExecuteTests- Unable to obtain local address information, error = %d", errno);
}
}
else
{
DbgTrace(0, "ExecuteTests- Unable to bind socket, error = %d", errno);
}
// Close the listen socket
closesocket(listenSock);
}
else
{
DbgTrace(0, "ExecuteTests- Unable to open socket, error = %d\n", errno);
}
DbgTrace(1, "ExecuteTests- End\n", 0);
}
//++=======================================================================
int
main(
int argc,
char* argv[])
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int optionsSpecified = 0;
bool doneScanning = false;
bool invalidOption = false;
int option;
printf("**** server auth_token test ****\n");
// Scan through the options specified
while (!doneScanning)
{
opterr = 0;
option = getopt(argc, argv, "s:D:");
// Proceed based on the result
switch (option)
{
case 'D':
// Set the debug level
printf("DebugLevel = %s\n", optarg);
DebugLevel = atoi(optarg);
optionsSpecified++;
break;
case 's':
// Set the service name
printf("Service name = %s\n", optarg);
pServiceName = optarg;
optionsSpecified++;
break;
case '?':
// Invalid option detected
doneScanning = true;
invalidOption = true;
break;
default:
// Done scanning
doneScanning = true;
break;
}
}
// Do some sanity checking
if (!invalidOption
&& pServiceName != NULL)
{
ExecuteTests();
}
else
{
// Invalid option detected
printf(usage, argv[0]);
}
return 0;
} /*-- main() --*/

View File

@@ -0,0 +1,6 @@
#%PAM-1.0
auth required pam_casaauthtok.so U
account required pam_casaauthtok.so
password required pam_casaauthtok.so
session required pam_casaauthtok.so